Fix some erroneous statements in the description of the math used for encryption/decryption of EC-Multiplied keys/addresses
Update bip-0038.mediawiki #29
pull MidnightLightning wants to merge 4 commits into bitcoin:master from MidnightLightning:patch-1 changing 1 files +11 −5-
MidnightLightning commented at 10:13 PM on March 5, 2014: contributor
- cscott cross-referenced this on Mar 6, 2014 from issue Fix typo for size of derivedhalf1 and derivedhalf2 by cscott
-
cscott commented at 7:45 PM on March 7, 2014: none
The UTF-8 stuff needs some fixes too. @MidnightLightning would you be willing to add those fixes into your patch set?
In particular, it should be explicitly specified that the password is converted to Unicode Normalization Form C before being encoded in UTF-8. See http://www.unicode.org/faq/normalization.html and http://tools.ietf.org/html/rfc3987. And the set of test vectors should include:
- A sequence normalized with NFC.
- A character normally encoded using UTF-16 surrogates, to demonstrate that the surrogates should be replaced by the proper code point (especially relevant for javascript implementations). Ie, the encoding should be UTF-8, not CESU-8.
- Inclusion of a password with an embedded null, to demonstrate that the null is encoded as a zero byte, not Modified UTF-8.
An example of such an input passphrase is: "\u03D2\u0301\u0000\U10400\U1F4A9" which should get encoded as '\xcf\x93\x00\xf0\x90\x90\x80\xf0\x9f\x92\xa9' (13 bytes) before being further processed.
EDIT: breaking down the parts of the suggested passphrase:
- U+03D2 U+0301 which should get normalized to U+03D3 under NFC (http://www.unicode.org/faq/normalization.html#6)
- U+0000 which should get encoded as 0x00 (Modified UTF-8 would serialize this as 0xC0 0x80)
- U+10400 which is an astral character which is represented in UTF-16 (Java/JavaScript) as U+D801 U+DC00 but which should not be encoded as six bytes (as CESU-8 would do; see https://en.wikipedia.org/wiki/CESU-8#Examples)
- U+1F4A9 which repeats the "astral characters" test as http://mathiasbynens.be/notes/javascript-unicode#poo-test suggests
Sanity check:
$ python >>> import unicodedata >>> unicodedata.normalize('NFC', u'\u03D2\u0301\u0000\U00010400\U0001F4A9').encode('utf-8') '\xcf\x93\x00\xf0\x90\x90\x80\xf0\x9f\x92\xa9' -
MidnightLightning commented at 8:10 PM on March 7, 2014: contributor
Sure, I can add that in. Can you generate the full test vector for that input passphrase, and I'll do the same to make sure they agree?
-
cscott commented at 8:39 PM on March 7, 2014: none
I don't actually have a full bip38 implementation; I just have https://github.com/cscott/bip38-cracker that I've been hacking on (for a reddit contest). So it's actually a little easier for me to verify a test vector than to generate one. So if you generate and post a test vector I can plug it in quick and check it out.
Otherwise it will take me a little longer, as I'll have to write (or carefully audit) a bit of code to do the generation. But I'll can do it if necessary.
-
MidnightLightning commented at 4:01 PM on March 10, 2014: contributor
All right, can you check me on this:
- Password of
\u03D2\u0301\u0000\U00010400\U0001F4A9; GREEK UPSILON WITH HOOK, COMBINING ACUTE ACCENT, NULL, DESERET CAPITAL LETTER LONG I, PILE OF POO - Unencrypted key to encrypt:
5Jajm8eQ22H3pGWLEVCXyvND8dQZhiQhoLJNKjYXk9roUFTMSZ4 - Public address of private key:
16ktGzmfrurhbhi6JGqsMWf7TyqK9HNAeF - Encrypted key:
6PRW5o9FLp4gJDDVqJQKJFTpMvdsSGJxMYHtHaQBF3ooa8mwD69bapcDQn
Do you get that same Encrypted Key as I do? I'm on a Mac and having problems getting Casascius' Address Utility (which is the reference implementation cited in the BIP) to allow proper Unicode character entry on my system (running with Mono); I'll see if I can verify that on a PC if I get a chance. But for this test, I'm using a Node.js Javascript implementation, so the input password is actually using the related surrogate pairs to define the string literal being input into the function and the unorm library to perform the NFC normalization:
var pass = new Buffer(unorm.nfc("\u03D2\u0301\u0000\uD801\uDC00\uD83D\uDCA9"), 'utf8'); console.log(pass.toString('hex')); // cf9300f0909080f09f92a9 - Password of
- laanwj cross-referenced this on Apr 12, 2014 from issue Update bip-0038.mediawiki by voisine
-
voisine commented at 8:28 AM on April 13, 2014: contributor
I added this test case to my own obj-c bip38 implementation and it passed: https://github.com/voisine/zincwallet/blob/a334859dbd720e1293509f30d98b69324670cdc9/ZincWalletTests/ZincWalletTests.m#L177
Also, I independently found the same typos from your commit and included fixes in pull request #47 before I saw this pr.
-
laanwj commented at 9:11 AM on April 13, 2014: member
This needs a rebase to the current version before it can be merged. If the changes are already in the document through the other patch, we can close it.
-
4a85b38916
Update bip-0038.mediawiki
Fix some erroneous statements in the description of the math used for encryption/decryption of EC-Multiplied keys/addresses
-
Add test case for UTF8 NFC normalization a0d6bb3433
-
Add normalization note on test case ab85705d40
-
MidnightLightning commented at 9:41 PM on April 15, 2014: contributor
Okay, rebased this update. There's some discrepancy between
ownerentropyvsownersalt; you thought the derivation ofpassfactorwas incorrect, while I thought theseedbkey derivation was incorrect. I'll double-check my code, and can you check yours to make sure the proper use of entropy/salt is used in that definition?Added in the UTF normalization test case; I haven't tried it with lot/sequence numbers, nor figured out what the private key would be in hex format, so doesn't quite match the syntax of the other test cases yet; if anyone's able to provide them before I have a chance to figure them out, I'll add them in.
-
Attempt to put the actual characters in the source file d69abd64e1
-
voisine commented at 9:39 PM on April 16, 2014: contributor
I changed step 2 in ec multiply decryption in order for passfactor derivation to match passfactor creation in step 4 of intermediate code generation.
the decryption key for seedb is derivedhalf2, which is generated using passpoint, addresshash, and ownerentropy, so your edit is also correct.
-
voisine commented at 5:17 PM on June 26, 2014: contributor
ACK, this is a good edit. I'll make another PR to add mention about the need for unicode normalization of the password.
- laanwj referenced this in commit 27bfe7f28e on Jun 26, 2014
- laanwj merged this on Jun 26, 2014
- laanwj closed this on Jun 26, 2014
- real-or-random referenced this in commit 9fc18ce733 on Aug 10, 2022
- guggero referenced this in commit 5da9e72e6b on Sep 29, 2022