BIP39 japanischer Mnemonik-Vektoreinheiten-Testprozess

Es gibt einen JSON für Komponententests japanischer Zeichen , den ich mit Python validieren möchte, insbesondere mit diesem Fork von pybitcointools , der über bip39-Funktionalität verfügt.

Unit-Tests von Trezors Python-Mnemonik-Testvektoren funktionieren gut (in Python 2.7 IME), dies ist jedoch unkompliziert, da es keine Normalisierung der Unicode-Dialektik und dergleichen gibt, da alle Mnemoniken in Kleinbuchstaben Englisch sind.

Die japanischen Felder sind:

  1. Entropie (hex)
  2. Mnemonik (Japanisch)
  3. Passwort (Japanisch, scheint für alle Tests gleich zu sein)
  4. Seed (hex, 64 Bytes)
  5. xprv

Also entropySamen mnemonic (bip39?), dann mnemonic| passwordhasht zu Seed; Seedfungiert dann als Hauptschlüssel für das bip32 xprv? (korrigiert mich, wenn ich falsch liege!?)

Also vorausgesetzt, es ist so einfach...

  1. Wie wird der japanische Unicode-Text "normalisiert"? (Ist es nur die NKFD-Unicode-Normalisierung, die Electrum 2.0 tut?)
  2. Was bedeutet "normal" für Japaner?

Antworten (1)

Also Entropiesamen mnemonisch (bip39?), dann mnemonisch | Passwort-Hashes zu Seed; Seed fungiert dann als Hauptschlüssel für das bip32 xprv? (korrigiert mich, wenn ich falsch liege!?)

Das klingt ungefähr richtig. Der größte Teil des Prozesses ist in BIP-39 ausführlich beschrieben .

  1. Der Entropie wird ein SHA-256 entnommen, und die ersten entropy_len_in_bits / 32Bits dieses Hashs werden an das Ende der Entropie angehängt. Die resultierende Entropiebitfolge ist in 11-Bit-lange Stücke teilbar (es ist keine ganze Zahl von Bytes mehr).
  2. Jeder 11-Bit-Chunk wird in eines von 2 11 mnemonischen Wörtern umgewandelt.
  3. Die Wörter werden durch Leerzeichen verbunden. Für Anzeigezwecke auf Japanisch sollten dies Unicode IDEOGRAPHIC SPACEs sein, '\u3000'. Wenn die Mnemonik dem Benutzer nicht angezeigt werden muss, können sie "normale" LEERZEICHEN ( '\u0020') sein.
  4. Der mnemonische Satz ist Unicode-normalisiert in NFKD-Form. Dadurch werden alle IDEOGRAPHIC SPACEs in SPACEs umgewandelt. Es ändert auch einige Zeichen in einigen der mnemonischen Wörter, daher kann dieser Schritt nicht übersprungen werden. (Die Frage Was ist NFKD-Normalisierung? ist ein ganz anderes Thema, das meiner Meinung nach an anderer Stelle wahrscheinlich am besten gestellt wird ....)
  5. Der mnemonische Satz wird per UTF-8-Kodierung in Bytes umgewandelt .
  6. Der binäre Seed wird als PBKDF2 HMAC SHA512 berechnet (key= "mnemonic" | passphrase, data=utf8_mnemonic, iterations=2048, out_bytes_length=64). Die Passphrase kann die leere Zeichenfolge sein. Es muss zuerst die gleichen Schritte 4 und 5 durchlaufen wie die Mnemonik.
  7. (Dieser Teil wird AFAIK nirgendwo detailliert beschrieben) Der Master Extended Private Key wird erstellt, indem die ersten 32 Bytes des binären Seeds als privater Schlüssel und die letzten 32 Bytes als Kettencode verwendet werden.

Ist es nur die NKFD-Unicode-Normalisierung, die Electrum 2.0 durchführt?

Electrum 2.x verwendet zwar die NFKD-Normalisierung, führt aber auch zusätzliche Schritte aus, z. B. das Entfernen von Leerzeichen zwischen japanischen Wörtern nach Schritt 4. Es verwendet auch eine andere Schlüsselzeichenfolge in Schritt 6 und einen völlig anderen Prozess vor Schritt 4. Siehe dies Antwort für eine Implementierung der Mnemonik-Wörter-zu-Seed-Prozedur von Electrum 2.x in Python.

Danke für die Antwort. Ich habe Lücken darin, wie UTF-8 hineinpasst, obwohl ich ziemlich gut verstehe, was NKFD tut. Warum nicht einfach Unicode direkt codieren? Außerdem verstehe ich den ideografischen Raum, denke ich (\u3000 ist das japanische "Äquivalent" von \u0020). Es war tatsächlich Electrum 2.0s Implementierung der Seed-Vorbereitung , die mich verwirrte. Das ist wirklich seltsames Elektrum, das an solch obskuren Orten abgelenkt wird
Vergiss das. Sie können Unicode-4-Byte-Codepunkte nicht so gut codieren wie UTF8, oder?
@WizardOfOzzie Unicode-Strings sind einfach Folgen von Ganzzahlen im Bereich [0,0x10FFFF]. Bevor Sie es hashen können, müssen Sie es in eine Folge von Bytes konvertieren. Eine einfache Möglichkeit besteht darin, einfach jedes 4-Byte-Int zu nehmen und diese Bytes so zu verwenden, wie sie sind (UTF-32LE-Codierung), aber dies ist aus Platzgründen unzulänglich (wenn man bedenkt, dass Englisch nur 1 Byte pro Zeichen benötigt). UTF-8 ist komplizierter, aber meistens platzsparender.
@WizardOfOzzie Stimmte zu, dass die Normalisierung von Electrum 2.x viel komplexer ist, aber es ist hilfreich, die Wahrscheinlichkeit eines Verlusts durch falsch geschriebene Mnemonik zu minimieren, da keine bestimmten Wortlisten vorhanden sind. (Und die Anforderung von BIP-39 nach bestimmten Wortlisten war etwas, womit der Entwickler von Electrum 2.x wirklich nicht einverstanden war.)
Sieht das richtig aus?norm = lambda d: (' '.join(unicodedata.('NFKD', unicode(d)).split('\u3000'))).encode('utf-8')
Angenommen d, es handelt sich um einen mnemonischen Satz vom Typ Python2 oder um einen Unicode? Ich würde für die meisten Sprachen so etwas denken (anders für Chinesisch, das möglicherweise keine Leerzeichen enthält d): norm = lambda d: (u' '.join(unicodedata.normalize('NFKD', unicode(d)).split())).encode('utf-8')(Ich habe das fehlende "Normalisieren" hinzugefügt und die Aufteilung geändert, um alle Leerzeichen aufzuteilen). Beachten Sie, dass BIP-39 erfordert, dass Sie die Prüfsumme überprüfen, wenn Sie Eingaben von einem Benutzer akzeptieren.
Thx, ich werde es jetzt versuchen. Hmmm, unter der Annahme, dass py 2/3 ist, also sagen wir, sowohl Unicode als auch str. Ja, ich kenne mich mit bip39 ziemlich gut aus, also behauptet meine mn2hex-Funktion check_bip39
Ich habe alle Komponententests zum Laufen gebracht *mit Ausnahme des Vergleichs von bip39_hex_to_mnmit VECTOR['mnemonic'], da die Funktion ein Standard-Leerzeichen (dh \u0020) zurückgibt, während die Testvektoren verwenden \u3000. \u3000Electrum (2.x) löst das Problem des ideografischen Leerzeichens ( ), indem alle CJK-Wörter ohne Leerzeichen verkettet werden. Siehe github.com/simcity4242/pybitcointools/blob/master/… (Ich habe es nur zum Arbeiten mit u' '.join(v['mnemonic'].split()), obwohl es nur sein solltev['mnemonic']
Tangential verwandt, warum haben die Wortlisten für Englisch und Japanisch das richtige Format (jedes Wort ist ein Unicode-Objekt, das aus Unicode-Zeichen besteht), während die Wörter Spanisch, Chinesisch und Französisch ( github.com/simcity4242/pybitcointools/blob/master/bitcoin /… und unten) haben Wortlisten dieses Format: '\xe7\x9a\x84'?
@WizardOfOzzie Nach meiner Lektüre des Standards sollte bip39_hex_to_mn () mnemonische Zeichen mit ideografischen Leerzeichen für Japanisch zurückgeben, sodass das Ergebnis sowohl für Anzeigezwecke als auch zur Berechnung des binären Seeds verwendet werden kann. Wie es derzeit geschrieben steht, ist der zurückgegebene Wert nur für den letzteren Zweck geeignet. Angesichts dieser Änderung könnten Sie den "Hack" entfernen, den Sie an TestBIP39JAP vorgenommen haben.
@WizardOfOzzie In Bezug auf Ihre Wortlisten stimme ich Ihnen zu, dass ich aus Gründen der Konsistenz vorziehen würde, dass sie alle Unicode-Objekte sind. Woher hast du deine Wortlisten? Vielleicht sollten Sie die offiziellen BIP-39-Wortlisten-Textdateien direkt aus dem Repo herunterladen und sie mit etwas wie with io.open(language+'.txt', encoding='utf_8_sig') as words_file: words[language] = tuple(word.strip() for word in words_file).
Ich habe sie mit iPython geladen und dann die Variable mit %store var >> file.py. Ich werde beide Empfehlungen aktualisieren, danke!