Bitcoin Programming: PrivateKey, PublicKey & Signature

In this writing, is about to serialization, how to transmit PrivateKey, PubKey & Signature
to other computers on the network, or even to disk. There will be 2 types SEC, 
Standards for Efficient Cryptography. Compressed and Uncompressed. With form provided
SEC form for given point P = (x,y) is generate as following:
1.  Start with the prefix byte, which is 0x04.
2.  Next, append the x coordinate in 32 bytes as a big-endian integer.
3.  Next, append the y coordinate in 32 bytes as a big-endian integer.


Prefix or marker. '04' meaning Uncompressed, '03' Compressed Odd ending and '02' Compressed Even ending. These are the format for PubKey.

Signature itself, there is DER Signatures and format is like following:
1.  Start with the 0x30 byte.
2.  Encode the length of the rest of the signature (usually 0x44 or 0x45) and append.
3.  Append the marker byte, 0x02.
4.  Encode r as a big-endian integer, but prepend it with 0x00 byte if r's first byte >= 0x80. 
     Prepend the resulting length to r. Add this to result
5.  Append the marker byte, 0x02.
6.  Encode s as a big-endian integer, but prepend with the 0x00 byte if s' first byte >= 0x80.
     Prepend the resulting length to s. Add this to result.

The rules of #4 and #6 if less then prepend with 0x00 or the first bit is zero.



Most of the content value mentioned is in hex-encode, then we will cover what the
Base58 used/implementation for. There are three major considerations. The first is that
the public key be readable (easy to hand-write and not too difficult to mistake, say, 
over the phone). The second is thats it's short (not so long that its cumbersome). 
The third is that it's secure (so it's harder to make mistakes)

The mechanics of doing Base58 encoding are as following:
1.  All numbers, uppercase letters and lowercase letters are utilised
     except for 0/o and l/I
2.  That leaves us 10 + 26 + 26 - 4 = 58.
3.  Each of this char repesents a digit in Base58.

>>> BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

>>> def encode_base58(s):

...     count = 0

...     for c in s:

...             if c == 0:

...                     count+=1

...             else:

...                     break

...     num = int.from_bytes(s,'big')

...     prefix = '1' * count

...     result = ''

...     while num > 0:

...             num, mod = divmod(num,58)

...             result = BASE58_ALPHABET[mod] + result

...     return prefix + result

... 

>>> 'Eg.'

>>> str_hex='7c076ff316692a3d7eb3c3bb0f8b1488cf72e1afcd929e29307032997a838a3d'

>>> bytes.fromhex(str_hex)

b'|\x07o\xf3\x16i*=~\xb3\xc3\xbb\x0f\x8b\x14\x88\xcfr\xe1\xaf\xcd\x92\x9e)0p2\x99z\x83\x8a='

>>> encode_base58(bytes.fromhex(str_hex))

'9MA8fRQrT4u8Zj8ZRd6MAiiyaxb2Y1CMpvVkHQu5hVM6'

>>> 


things i've learned, 

a. compressed/un-compressed serialization of public key

b. Base58 encoder

Comments