主頁 > 區塊鏈 > 《區塊鏈編程》-第三章

《區塊鏈編程》-第三章

2022-01-02 09:02:06 區塊鏈

文章目錄

  • 橢圓曲線數字簽名演算法
    • 名稱解釋
    • 簽名的程序:
    • 驗證簽名的程序:
  • 橢圓曲線密碼學
    • 練習1
      • 代碼實作
      • 測驗
    • 練習2
      • 代碼實作
      • 測驗
    • 練習3
      • 代碼實作
      • 測驗
    • 練習4
      • 代碼實作
      • 運行結果
    • 練習5
      • 代碼實作
      • 運行結果
    • 練習6
      • 代碼實作
      • 運行結果
    • 練習7
      • 代碼實作
      • 運行結果
    • 本章中涉及的ecc與helper
      • 書中給的ecc
      • 書中給的helper

《區塊鏈編程》第三章

橢圓曲線數字簽名演算法

名稱解釋

一定配合著書看,
如下的名詞解釋不足以解釋橢圓曲線數字簽名演算法的細節, 具體內容還要看書中的詳細解釋,

  1. R R是橢圓曲線上的點,R點有兩個,一個是簽名者創建的R點, 一個是驗證者計算得到的R點
  2. r 小r是R點的橫坐標
  3. z z是簽名資訊的哈希
  4. s : s是通過計算得到的,與z,r,e,k有關,

======================================

  1. G G點是橢圓曲線密碼學的起點,是可以自由選擇的
  2. e eG = P; 在這個式子中,e是私鑰,是一個256位數字,P是公鑰,是橢圓曲線上的點,
  3. k kG = R, k是一個256位的亂數,k是私鑰擁有者(簽名者)選定的亂數,

簽名的程序:

  1. 簽名者 已知z,e
  2. 隨機選擇k
  3. 計算 R = kG,得到x軸坐標r
  4. 計算出s(由z、r、e、k計算得到)
  5. 得到數字簽名 (r,s)

驗證簽名的程序:

  1. 驗證者接收(r,s)、z與公鑰
  2. 計算出R點
  3. 驗證R點的x軸坐標與r值是否相等,相等則簽名是有效的

橢圓曲線密碼學

練習1

p44

代碼實作

# -*- coding: utf-8 -*-
# @Author: 從化北(喵星人)
# @Date:   2021-12-31 14:28:13
# @Last Modified by:   從化北
# @Last Modified time: 2021-12-31 15:55:45

# 注意: ecc內包含FieldElement類,
# 這里不再重復給出
from ecc import FieldElement
prime = 223
a = FieldElement(0, prime)
b = FieldElement(7, prime)


def onCurve(x, y):
    return y ** 2 == x**3 + a * x + b


if __name__ == '__main__':
    print(onCurve(FieldElement(192, prime), FieldElement(105, prime)))
    print(onCurve(FieldElement(17, prime), FieldElement(56, prime)))
    print(onCurve(FieldElement(200, prime), FieldElement(119, prime)))
    print(onCurve(FieldElement(1, prime), FieldElement(193, prime)))
    print(onCurve(FieldElement(42, prime), FieldElement(99, prime)))



測驗

True
True
False
True
False
[Finished in 303ms]

練習2

p49

代碼實作


# -*- coding: utf-8 -*-
# @Author: 從化北(喵星人)
# @Date:   2021-12-31 15:57:16
# @Last Modified by:   從化北
# @Last Modified time: 2021-12-31 16:12:16


# 注意: ecc內包含FieldElement類與Point類,
# 第一章和第二章中已給出,這里不再重復給出

from ecc import FieldElement, Point

prime = 223
a = FieldElement(0, prime)
b = FieldElement(7, prime)

x1, y1, x2, y2 = FieldElement(170, prime), FieldElement(142, prime), FieldElement(60, prime), FieldElement(139, prime)
x3, y3, x4, y4 = FieldElement(47, prime), FieldElement(71, prime), FieldElement(17, prime), FieldElement(56, prime)
x5, y5, x6, y6 = FieldElement(143, prime), FieldElement(98, prime), FieldElement(76, prime), FieldElement(66, prime)
p1, p2 = Point(x1, y1, a, b), Point(x2, y2, a, b)
p3, p4 = Point(x3, y3, a, b), Point(x4, y4, a, b)
p5, p6 = Point(x5, y5, a, b), Point(x6, y6, a, b)

print(p1 + p2)
print(p3 + p4)
print(p5 + p6)

測驗

Point(FieldElement_223(220), FieldElement_223(181))_FieldElement_223(0)_FieldElement_223(7)
Point(FieldElement_223(215), FieldElement_223(68))_FieldElement_223(0)_FieldElement_223(7)
Point(FieldElement_223(47), FieldElement_223(71))_FieldElement_223(0)_FieldElement_223(7)
[Finished in 330ms]

練習3

p49

代碼實作

# -*- coding: utf-8 -*-
# @Author: 從化北(喵星人)
# @Date:   2021-12-31 16:17:26
# @Last Modified by:   從化北
# @Last Modified time: 2021-12-31 16:25:22

# 注意: ecc內包含FieldElement類與Point類,
# 第一章和第二章中已給出,這里不再重復給出

from ecc import FieldElement, Point
from unittest import TestCase
from unittest import TestSuite, TextTestRunner


class ECCTest(TestCase):

    def test_add(self):
        # tests the following additions on curve y^2=x^3-7 over F_223:
        # (192,105) + (17,56)
        # (47,71) + (117,141)
        # (143,98) + (76,66)
        prime = 223
        a = FieldElement(0, prime)
        b = FieldElement(7, prime)

        additions = (
            # (x1, y1, x2, y2, x3, y3)
            (192, 105, 17, 56, 170, 142),
            (47, 71, 117, 141, 60, 139),
            (143, 98, 76, 66, 47, 71),
        )
        for x1_raw, y1_raw, x2_raw, y2_raw, x3_raw, y3_raw in additions:
            x1 = FieldElement(x1_raw, prime)
            y1 = FieldElement(y1_raw, prime)
            p1 = Point(x1, y1, a, b)

            x2 = FieldElement(x2_raw, prime)
            y2 = FieldElement(y2_raw, prime)
            p2 = Point(x2, y2, a, b)

            x3 = FieldElement(x3_raw, prime)
            y3 = FieldElement(y3_raw, prime)
            p3 = Point(x3, y3, a, b)

            self.assertEqual(p1 + p2, p3)


def run(test):
    suite = TestSuite()
    suite.addTest(test)
    TextTestRunner().run(suite)


if __name__ == '__main__':
    run(ECCTest("test_add"))


測驗

.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
[Finished in 309ms]

練習4

p51
第二個點,書中寫錯了, 應該是(143,98)

代碼實作

# -*- coding: utf-8 -*-
# @Author: 從化北(喵星人)
# @Date:   2021-12-31 17:00:43
# @Last Modified by:   從化北
# @Last Modified time: 2021-12-31 17:06:08


# 注意: ecc內包含FieldElement類和Point類,
# 第一章和第二章中已給出,這里不再重復給出
from ecc import FieldElement, Point

prime = 223
a = FieldElement(0, prime)
b = FieldElement(7, prime)


x1 = FieldElement(192, prime)
y1 = FieldElement(105, prime)

x2 = FieldElement(143, prime)
y2 = FieldElement(98, prime)

x3 = FieldElement(47, prime)
y3 = FieldElement(71, prime)
p1 = Point(x1, y1, a, b)
p2 = Point(x2, y2, a, b)
p3 = Point(x3, y3, a, b)
print(p1 + p1)
print(p2 + p2)
print(p3 + p3)
print(p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3)
print(p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3 + p3)



運行結果

Point(49,71)_0_7 FieldElement(223)
Point(64,168)_0_7 FieldElement(223)
Point(36,111)_0_7 FieldElement(223)
Point(116,55)_0_7 FieldElement(223)
Point(infinity)
[Finished in 313ms]

練習5

p56

代碼實作

# -*- coding: utf-8 -*-
# @Author: 從化北(喵星人)
# @Date:   2021-12-31 17:14:38
# @Last Modified by:   從化北
# @Last Modified time: 2021-12-31 17:17:50

# 注意: ecc內包含FieldElement類和Point類,
# 第一章和第二章中已給出,這里不再重復給出
from ecc import FieldElement, Point

prime = 223
a = FieldElement(0, prime)
b = FieldElement(7, prime)


x1 = FieldElement(15, prime)
y1 = FieldElement(86, prime)

p1 = Point(x1, y1, a, b)
inf = Point(None, None, a, b)
count = 1
product = p1
while product != inf:
    product += p1
    count += 1
print(count)

運行結果

7
[Finished in 320ms]

練習6

p66

代碼實作

# -*- coding: utf-8 -*-
# @Author: 從化北(喵星人)
# @Date:   2021-12-31 17:22:58
# @Last Modified by:   從化北
# @Last Modified time: 2021-12-31 18:15:33

from ecc import S256Point, N, G


point = S256Point(
    0x887387e452b8eacc4acfde10d9aaf7f6d9a0f975aabb10d006e4da568744d06c,
    0x61de6d95231cd89026e286df3b6ae4a894a3378e393e93a0f45b666329a0ae34)
z = 0xec208baa0fc1c19f708a9ca96fdeff3ac3f230bb4a7ba4aede4942ad003c0f60
r = 0xac8d1c87e51d0d441be8b3dd5b05c8795b48875dffe00b7ffcfac23010d3a395
s = 0x68342ceff8935ededd102dd876ffd6ba72d6a427a3edb13d26eb0781cb423c4
u = z * pow(s, N - 2, N) % N
v = r * pow(s, N - 2, N) % N
print((u * G + v * point).x.num == r)

z = 0x7c076ff316692a3d7eb3c3bb0f8b1488cf72e1afcd929e29307032997a838a3d
r = 0xeff69ef2b1bd93a66ed5219add4fb51e11a840f404876325a1e8ffe0529a2c
s = 0xc7207fee197d27c618aea621406f6bf5ef6fca38681d82b2f06fddbdce6feab6
u = z * pow(s, N - 2, N) % N
v = r * pow(s, N - 2, N) % N
print((u * G + v * point).x.num == r)



運行結果

True
True
[Finished in 691ms]

練習7

p68

代碼實作

# -*- coding: utf-8 -*-
# @Author: 從化北(喵星人)
# @Date:   2021-12-31 18:19:04
# @Last Modified by:   從化北
# @Last Modified time: 2021-12-31 18:27:22

from ecc import S256Point, G, N
from helper import hash256
e = 12345
z = int.from_bytes(hash256('Programming Bitcoin!'.encode("utf-8")), 'big')
k = 1234567890
r = (k * G).x.num
k_inv = pow(k, N - 2, N)
s = (z + r * e) * k_inv % N
print(e * G)
print(hex(z))
print(hex(r))
print(hex(s))



運行結果

S256Point(f01d6b9018ab421dd410404cb869072065522bf85734008f105cf385a023a80f, 0eba29d0f0c5408ed681984dc525982abefccd9f7ff01dd26da4999cf3f6a295)
0x969f6056aa26f7d2795fd013fe88868d09c9f6aed96965016e1936ae47060d48
0x2b698a0f0a4041b77e63488ad48c23e8e8838dd1fb7520408b121697b782ef22
0x1dbc63bfef4416705e602a7b564161167076d8b20990a0f26f316cff2cb0bc1a
[Finished in 325ms]

本章中涉及的ecc與helper

書中給的ecc

from random import randint
from unittest import TestCase

import hashlib
import hmac


class FieldElement:

    def __init__(self, num, prime):
        if num >= prime or num < 0:
            error = 'Num {} not in field range 0 to {}'.format(
                num, prime - 1)
            raise ValueError(error)
        self.num = num
        self.prime = prime

    def __repr__(self):
        return 'FieldElement_{}({})'.format(self.prime, self.num)

    def __eq__(self, other):
        if other is None:
            return False
        return self.num == other.num and self.prime == other.prime

    def __ne__(self, other):
        # this should be the inverse of the == operator
        return not (self == other)

    def __add__(self, other):
        if self.prime != other.prime:
            raise TypeError('Cannot add two numbers in different Fields')
        # self.num and other.num are the actual values
        # self.prime is what we need to mod against
        num = (self.num + other.num) % self.prime
        # We return an element of the same class
        return self.__class__(num, self.prime)

    def __sub__(self, other):
        if self.prime != other.prime:
            raise TypeError('Cannot subtract two numbers in different Fields')
        # self.num and other.num are the actual values
        # self.prime is what we need to mod against
        num = (self.num - other.num) % self.prime
        # We return an element of the same class
        return self.__class__(num, self.prime)

    def __mul__(self, other):
        if self.prime != other.prime:
            raise TypeError('Cannot multiply two numbers in different Fields')
        # self.num and other.num are the actual values
        # self.prime is what we need to mod against
        num = (self.num * other.num) % self.prime
        # We return an element of the same class
        return self.__class__(num, self.prime)

    def __pow__(self, exponent):
        n = exponent % (self.prime - 1)
        num = pow(self.num, n, self.prime)
        return self.__class__(num, self.prime)

    def __truediv__(self, other):
        if self.prime != other.prime:
            raise TypeError('Cannot divide two numbers in different Fields')
        # self.num and other.num are the actual values
        # self.prime is what we need to mod against
        # use fermat's little theorem:
        # self.num**(p-1) % p == 1
        # this means:
        # 1/n == pow(n, p-2, p)
        num = (self.num * pow(other.num, self.prime - 2, self.prime)) % self.prime
        # We return an element of the same class
        return self.__class__(num, self.prime)

    def __rmul__(self, coefficient):
        num = (self.num * coefficient) % self.prime
        return self.__class__(num=num, prime=self.prime)


class FieldElementTest(TestCase):

    def test_ne(self):
        a = FieldElement(2, 31)
        b = FieldElement(2, 31)
        c = FieldElement(15, 31)
        self.assertEqual(a, b)
        self.assertTrue(a != c)
        self.assertFalse(a != b)

    def test_add(self):
        a = FieldElement(2, 31)
        b = FieldElement(15, 31)
        self.assertEqual(a + b, FieldElement(17, 31))
        a = FieldElement(17, 31)
        b = FieldElement(21, 31)
        self.assertEqual(a + b, FieldElement(7, 31))

    def test_sub(self):
        a = FieldElement(29, 31)
        b = FieldElement(4, 31)
        self.assertEqual(a - b, FieldElement(25, 31))
        a = FieldElement(15, 31)
        b = FieldElement(30, 31)
        self.assertEqual(a - b, FieldElement(16, 31))

    def test_mul(self):
        a = FieldElement(24, 31)
        b = FieldElement(19, 31)
        self.assertEqual(a * b, FieldElement(22, 31))

    def test_rmul(self):
        a = FieldElement(24, 31)
        b = 2
        self.assertEqual(b * a, a + a)

    def test_pow(self):
        a = FieldElement(17, 31)
        self.assertEqual(a**3, FieldElement(15, 31))
        a = FieldElement(5, 31)
        b = FieldElement(18, 31)
        self.assertEqual(a**5 * b, FieldElement(16, 31))

    def test_div(self):
        a = FieldElement(3, 31)
        b = FieldElement(24, 31)
        self.assertEqual(a / b, FieldElement(4, 31))
        a = FieldElement(17, 31)
        self.assertEqual(a**-3, FieldElement(29, 31))
        a = FieldElement(4, 31)
        b = FieldElement(11, 31)
        self.assertEqual(a**-4 * b, FieldElement(13, 31))


# tag::source1[]
class Point:

    def __init__(self, x, y, a, b):
        self.a = a
        self.b = b
        self.x = x
        self.y = y
        if self.x is None and self.y is None:
            return
        if self.y**2 != self.x**3 + a * x + b:
            raise ValueError('({}, {}) is not on the curve'.format(x, y))
    # end::source1[]

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y \
            and self.a == other.a and self.b == other.b

    def __ne__(self, other):
        # this should be the inverse of the == operator
        return not (self == other)

    def __repr__(self):
        if self.x is None:
            return 'Point(infinity)'
        elif isinstance(self.x, FieldElement):
            return 'Point({},{})_{}_{} FieldElement({})'.format(
                self.x.num, self.y.num, self.a.num, self.b.num, self.x.prime)
        else:
            return 'Point({},{})_{}_{}'.format(self.x, self.y, self.a, self.b)

    def __add__(self, other):
        if self.a != other.a or self.b != other.b:
            raise TypeError('Points {}, {} are not on the same curve'.format(self, other))
        # Case 0.0: self is the point at infinity, return other
        if self.x is None:
            return other
        # Case 0.1: other is the point at infinity, return self
        if other.x is None:
            return self

        # Case 1: self.x == other.x, self.y != other.y
        # Result is point at infinity
        if self.x == other.x and self.y != other.y:
            return self.__class__(None, None, self.a, self.b)

        # Case 2: self.x ≠ other.x
        # Formula (x3,y3)==(x1,y1)+(x2,y2)
        # s=(y2-y1)/(x2-x1)
        # x3=s**2-x1-x2
        # y3=s*(x1-x3)-y1
        if self.x != other.x:
            s = (other.y - self.y) / (other.x - self.x)
            x = s**2 - self.x - other.x
            y = s * (self.x - x) - self.y
            return self.__class__(x, y, self.a, self.b)

        # Case 4: if we are tangent to the vertical line,
        # we return the point at infinity
        # note instead of figuring out what 0 is for each type
        # we just use 0 * self.x
        if self == other and self.y == 0 * self.x:
            return self.__class__(None, None, self.a, self.b)

        # Case 3: self == other
        # Formula (x3,y3)=(x1,y1)+(x1,y1)
        # s=(3*x1**2+a)/(2*y1)
        # x3=s**2-2*x1
        # y3=s*(x1-x3)-y1
        if self == other:
            s = (3 * self.x**2 + self.a) / (2 * self.y)
            x = s**2 - 2 * self.x
            y = s * (self.x - x) - self.y
            return self.__class__(x, y, self.a, self.b)

    # tag::source3[]
    def __rmul__(self, coefficient):
        coef = coefficient
        current = self  # <1>
        result = self.__class__(None, None, self.a, self.b)  # <2>
        while coef:
            if coef & 1:  # <3>
                result += current
            current += current  # <4>
            coef >>= 1  # <5>
        return result
    # end::source3[]


class PointTest(TestCase):

    def test_ne(self):
        a = Point(x=3, y=-7, a=5, b=7)
        b = Point(x=18, y=77, a=5, b=7)
        self.assertTrue(a != b)
        self.assertFalse(a != a)

    def test_on_curve(self):
        with self.assertRaises(ValueError):
            Point(x=-2, y=4, a=5, b=7)
        # these should not raise an error
        Point(x=3, y=-7, a=5, b=7)
        Point(x=18, y=77, a=5, b=7)

    def test_add0(self):
        a = Point(x=None, y=None, a=5, b=7)
        b = Point(x=2, y=5, a=5, b=7)
        c = Point(x=2, y=-5, a=5, b=7)
        self.assertEqual(a + b, b)
        self.assertEqual(b + a, b)
        self.assertEqual(b + c, a)

    def test_add1(self):
        a = Point(x=3, y=7, a=5, b=7)
        b = Point(x=-1, y=-1, a=5, b=7)
        self.assertEqual(a + b, Point(x=2, y=-5, a=5, b=7))

    def test_add2(self):
        a = Point(x=-1, y=1, a=5, b=7)
        self.assertEqual(a + a, Point(x=18, y=-77, a=5, b=7))


# tag::source2[]
class ECCTest(TestCase):

    def test_on_curve(self):
        prime = 223
        a = FieldElement(0, prime)
        b = FieldElement(7, prime)
        valid_points = ((192, 105), (17, 56), (1, 193))
        invalid_points = ((200, 119), (42, 99))
        for x_raw, y_raw in valid_points:
            x = FieldElement(x_raw, prime)
            y = FieldElement(y_raw, prime)
            Point(x, y, a, b)  # <1>
        for x_raw, y_raw in invalid_points:
            x = FieldElement(x_raw, prime)
            y = FieldElement(y_raw, prime)
            with self.assertRaises(ValueError):
                Point(x, y, a, b)  # <1>
    # end::source2[]

    def test_add(self):
        # tests the following additions on curve y^2=x^3-7 over F_223:
        # (192,105) + (17,56)
        # (47,71) + (117,141)
        # (143,98) + (76,66)
        prime = 223
        a = FieldElement(0, prime)
        b = FieldElement(7, prime)

        additions = (
            # (x1, y1, x2, y2, x3, y3)
            (192, 105, 17, 56, 170, 142),
            (47, 71, 117, 141, 60, 139),
            (143, 98, 76, 66, 47, 71),
        )

        # loop over additions
        # initialize x's and y's as FieldElements
        # create p1, p2 and p3 as Points
        # check p1+p2==p3
        raise NotImplementedError

    def test_rmul(self):
        # tests the following scalar multiplications
        # 2*(192,105)
        # 2*(143,98)
        # 2*(47,71)
        # 4*(47,71)
        # 8*(47,71)
        # 21*(47,71)
        prime = 223
        a = FieldElement(0, prime)
        b = FieldElement(7, prime)

        multiplications = (
            # (coefficient, x1, y1, x2, y2)
            (2, 192, 105, 49, 71),
            (2, 143, 98, 64, 168),
            (2, 47, 71, 36, 111),
            (4, 47, 71, 194, 51),
            (8, 47, 71, 116, 55),
            (21, 47, 71, None, None),
        )

        # iterate over the multiplications
        for s, x1_raw, y1_raw, x2_raw, y2_raw in multiplications:
            x1 = FieldElement(x1_raw, prime)
            y1 = FieldElement(y1_raw, prime)
            p1 = Point(x1, y1, a, b)
            # initialize the second point based on whether it's the point at infinity
            if x2_raw is None:
                p2 = Point(None, None, a, b)
            else:
                x2 = FieldElement(x2_raw, prime)
                y2 = FieldElement(y2_raw, prime)
                p2 = Point(x2, y2, a, b)

            # check that the product is equal to the expected point
            self.assertEqual(s * p1, p2)


# tag::source6[]
A = 0
B = 7
# end::source6[]
# tag::source4[]
P = 2**256 - 2**32 - 977
# end::source4[]
# tag::source9[]
N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
# end::source9[]


# tag::source5[]
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)
# end::source5[]


# tag::source7[]
class S256Point(Point):

    def __init__(self, x, y, a=None, b=None):

        a, b = S256Field(A), S256Field(B)
        if type(x) == int:
            super().__init__(x=S256Field(x), y=S256Field(y), a=a, b=b)
        else:
            super().__init__(x=x, y=y, a=a, b=b)  # <1>
    # end::source7[]

    def __repr__(self):
        if self.x is None:
            return 'S256Point(infinity)'
        else:
            return 'S256Point({}, {})'.format(self.x, self.y)

    # tag::source8[]
    def __rmul__(self, coefficient):
        coef = coefficient % N  # <1>
        return super().__rmul__(coef)
    # end::source8[]

    # tag::source12[]
    def verify(self, z, sig):
        s_inv = pow(sig.s, N - 2, N)  # <1>
        u = z * s_inv % N  # <2>
        v = sig.r * s_inv % N  # <3>
        total = u * G + v * self  # <4>
        return total.x.num == sig.r  # <5>
    # end::source12[]


# tag::source10[]
# starting point
G = S256Point(
    0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
    0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8)
# end::source10[]


class S256Test(TestCase):

    def test_order(self):
        point = N * G
        self.assertIsNone(point.x)

    def test_pubpoint(self):
        # write a test that tests the public point for the following
        points = (
            # secret, x, y
            (7, 0x5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc, 0x6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da),
            (1485, 0xc982196a7466fbbbb0e27a940b6af926c1a74d5ad07128c82824a11b5398afda, 0x7a91f9eae64438afb9ce6448a1c133db2d8fb9254e4546b6f001637d50901f55),
            (2**128, 0x8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da, 0x662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82),
            (2**240 + 2**31, 0x9577ff57c8234558f293df502ca4f09cbc65a6572c842b39b366f21717945116, 0x10b49c67fa9365ad7b90dab070be339a1daf9052373ec30ffae4f72d5e66d053),
        )

        # iterate over points
        for secret, x, y in points:
            # initialize the secp256k1 point (S256Point)
            point = S256Point(x, y)
            # check that the secret*G is the same as the point
            self.assertEqual(secret * G, point)

    def test_verify(self):
        point = S256Point(
            0x887387e452b8eacc4acfde10d9aaf7f6d9a0f975aabb10d006e4da568744d06c,
            0x61de6d95231cd89026e286df3b6ae4a894a3378e393e93a0f45b666329a0ae34)
        z = 0xec208baa0fc1c19f708a9ca96fdeff3ac3f230bb4a7ba4aede4942ad003c0f60
        r = 0xac8d1c87e51d0d441be8b3dd5b05c8795b48875dffe00b7ffcfac23010d3a395
        s = 0x68342ceff8935ededd102dd876ffd6ba72d6a427a3edb13d26eb0781cb423c4
        self.assertTrue(point.verify(z, Signature(r, s)))
        z = 0x7c076ff316692a3d7eb3c3bb0f8b1488cf72e1afcd929e29307032997a838a3d
        r = 0xeff69ef2b1bd93a66ed5219add4fb51e11a840f404876325a1e8ffe0529a2c
        s = 0xc7207fee197d27c618aea621406f6bf5ef6fca38681d82b2f06fddbdce6feab6
        self.assertTrue(point.verify(z, Signature(r, s)))


# tag::source11[]
class Signature:

    def __init__(self, r, s):
        self.r = r
        self.s = s

    def __repr__(self):
        return 'Signature({:x},{:x})'.format(self.r, self.s)
# end::source11[]


# tag::source13[]
class PrivateKey:

    def __init__(self, secret):
        self.secret = secret
        self.point = secret * G  # <1>

    def hex(self):
        return '{:x}'.format(self.secret).zfill(64)
    # end::source13[]

    # tag::source14[]
    def sign(self, z):
        k = self.deterministic_k(z)  # <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)

    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  # <2>
            k = hmac.new(k, v + b'\x00', s256).digest()
            v = hmac.new(k, v, s256).digest()
    # end::source14[]


class PrivateKeyTest(TestCase):

    def test_sign(self):
        pk = PrivateKey(randint(0, N))
        z = randint(0, 2**256)
        sig = pk.sign(z)
        self.assertTrue(pk.point.verify(z, sig))

書中給的helper

# -*- coding: utf-8 -*-
from unittest import TestSuite, TextTestRunner

import hashlib


def run(test):
    suite = TestSuite()
    suite.addTest(test)
    TextTestRunner().run(suite)


def hash256(s):
    '''two rounds of sha256'''
    return hashlib.sha256(hashlib.sha256(s).digest()).digest()



轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/400637.html

標籤:區塊鏈

上一篇:opendao拉你進坑后,metaDao也想拉你進他的坑

下一篇:商湯IPO首日市值漲百億,徐立感慨時代之幸:有機會改變世界!

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • JAVA使用 web3j 進行token轉賬

    最近新學習了下區塊鏈這方面的知識,所學不多,給大家分享下。 # 1. 關于web3j web3j是一個高度模塊化,反應性,型別安全的Java和Android庫,用于與智能合約配合并與以太坊網路上的客戶端(節點)集成。 # 2. 準備作業 jdk版本1.8 引入maven <dependency> < ......

    uj5u.com 2020-09-10 03:03:06 more
  • 以太坊智能合約開發框架Truffle

    前言 部署智能合約有多種方式,命令列的瀏覽器的渠道都有,但往往跟我們程式員的風格不太相符,因為我們習慣了在IDE里寫了代碼然后打包運行看效果。 雖然現在IDE中已經存在了Solidity插件,可以撰寫智能合約,但是部署智能合約卻要另走他路,沒辦法進行一個快捷的部署與測驗。 如果團隊管理的區塊節點多、 ......

    uj5u.com 2020-09-10 03:03:12 more
  • 谷歌二次驗證碼成為區塊鏈專用安全碼,你怎么看?

    前言 谷歌身份驗證器,前些年大家都比較陌生,但隨著國內互聯網安全的加強,它越來越多地出現在大家的視野中。 比較廣泛接觸的人群是國際3A游戲愛好者,游戲盜號現象嚴重+國外賬號安全應用廣泛,這類游戲一般都會要求用戶系結名為“兩步驗證”、“雙重驗證”等,平臺一般都推薦用谷歌身份驗證器。 后來區塊鏈業務風靡 ......

    uj5u.com 2020-09-10 03:03:17 more
  • 密碼學DAY1

    目錄 ##1.1 密碼學基本概念 密碼在我們的生活中有著重要的作用,那么密碼究竟來自何方,為何會產生呢? 密碼學是網路安全、資訊安全、區塊鏈等產品的基礎,常見的非對稱加密、對稱加密、散列函式等,都屬于密碼學范疇。 密碼學有數千年的歷史,從最開始的替換法到如今的非對稱加密演算法,經歷了古典密碼學,近代密 ......

    uj5u.com 2020-09-10 03:03:50 more
  • 密碼學DAY1_02

    目錄 ##1.1 ASCII編碼 ASCII(American Standard Code for Information Interchange,美國資訊交換標準代碼)是基于拉丁字母的一套電腦編碼系統,主要用于顯示現代英語和其他西歐語言。它是現今最通用的單位元組編碼系統,并等同于國際標準ISO/IE ......

    uj5u.com 2020-09-10 03:04:50 more
  • 密碼學DAY2

    ##1.1 加密模式 加密模式:https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html ECB ECB : Electronic codebook, 電子密碼本. 需要加密的訊息按照塊密碼的塊大小被分為數個塊,并對每個塊進 ......

    uj5u.com 2020-09-10 03:05:42 more
  • NTP時鐘服務器的特點(京準電子)

    NTP時鐘服務器的特點(京準電子) NTP時鐘服務器的特點(京準電子) 京準電子官V——ahjzsz 首先對時間同步進行了背景介紹,然后討論了不同的時間同步網路技術,最后指出了建立全球或區域時間同步網存在的問題。 一、概 述 在通信領域,“同步”概念是指頻率的同步,即網路各個節點的時鐘頻率和相位同步 ......

    uj5u.com 2020-09-10 03:05:47 more
  • 標準化考場時鐘同步系統推進智能化校園建設

    標準化考場時鐘同步系統推進智能化校園建設 標準化考場時鐘同步系統推進智能化校園建設 安徽京準電子科技官微——ahjzsz 一、背景概述隨著教育事業的快速發展,學校建設如雨后春筍,隨之而來的學校教育、管理、安全方面的問題成了學校管理人員面臨的最大的挑戰,這些問題同時也是學生家長所擔心的。為了讓學生有更 ......

    uj5u.com 2020-09-10 03:05:51 more
  • 位元幣入門

    引言 位元幣基本結構 位元幣基礎知識 1)哈希演算法 2)非對稱加密技術 3)數字簽名 4)MerkleTree 5)哪有位元幣,有的是UTXO 6)位元幣挖礦與共識 7)區塊驗證(共識) 總結 引言 上一篇我們已經知道了什么是區塊鏈,此篇說一下區塊鏈的第一個應用——位元幣。其實先有位元幣,后有的區塊 ......

    uj5u.com 2020-09-10 03:06:15 more
  • 北斗對時服務器(北斗對時設備)電力系統應用

    北斗對時服務器(北斗對時設備)電力系統應用 北斗對時服務器(北斗對時設備)電力系統應用 京準電子科技官微(ahjzsz) 中國北斗衛星導航系統(英文名稱:BeiDou Navigation Satellite System,簡稱BDS),因為是目前世界范圍內唯一可以大面積提供免費定位服務的系統,所以 ......

    uj5u.com 2020-09-10 03:06:20 more
最新发布
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:46:47 more
  • Hyperledger Fabric 使用 CouchDB 和復雜智能合約開發

    在上個實驗中,我們已經實作了簡單智能合約實作及客戶端開發,但該實驗中智能合約只有基礎的增刪改查功能,且其中的資料管理功能與傳統 MySQL 比相差甚遠。本文將在前面實驗的基礎上,將 Hyperledger Fabric 的默認資料庫支持 LevelDB 改為 CouchDB 模式,以實作更復雜的資料... ......

    uj5u.com 2023-04-16 07:28:31 more
  • .NET Core 波場鏈離線簽名、廣播交易(發送 TRX和USDT)筆記

    Get Started NuGet You can run the following command to install the Tron.Wallet.Net in your project. PM> Install-Package Tron.Wallet.Net 配置 public reco ......

    uj5u.com 2023-04-14 08:08:00 more
  • DKP 黑客分析——不正確的代幣對比率計算

    概述: 2023 年 2 月 8 日,針對 DKP 協議的閃電貸攻擊導致該協議的用戶損失了 8 萬美元,因為 execute() 函式取決于 USDT-DKP 對中兩種代幣的余額比率。 智能合約黑客概述: 攻擊者的交易:0x0c850f,0x2d31 攻擊者地址:0xF38 利用合同:0xf34ad ......

    uj5u.com 2023-04-07 07:46:09 more
  • Defi開發簡介

    Defi開發簡介 介紹 Defi是去中心化金融的縮寫, 是一項旨在利用區塊鏈技術和智能合約創建更加開放,可訪問和透明的金融體系的運動. 這與傳統金融形成鮮明對比,傳統金融通常由少數大型銀行和金融機構控制 在Defi的世界里,用戶可以直接從他們的電腦或移動設備上訪問廣泛的金融服務,而不需要像銀行或者信 ......

    uj5u.com 2023-04-05 08:01:34 more
  • solidity簡單的ERC20代幣實作

    // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; import "hardhat/console.sol"; //ERC20 同質化代幣,每個代幣的本質或性質都是相同 //ETH 是原生代幣,它不是ERC20代幣, ......

    uj5u.com 2023-03-21 07:56:29 more
  • solidity 參考型別修飾符memory、calldata與storage 常量修飾符C

    在solidity語言中 參考型別修飾符(參考型別為存盤空間不固定的數值型別) memory、calldata與storage,它們只能修飾參考型別變數,比如字串、陣列、位元組等... memory 適用于方法傳參、返參或在方法體內使用,使用完就會清除掉,釋放記憶體 calldata 僅適用于方法傳參 ......

    uj5u.com 2023-03-08 07:57:54 more
  • solidity注解標簽

    在solidity語言中 注釋符為// 注解符為/* 內容*/ 或者 是 ///內容 注解中含有這幾個標簽給予我們使用 @title 一個應該描述合約/介面的標題 contract, library, interface @author 作者的名字 contract, library, interf ......

    uj5u.com 2023-03-08 07:57:49 more
  • 評價指標:相似度、GAS消耗

    【代碼注釋自動生成方法綜述】 這些評測指標主要來自機器翻譯和文本總結等研究領域,可以評估候選文本(即基于代碼注釋自動方法而生成)和參考文本(即基于手工方式而生成)的相似度. BLEU指標^[^?88^^?^]^:其全稱是bilingual evaluation understudy.該指標是最早用于 ......

    uj5u.com 2023-02-23 07:27:39 more
  • 基于NOSTR協議的“公有制”版本的Twitter,去中心化社交軟體Damus

    最近,一個幽靈,Web3的幽靈,在網路游蕩,它叫Damus,這玩意詮釋了什么叫做病毒式營銷,滑稽的是,一個Web3產品卻在Web2的產品鏈上瘋狂傳銷,各方大佬紛紛為其背書,到底發生了什么?Damus的葫蘆里,賣的是什么藥? 注冊和簡單實用 很少有什么產品在用戶注冊環節會有什么噱頭,但Damus確實出 ......

    uj5u.com 2023-02-05 06:48:39 more