Author

Topic: Why is private key in wallet 214 bytes? (Read 229 times)

member
Activity: 61
Merit: 15
March 29, 2018, 07:43:48 PM
#5
I see, the 214 bytes is made of version + private key + parameters + public key.
Another question, when the wallet is encrypted, the ckey entry for private keys only contains 48bytes, which is 32 bytes private key + 16 bytes IV, is that right?
Yes

Why the different db store strategy?
For compatibility reasons. Earlier versions of Bitcoin Core (including the original Bitcoin 0.1.0) used OpenSSL to do key operations. When keys were written to disk, they used the OpenSSL format which includes all of this extra data. Later, when key encryption was introduced, it was decided that for encrypted keys we could use a different format (since encrypted keys are already backwards incompatible with earlier versions). So for encrypted private keys, we only store what we need, not the full extra stuff. We could bump the wallet version and change the unencrypted key storage format to just be the private key, but no one has bothered to do that and it really isn't all that important.

Great to know, thanks for answering!
staff
Activity: 3458
Merit: 6793
Just writing some code
March 29, 2018, 10:39:47 AM
#4
I see, the 214 bytes is made of version + private key + parameters + public key.
Another question, when the wallet is encrypted, the ckey entry for private keys only contains 48bytes, which is 32 bytes private key + 16 bytes IV, is that right?
Yes

Why the different db store strategy?
For compatibility reasons. Earlier versions of Bitcoin Core (including the original Bitcoin 0.1.0) used OpenSSL to do key operations. When keys were written to disk, they used the OpenSSL format which includes all of this extra data. Later, when key encryption was introduced, it was decided that for encrypted keys we could use a different format (since encrypted keys are already backwards incompatible with earlier versions). So for encrypted private keys, we only store what we need, not the full extra stuff. We could bump the wallet version and change the unencrypted key storage format to just be the private key, but no one has bothered to do that and it really isn't all that important.
member
Activity: 61
Merit: 15
March 29, 2018, 02:56:00 AM
#3
Those additional bytes are for the elliptic curve parameters and the full public key. This format is described in http://www.secg.org/sec1-v2.pdf section C.4

I see, the 214 bytes is made of version + private key + parameters + public key.
Another question, when the wallet is encrypted, the ckey entry for private keys only contains 48bytes, which is 32 bytes private key + 16 bytes IV, is that right? Why the different db store strategy?
staff
Activity: 3458
Merit: 6793
Just writing some code
March 29, 2018, 01:42:03 AM
#2
Those additional bytes are for the elliptic curve parameters and the full public key. This format is described in http://www.secg.org/sec1-v2.pdf section C.4
member
Activity: 61
Merit: 15
March 27, 2018, 10:43:58 PM
#1
Trying to examine and dump the wallet file, and found out the private key is stored as 214 bytes, rather than 32 bytes, this is true for every key in the file, for example, an raw entry in the wallet file looks like this:

Code:
Key: type prefix + pubkey

key 02004cc49d5e1dd6fdf3148cc4004bcf2c6f715c5b61a39f9cf93d8ea4d161652b

Value: private key + hash

3081d30201010420c481b015db511aaf9729855e94c7ac9f990a664d76c6bb487af5f4aa22aa387ba08185308182020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101a12403220002004cc49d5e1dd6fdf3148cc4004bcf2c6f715c5b61a39f9cf93d8ea4d161652b 38ab424074511b183cd10429725ea312bcf5143d6cc71b8041d678ace5a71779

----------------c481b015db511aaf9729855e94c7ac9f990a664d76c6bb487af5f4aa22aa387b
Actual key^^


(gdb) n
672         unsigned int nSize = ReadCompactSize(is);
(gdb)
673         unsigned int i = 0;
(gdb) p nSize
$3 = 214
(gdb) l
668     void Unserialize_impl(Stream& is, std::vector& v, const unsigned char&)
669     {
670         // Limit size per read so bogus size value won't cause out of memory
671         v.clear();
672         unsigned int nSize = ReadCompactSize(is);
673         unsigned int i = 0;
674         while (i < nSize)
675         {
676             unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
677             v.resize(i + blk);


Stepping into code also verifies it's 214 bytes data. The actual private key is starting at the 9th byte. Why is this? What are the additional 182 bytes for?

Jump to: