Iteratives Hashing gibt verschiedene Werte in Python und Java zurück

Ich versuche, ein Python (2.7) Skript an Java zu portieren. Es iteriert einen Sha256 Hash mehrmals, aber sie enden mit verschiedenen Ergebnissen. Ich habe das erste Mal bemerkt, dass sie das gleiche Ergebnis zurückgeben, aber von dort an unterscheidet es sich.

Hier ist die Python-Implementierung:

import hashlib def to_hex(s): print " ".join(hex(ord(i)) for i in s) d = hashlib.sha256() print "Entry:" r = chr(1) to_hex(r) for i in range(2): print "Loop", i d.update(r) r = d.digest() to_hex(r) 

Und in Java:

 import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class LoopTest { public static void main(String[] args) { MessageDigest d; try { d = MessageDigest.getInstance("SHA-256"); } catch (NoSuchAlgorithmException e) { System.out.println("NoSuchAlgorithmException"); return; } System.out.println("Entry:"); byte[] r = new byte[] {1}; System.out.println(toHex(r)); for(int i = 0; i < 2; i++) { System.out.printf("Loop %d\n", i); d.update(r); r = d.digest(); System.out.println(toHex(r)); } } private static String toHex(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length); for (byte b: bytes) { sb.append(String.format("0x%02X ", b)); } return sb.toString(); } } 

Die Ausgänge sind für python:

 $ python looptest.py Entry: 0x1 Loop 0 0x4b 0xf5 0x12 0x2f 0x34 0x45 0x54 0xc5 0x3b 0xde 0x2e 0xbb 0x8c 0xd2 0xb7 0xe3 0xd1 0x60 0xa 0xd6 0x31 0xc3 0x85 0xa5 0xd7 0xcc 0xe2 0x3c 0x77 0x85 0x45 0x9a Loop 1 0x98 0x1f 0xc8 0xd4 0x71 0xa8 0xb0 0x19 0x32 0xe3 0x84 0xac 0x1c 0xd0 0xa0 0x62 0xc4 0xdb 0x2c 0xe 0x13 0x58 0x61 0x9a 0x83 0xd1 0x67 0xf5 0xe8 0x4e 0x6a 0x17 

Und für Java:

 $ java LoopTest Entry: 0x01 Loop 0 0x4B 0xF5 0x12 0x2F 0x34 0x45 0x54 0xC5 0x3B 0xDE 0x2E 0xBB 0x8C 0xD2 0xB7 0xE3 0xD1 0x60 0x0A 0xD6 0x31 0xC3 0x85 0xA5 0xD7 0xCC 0xE2 0x3C 0x77 0x85 0x45 0x9A Loop 1 0x9C 0x12 0xCF 0xDC 0x04 0xC7 0x45 0x84 0xD7 0x87 0xAC 0x3D 0x23 0x77 0x21 0x32 0xC1 0x85 0x24 0xBC 0x7A 0xB2 0x8D 0xEC 0x42 0x19 0xB8 0xFC 0x5B 0x42 0x5F 0x70 

Was könnte der Grund für diesen Unterschied sein?

Bearbeiten:

Danke für die Antworten @dcsohl und @Alik Ich verstehe den Grund jetzt. Da ich das Python-Skript auf Java portiere, musste ich den Python so halten, wie es ist, also habe ich das Java-Programm so modifiziert:

 byte[] r2 = new byte[]{}; for(int i = 0; i < 2; i++) { System.out.printf("Loop %d\n", i); d.update(r); r2 = d.digest(); System.out.println(toHex(r2)); byte[] c = new byte[r.length + r2.length]; System.arraycopy(r, 0, c, 0, r.length); System.arraycopy(r2, 0, c, r.length, r2.length); r = c; } 

2 Solutions collect form web for “Iteratives Hashing gibt verschiedene Werte in Python und Java zurück”

Die beiden Sprachen laufen update() und digest() anders.

Die Pythonendokumentation für update() sagt

Aktualisieren Sie das Hash-Objekt mit dem String arg. Wiederholte Anrufe entsprechen einem einzigen Aufruf mit der Verkettung aller Argumente: m.update(a); m.update(b) m.update(a); m.update(b) entspricht m.update(a+b) .

Ich habe das getestet, indem sha256sum Befehl shell sha256sum .

 echo -n '\0x01\0x4b\0xf5\0x12\0x2f\0x34\0x45\0x54\0xc5\0x3b\0xde\0x2e\0xbb\0x8c\0xd2\0xb7\0xe3\0xd1\0x60\0xa\0xd6\0x31\0xc3\0x85\0xa5\0xd7\0xcc\0xe2\0x3c\0x77\0x85\0x45\0x9a' | sha256sum 981fc8d471a8b01932e384ac1cd0a062c4db2c0e1358619a83d167f5e84e6a17 *- 

Sie haben mit \ 0x01 angefangen, also das ist das erste Byte, und dann sind die restlichen Bytes der Hash von 0x01. Der resultierende Hash entspricht Ihrer Python-Ausgabe.

Nun schau dir das an – ich habe die erste \ 0x01 ausgelassen und habe den Hash zurück – es passt zu deiner Java-Ausgabe.

 > echo -n '\0x4b\0xf5\0x12\0x2f\0x34\0x45\0x54\0xc5\0x3b\0xde\0x2e\0xbb\0x8c\0xd2\0xb7\0xe3\0xd1\0x60\0xa\0xd6\0x31\0xc3\0x85\0xa5\0xd7\0xcc\0xe2\0x3c\0x77\0x85\0x45\0x9a' | sha256sum 9c12cfdc04c74584d787ac3d23772132c18524bc7ab28dec4219b8fc5b425f70 *- 

Aber warum? Sollte nicht die erste \ 0x01 enthalten sein? Es wäre, außer dass die javadoc für digest() sagt:

Vervollständigt die Hash-Berechnung durch die Durchführung von Endoperationen wie Polsterung. Der Digest wird nach dem Aufruf zurückgesetzt.

Also dein Anfang \ 0x01 wird gelöscht, wenn du digest() in Java nennst und du einfach den alten Digest ohne den ersten \ 0x01 Eintrag verdaust.

In Java d.digest kehrt die Nachricht Digest zurück und setzt den Digest am Ende zurück.

In Python d.digest wird kein Digest zurückgesetzt. So werden wiederholte Anrufe d.update tatsächlich verkettet, was an früheren Anrufen weitergegeben wurde

Sie können einfach d = hashlib.sha256() in die Schleife setzen

 import hashlib def to_hex(s): print " ".join(hex(ord(i)) for i in s) print "Entry:" r = chr(1) to_hex(r) for i in range(2): print "Loop", i d = hashlib.sha256() d.update(r) r = d.digest() to_hex(r) 

Um die gleichen Ergebnisse wie Sie Java-Programm zu bekommen

 Entry: 0x1 Loop 0 0x4b 0xf5 0x12 0x2f 0x34 0x45 0x54 0xc5 0x3b 0xde 0x2e 0xbb 0x8c 0xd2 0xb7 0xe3 0xd1 0x60 0xa 0xd6 0x31 0xc3 0x85 0xa5 0xd7 0xcc 0xe2 0x3c 0x77 0x85 0x45 0x9a Loop 1 0x9c 0x12 0xcf 0xdc 0x4 0xc7 0x45 0x84 0xd7 0x87 0xac 0x3d 0x23 0x77 0x21 0x32 0xc1 0x85 0x24 0xbc 0x7a 0xb2 0x8d 0xec 0x42 0x19 0xb8 0xfc 0x5b 0x42 0x5f 0x70 
Python ist die beste Programmiersprache der Welt.