《区块链编程》-第三章

Posted 从化北

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《区块链编程》-第三章相关的知识,希望对你有一定的参考价值。

《区块链编程》第三章

椭圆曲线数字签名算法

名称解释

一定配合着书看。
如下的名词解释不足以解释椭圆曲线数字签名算法的细节。 具体内容还要看书中的详细解释。

  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, 

以上是关于《区块链编程》-第三章的主要内容,如果未能解决你的问题,请参考以下文章

《筱静观察》第三季第6期丨区块链安全及其应用

区块链网络架构

区块链应用编程开发培训班

合作推广 | 第三届 Blockchain Connect 全球区块链峰会

什么是区块链

第三方可以向以太坊区块链发送 ERC20 代币交易吗?