[Bitcoin] シリアライズ:非圧縮・圧縮SECフォーマット

楕円曲線暗号の公開鍵は(x,y)形式の一つの座標
ECDSA公開鍵をシリアライズする方法はSECフォーマットと呼ばれている
非圧縮と圧縮がある

1.プレフィックス0x04
2.32バイトのビッグエンディアン整数をx座標に追加
2.32バイトのビッグエンディアン整数をy座標に追加

### 非圧縮

class S256Point(Point):
	// 省略
	def sec(self):
		return b'\x04' + self.x.num.to_bytes(32, 'big')\
			+ self.y.num.to_bytes(32, 'big')
priv = PrivateKey(5002)
print(priv.point.sec(compressed=False).hex())
priv = PrivateKey(2018**5)
print(priv.point.sec(compressed=False).hex())
priv = PrivateKey(0xdeadbeef12345)
print(priv.point.sec(compressed=False).hex())

$ python3 app.py
040f85cb0c917647fadfd31e641231d3a01ac9d3d8a680aab2457e0036bf34d37e6949b302843a33cdf068589c8330bb5c09c1739420d65b7b33cfab6d10118d97
04027f3da1918455e03c46f659266a1bb5204e959db7364d2f473bdf8f0a13cc9dff87647fd023c13b4a4994f17691895806e1b40b57f4fd22581a4f46851f3b06
04d90cd625ee87dd38656dd95cf79f65f60f7273b67d3096e68

### 圧縮

class S256Field(FieldElement):

	def __init__(self, num, prime=None):
		super().__init__(num=num, prime=P)

	def __repr__(self):
		return '{:x}'.format(self.num).zfill(64)

	def sqrt(self):
		return self**((P + 1) // 4)

	@classmethod
	def parse(self, sec_bin):
		if sec_bin[0] == 4:
			x = int.from_bytes(sec_bin[1:33], 'big')
			y = int.from_bytes(sec_bin[33:65], 'big')
			return S256Point(x=x, y=y)
		is_even = sec_bin[0] == 2
		x = S256Field(int.from_bytes(sec_bin[1:], 'big'))
		alpha = x**3 + S256Field(B)
		beta = alpha.sqrt()
		if beta.num % 2 == 0:
			even_beta = beta
			odd_beta = S256Field(P - beta.num)
		else:
			even_beta = S256Field(P - beta.num)
			odd_beta = beta
		if is_even:
			return S256Point(x, even_beta)
		else:
			return S256Point(x, odd_beta)

priv = PrivateKey(5001)
print(priv.point.sec(compressed=True).hex())
priv = PrivateKey(2019**5)
print(priv.point.sec(compressed=True).hex())
priv = PrivateKey(0xdeadbeef54321)
print(priv.point.sec(compressed=True).hex())

$ python3 app.py
0357a4f368868a8a6d572991e484e664810ff14c05c0fa023275251151fe0e53d1
02933ec2d2b111b92737ec12f1c5d20f3233a0ad21cd8b36d0bca7a0cfa5cb8701
0296be5b1292f6c856b3c5654e886fc13511462059089cdf9c479623bfcbe77690