開発環境
- macOS Mojave - Apple (OS)
- Emacs (Text Editor)
- Windows 10 Pro (OS)
- Visual Studio Code (Text Editor)
- Python 3.7 (プログラミング言語)
Programming Bitcoin: Learn How to Program Bitcoin from Scratch (Jimmy Song(著)、O'Reilly Media)のChapter 4(Serialization)、Compressed SEC Format、Exercises 2(79)の解答を求めてみる。
コード
Python 3
ecc_test.py
#!/usr/bin/env python3
from unittest import TestCase, main
from ecc import FieldElement, Point, S256Point, PrivateKey
class S256PointTest(TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def test_parse(self):
secrets = [5001, 2019**5, 0xdeadbeef54321]
for secret in secrets:
private_key = PrivateKey(secret)
point = private_key.point
self.assertEqual(point,
S256Point.parse(point.sec(compressed=True)))
if __name__ == '__main__':
main()
ecc.py
#!/usr/bin/env python3
class S256Point(Point):
def __init__(self, x, y, a=None, b=None):
a = S256Field(A)
b = S256Field(B)
if type(x) == int:
x = S256Field(x)
y = S256Field(y)
super().__init__(x=x, y=y, a=a, b=b)
def __rmul__(self, coefficient):
return super().__rmul__(coefficient % N)
def __repr__(self):
if self.x is None:
return 'S256Point(infinity)'
return f'S256Point({self.x}, {self.y})'
def verify(self, z, sig):
s_inv = pow(sig.s, N - 2, N)
u = z * s_inv % N
v = sig.r * s_inv % N
total = u * G + v * self
return total.x.num == sig.r
def sec(self, compressed=True):
if compressed:
if self.y.num % 2 == 0:
prefix = b'\x02'
else:
prefix = b'\x03'
return prefix + self.x.num.to_bytes(32, 'big')
return b'\x04' + \
self.x.num.to_bytes(32, 'big') + \
self.y.num.to_bytes(32, 'big')
@staticmethod
def parse(sec_bin):
if sec_bin[0] == 4:
x = int.from_bytes(sec_bin[1:3], 'big')
y = int.from_bytes(sec_bin[33:36], 'big')
return S256Point(x, y)
x = S256Field(int.from_bytes(sec_bin[1:], 'big'))
left = x ** 3 + S256Field(A) * x + S256Field(B)
y = left.sqrt()
is_even = sec_bin[0] == 2
if (is_even and y.num % 2 != 0) or \
(not is_even and y.num % 2 == 0):
y = S256Field(P - y.num)
return S256Point(x, y)
sample2.py
#!/usr/bin/env python3
from ecc import PrivateKey
secrets = [2001, 2019 ** 5, 0xdeadbeef52321]
for secret in secrets:
private_key = PrivateKey(secret)
sec = private_key.point.sec()
print(sec.hex())
入出力結果(cmd(コマンドプロンプト)、Terminal、Jupyter(IPython))
C:\Users\...>py ecc_test.py .................... ---------------------------------------------------------------------- Ran 20 tests in 0.041s OK C:\Users\...>py sample2.py 038d3f06b158ddd609f83b0531466fc2a3da6aa80b433a92ddeeb20435cf33ddae 02933ec2d2b111b92737ec12f1c5d20f3233a0ad21cd8b36d0bca7a0cfa5cb8701 02984d8976231dcb7873ef76f4f11c0986a60c3560bfef1e45f3db696e26f3f656 C:\Users\...>
0 コメント:
コメントを投稿