2019年4月14日日曜日

開発環境

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 コメント:

コメントを投稿