Author

Topic: Need help on dealing with compressed keys (Read 4140 times)

cjp
full member
Activity: 210
Merit: 124
October 18, 2014, 08:59:25 AM
#4
Thanks.

Here is my implementation in Python:
https://github.com/cornwarecjp/amiko-pay/commit/40ad1f844bad6c74223d13bc71a4812e8b24e9db

Interestingly, no changes to other parts of the software were needed. They just need to pass key data to this class, and this class will figure out the distinction between compressed/uncompressed automatically.
sr. member
Activity: 467
Merit: 267
October 18, 2014, 07:57:10 AM
#3
Glad you figured it out. If you'd like some background info, here's a thread explaining the subtle differences.

https://bitcointalksearch.org/topic/compressed-vs-uncompresed-private-keys-129652
cjp
full member
Activity: 210
Merit: 124
October 18, 2014, 07:12:51 AM
#2
For those of you with the same problem: I think I've figured it out. Apparently, private keys that correspond to compressed public keys can be recognized because Bitcoin adds a single (unused) byte to them (value: 0x01), making them 33 bytes long instead of 32 bytes. See CBitcoinSecret in base58.h. Somehow the appended byte causes the first Base58 character to become 'L' instead of '5' (probably there is some endianness inversion in the pipeline).

For the exact differences in behavior, see key.cpp. The essence is in CKey::SetCompressedPubKey, which calls EC_KEY_set_conv_form. Compressed public keys can be recognized because they're smaller (they're 33 bytes) than non-compressed keys. The corresponding Bitcoin addresses can not be distinguished from each other, since they're secure hashes of public keys.
cjp
full member
Activity: 210
Merit: 124
October 18, 2014, 05:51:55 AM
#1
I made a piece of software which
* retrieves the private key of a given address with the dumpprivkey command
* decodes the private key according to the Wallet Import Format
* gives the private key to OpenSSL (based on what the Bitcoin source code does), and gets the corresponding public key
* encodes the public key to a Bitcoin address
* checks whether given and resulting Bitcoin addresses are the same.

This works fine for some keys, but not for others. Further investigation showed that it works for keys generated with an old version of BOTG (imported into Bitcoin-Qt), and fails for keys generated by Bitcoin-Qt itself (version 0.8.6). The addresses for which it works have a private key (as returned by dumpprivkey) that starts with a '5', and when it doesn't work, it starts with an 'L'. I've read that the ones that start with an 'L' correspond to "compressed public keys", so that's probably what causes the problem.

Note that my code did not generate any errors: it just returned an address that was different from the original. Among other things, this means the version number in the private key format is the same.

I couldn't find good documentation on how to go from private key to public key, either for compressed or for non-compressed keys, so I'll use the Bitcoin source code again to help me. I'd appreciate it if somebody could document this (also, just in case I can't figure it out from the code). Apparently, just saying "this is the private key, and this is the ECDSA curve you should use" is not enough.
Jump to: