Bitcoin Forum

Bitcoin => Development & Technical Discussion => Topic started by: etotheipi on September 09, 2011, 03:32:17 AM



Title: The prefix byte (0x04) in public keys
Post by: etotheipi on September 09, 2011, 03:32:17 AM
I haven't found any documentation mentioning why we have this extra byte in every public-key serialization.  For reference, a public key is always serialized as 65 bytes:  (0x04 | PubKeyX(32B) | PubKeyY(32B)), but that 0x04 byte doesn't appear to serve a purpose.   If I had to guess, I would think it's to identify the length of the ECDSA key, in multiples of 64 bits / 8 bytes.  Or maybe it's the encryption type...?

I hate having to hard-code random bytes into my source files, when it's possible they are actually variable and useful.


Title: Re: The prefix byte (0x04) in public keys
Post by: casascius on September 09, 2011, 03:36:04 AM
I can't point to anything useful, but can vouch for the fact that it must be there when converting a public key to a bitcoin address (via sha256/ripemd160).


Title: Re: The prefix byte (0x04) in public keys
Post by: Pieter Wuille on September 09, 2011, 07:46:35 AM
Bitcoin uses the standard encoding for public keys, as described in http://www.secg.org/index.php?action=secg,docs_secg (http://www.secg.org/index.php?action=secg,docs_secg). The prefix byte is there to distinguish between several encodings - with 0x04 denoting uncompressed coordinates.


Title: Re: The prefix byte (0x04) in public keys
Post by: etotheipi on September 09, 2011, 11:07:21 AM
So is this related to DER?  Looks too lite to be DER (which is similarly used for signatures, but there's like 8 extra bytes floating around).

Is it safe to assume that 0x04 will always be there?


Title: Re: The prefix byte (0x04) in public keys
Post by: Pieter Wuille on September 09, 2011, 11:29:39 AM
No, DER is used for signatures, but not for public keys. Several encodings of keys are possible (including patented compressed coordinates), but as Bitcoin depends (through the specification of addresses as ripemd160(sha256(pubkey))) on a normalized encoding, i think it is safe the 0x04 will always be there in the current generation of addresses.


Title: Re: The prefix byte (0x04) in public keys
Post by: davout on September 09, 2011, 12:02:44 PM
Isn't it a way to differentiate testnet addresses also ?


Title: Re: The prefix byte (0x04) in public keys
Post by: etotheipi on September 09, 2011, 12:15:59 PM
Quote
Isn't it a way to differentiate testnet addresses also ?

See my diagram on address calculations.  The extra byte for the network gets added to the ripemd160(sha256()) digest.  The 0x04 is appears to be constant across all networks (definitely the same on the test-network)

http://dl.dropbox.com/u/1139081/BitcoinImg/PubKeyToAddr.png


Title: Re: The prefix byte (0x04) in public keys
Post by: Pieter Wuille on September 09, 2011, 12:38:44 PM
Correct. The public key format is managed by OpenSSL, bitcoin treats it as a black box.


Title: Re: The prefix byte (0x04) in public keys
Post by: Joric on April 01, 2012, 02:34:54 PM
SEC defines three types: 0x00 = point at infinity, 0x02 and 0x03 = compressed, 0x04 = uncompressed

02 basically means even y-point, 03 means odd y-point, thus:

uncompressed pubkey = chr(4) + 32-byte x + 32-byte y
compressed pubkey = chr(1 + (y & 1)) + 32-byte x

Also see http://github.com/joric/pywallet (I updated it recently, now it supports compressed keys).

Using OpenSSL you just have to set point conversion via EC_KEY_set_conv_form().