Bitcoin Forum

Bitcoin => Development & Technical Discussion => Topic started by: Vitalik Buterin on October 28, 2013, 07:43:32 AM



Title: Suggestion: change the encoding for compressed private keys
Post by: Vitalik Buterin on October 28, 2013, 07:43:32 AM
Currently, Bitcoin private and public keys have the following data types:

* Uncompressed private key: 64 hex bytes, eg:

a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3

* Uncompressed public key: 04 + x coordinate + y coordinate

04be686ed7f0539affbaf634f3bcc2b235e8e220e7be57e9397ab1c14c39137eb43705125aac75a 865268ef33c53897c141bd092cf4d1a306b2a57e37e1386826d

* Compressed public key: 02 or 03 (depending on whether y is odd or even) + x coordinate

03be686ed7f0539affbaf634f3bcc2b235e8e220e7be57e9397ab1c14c39137eb4

* Private key intended to become a compressed key: key + '01'

a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae301

* BIP32 internal format for a private key intended to become a compressed key: '00' + key

00a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3

There is an obvious problem here: the compressed public key encoding and the private key encoding are ambiguous. For example, consider the string:

02d20bbd7e394ad5999a4cebabac9619732c343a4cac99470c03e23ba2bdc2bc01

This can be seen in one of two ways:

1. As a compressed public key with x coordinate d20bbd7e394ad5999a4cebabac9619732c343a4cac99470c03e23ba2bdc2bc01
2. As a private key intended to become a compressed key, with the original key being 02d20bbd7e394ad5999a4cebabac9619732c343a4cac99470c03e23ba2bdc2bc

The question is: why is it the case that every other encoding we use puts the type data at the beginning (02/03 for uncompressed, 04 for compressed, 00 for BIP32 privkeys), while to-be-compressed private keys are instead marked with '01' at the end?

The solution that I propose is to make the BIP32 internal private key format, that of '00' + key being the standard way to encode a private key intended to become a public key, standard. That way there will be a trivial algorithm to determine the data type of anything:

* Is it base58? Then, decode it and run the algorithm on the result.
* Is it 20 bytes? It's an address
* Is it 32 bytes? It's a standard old-style privkey
* Is it 33 bytes? Look at the first byte, if it's 00 it's a privkey to be used with compression, if it's 02 or 03 it's a compressed pubkey, if it's 04 it's an uncompressed pubkey.

The WIF format of a new-style privkey would then start with Kw (precisely, it would be between "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73NUBByJr" and "KwFevqMbSXhGxNWuVc6vuERwdXq7aDQtiLNkjPVokF87Rs4LmqrN").


Title: Re: Suggestion: change the encoding for compressed private keys
Post by: gmaxwell on October 28, 2013, 08:09:59 AM
The base58 encodings have a type parameter which specifies the data-type:

chainparams.cpp:        base58Prefixes[PUBKEY_ADDRESS] = list_of(0);
chainparams.cpp:        base58Prefixes[SCRIPT_ADDRESS] = list_of(5);
chainparams.cpp:        base58Prefixes[SECRET_KEY] =     list_of(128);
chainparams.cpp:        base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x88)(0xB2)(0x1E);
chainparams.cpp:        base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x88)(0xAD)(0xE4);

All BIP32 keys are used 'compressed'.

I'm not sure what value having a second type coding would have, but it's late and so perhaps I'm confused. Why should we have additional overhead to have types inside our typed data? As an aside I'm generally not generally thrilled with size sniffing for type determination, as it tends to be brittle.


Title: Re: Suggestion: change the encoding for compressed private keys
Post by: DannyHamilton on October 28, 2013, 02:35:16 PM
Currently, Bitcoin private and public keys have the following data types:

* Uncompressed private key: 64 hex bytes, eg:

a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3


Just a small correction, having no bearing on the specific topic you are discussing:

Private key is 256 bits.  1 byte is 8 bits. 256 / 8 = 32.  So the private key is 32 bytes not 64 bytes. Those 32 bytes are represented in hex as 64 characters each representing 1 nybble.


Title: Re: Suggestion: change the encoding for compressed private keys
Post by: kjj on October 28, 2013, 05:59:05 PM
The ambiguity of the hex forms is one of the reasons for the encoded forms.  Hex is not suitable for interchange, only for internal temporary use.

Avoid ambiguity internal to your program by attaching metadata.