[Bitcoin] 署名の作成

### 署名の作成

e = int.from_bytes(hash256(b'my secret'), 'big') 
z = int.from_bytes(hash256(b'my message'), 'big') # 署名しようとしているメッセージ
k = 1234567890 
r = (k*G).x.num # x座標のみ取り出す
k_inv = pow(k, N-2, N)
s = (z+r*e) * k_inv % N # モジュロ演算
point = e*G # 公開点は知らせる必要がある
print(point)

print(hex(z))
print(hex(r))
print(hex(s))

$ python3 app.py
Point(1153752822844410451703720272380683670327470420405725541447346968941621636178,4935740600172189071191766981850281297554521083605982627869195587800421042658)_0_7 FieldElement(115792089237316195423570985008687907853269984665640564039457584007908834671663)
0x231c6f3d980a6b0fb7152f85cee7eb52bf92433d9919b9c5218cb08e79cce78
0x2b698a0f0a4041b77e63488ad48c23e8e8838dd1fb7520408b121697b782ef22
0xbb14e602ef9e3f872e25fad328466b34e6734b7a0fcd58b1eb635447ffae8cb9

e = 12345
z = int.from_bytes(hash256(b'programming bitcoin'), 'big')
k = 1234567890
r = (k*G).x.num
k_inv = pow(k, N-2, N)
s = (z+r*e) * k_inv % N
point = e*G
print(point)

print(hex(z))
print(hex(r))
print(hex(s))

$ python3 app.py
Point(108607064596551879580190606910245687803607295064141551927605737287325610911759,6661302038839728943522144359728938428925407345457796456954441906546235843221)_0_7 FieldElement(115792089237316195423570985008687907853269984665640564039457584007908834671663)
0x6aac771a641117f22150921737c72c77e73150945342f7a490b77332abaac5c
0x2b698a0f0a4041b77e63488ad48c23e8e8838dd1fb7520408b121697b782ef22
0xd6f075528e124345b4b81029288861d9c33ddc49f8327005dfb203b3e9c1ee9c

### メッセージ署名

from random import randint

class PrivateKey:

	def __init__(self, secret):
		self.secret = secret
		self.point = secret * G

	def hex(self):
		return '{:x}'.format(self.secret).zfill(64)

	def sign(self, z):
		k = randint(0, N-1)
		r = (k*G).x.num
		k_inv = pow(k, N-2, N)
		s = (z + r*self.secret) * k_inv % N
		if s > N/2:
			s = N - s
		return Signature(r, s)

k は署名ごとに一意である必要がある。
RFC6979

	def sign(self, z):
		k = self.deterministic_k(z)
		r = (k*G).x.num
		k_inv = pow(k, N-2, N)
		s = (z + r*self.secret) * k_inv % N
		if s > N/2:
			s = N - s
		return Signature(r, s)

	def deterministic_k(self, z):
		k = b'\x00' * 32
        v = b'\x01' * 32
        if z > N:
            z -= N
        z_bytes = z.to_bytes(32, 'big')
        secret_bytes = self.secret.to_bytes(32, 'big')
        s256 = hashlib.sha256
        k = hmac.new(k, v + b'\x00' + secret_bytes + z_bytes, s256).digest()
        v = hmac.new(k, v, s256).digest()
        k = hmac.new(k, v + b'\x01' + secret_bytes + z_bytes, s256).digest()
        v = hmac.new(k, v, s256).digest()
        while True:
            v = hmac.new(k, v, s256).digest()
            candidate = int.from_bytes(v, 'big')
            if candidate >= 1 and candidate < N:
                return candidate  
            k = hmac.new(k, v + b'\x00', s256).digest()
            v = hmac.new(k, v, s256).digest()

これが基本要素なのか
なんか凄いな