Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save bitkevin/5925465 to your computer and use it in GitHub Desktop.
Save bitkevin/5925465 to your computer and use it in GitHub Desktop.

compressed and uncompressed pubkey

The private key is always exactly 256 bits, or 32 bytes. The exact same private key corresponds to two different public keys. One is uncompressed in the form of (x,y), and the other is compressed in the form of (x,p). The two forms have different representations, and thus different hashes, and thus different addresses. The compression flag just tells the system which of the two possible addresses to use.

You should pretty much always do compressed keys for new generation. There is no reason to ever use uncompressed keys, at least none that I'm aware of.

So, to create the WIF, suitable for importing later, you take the 32 byte binary private key, prepend the 0x80 bytes, and append the 0x01 flag for compression, then run through base58encode and the output is the WIF. For reference, to create an uncompressed WIF, just don't append the 0x01 before encoding.

To create the matching address, calculate the public key as usual, but when you go to encode it, check the parity of Y. If Y%2 is even, encode it as 0x02 + x. If Y%2 is odd, encode it as 0x03 + x. (Uncompressed, it would be 0x04 + x + y.) Note that I'm using + to mean concatenation here. Then the address is created as usual.

If you need to accept WIF as input, after the base58decode step, you'll always have 33 or 34 bytes. If 33 bytes, it is uncompressed, and the private key is the 32 bytes after the 0x80 header. If 34 bytes, it is compressed, the last byte must be 0x01, and the private key is everything between the 0x80 header and the 0x01 compression flag. Once you have the private key and know whether the compression flag was present or not, you can calculate the public key and address as above.

Sig

[sig] = [sigLength][0×30][rsLength][0×02][rLength][sig_r][0×02][sLength][sig_s][0×01]

where

  • sigLength
    • gives the number of bytes taken up the rest of the signature ([0×30]…[0×01])
  • rsLength
    • gives the number of bytes in [0×02][rLength][sig_r][0×02][sLength][sig_s]
  • rLength
    • gives the number of bytes in [sig_r] (approx 32 bytes)
  • sLength
    • gives the number of bytes in [sig_s] (approx 32 bytes)

pubKeyHash

[pubKeyHash] = [pubKeyHashLength][RIPEMD160(SHA256(public key))]

where pubKeyHashLength is always 0×14 (= 20) since the RIPEMD160 digest is 20 bytes.

[pubKey] (uncompressed) = [publicKeyLength][0×04][keyX][keyY]

where publicKeyLength is always 0×41 (= 65) since keyX and keyY are 32 bytes and 0×04 is 1 byte

[pubKey] (compressed) = [publicKeyLength][0×02 or 0×03][keyX]

where publicKeyLength is always 0×21 (= 33) since keyX is 32 bytes and 0×02/0×03 is 1 byte.

If keyY%2 is even, encode it as 0x02 + keyX. If keyY%2 is odd, encode it as 0x03 + keyX

Ref

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment