Bitcoin Forum
April 19, 2024, 01:01:25 PM *
News: Latest Bitcoin Core release: 26.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Suggestion: change the encoding for compressed private keys  (Read 1513 times)
Vitalik Buterin (OP)
Sr. Member
****
Offline Offline

Activity: 330
Merit: 397


View Profile
October 28, 2013, 07:43:32 AM
 #1

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").

Argumentum ad lunam: the fallacy that because Bitcoin's price is rising really fast the currency must be a speculative bubble and/or Ponzi scheme.
1713531685
Hero Member
*
Offline Offline

Posts: 1713531685

View Profile Personal Message (Offline)

Ignore
1713531685
Reply with quote  #2

1713531685
Report to moderator
BitcoinCleanup.com: Learn why Bitcoin isn't bad for the environment
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1713531685
Hero Member
*
Offline Offline

Posts: 1713531685

View Profile Personal Message (Offline)

Ignore
1713531685
Reply with quote  #2

1713531685
Report to moderator
gmaxwell
Moderator
Legendary
*
expert
Offline Offline

Activity: 4158
Merit: 8382



View Profile WWW
October 28, 2013, 08:09:59 AM
 #2

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.
DannyHamilton
Legendary
*
Offline Offline

Activity: 3360
Merit: 4570



View Profile
October 28, 2013, 02:35:16 PM
 #3

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.
kjj
Legendary
*
Offline Offline

Activity: 1302
Merit: 1024



View Profile
October 28, 2013, 05:59:05 PM
 #4

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.

17Np17BSrpnHCZ2pgtiMNnhjnsWJ2TMqq8
I routinely ignore posters with paid advertising in their sigs.  You should too.
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!