公钥算法

理解一下公钥算法:

椭圆曲线参数:
a=0
b=7

p=115792089237316195423570985008687907853269984665640564039457584007908834671663

p_hex='%64x'%p
p_hex=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f

order=115792089237316195423570985008687907852837564279074904382605163141518161494337
order_hex='%64x'%order
order_hex=fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141


# ECDSA curve using secp256k1 is defined by: y**2 = x**3 + 7
# This is done modulo p which (secp256k1) is:
# p is the finite field prime number and is equal to:
# 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
# Note that we could also get that from ecdsa lib from the curve, e.g.:
# SECP256k1.__dict__['curve'].__dict__['_CurveFp__p']
_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
# Curve's a and b are (y**2 = x**3 + a*x + b)
_a = 0x0000000000000000000000000000000000000000000000000000000000000000
_b = 0x0000000000000000000000000000000000000000000000000000000000000007
# Curve's generator point is:
_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
_Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
# prime number of points in the group (the order)
_order = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141

# The ECDSA curve (secp256k1) is:
# Note that we could get that from ecdsa lib, e.g.:
# SECP256k1.__dict__['curve']
_curve = ellipticcurve.CurveFp( _p, _a, _b )

# The generator base point is:
# Note that we could get that from ecdsa lib, e.g.:
# SECP256k1.__dict__['generator']
_G = ellipticcurve.Point( _curve, _Gx, _Gy, _order )



y^2 \mod{p} = (x^3+7)\mod{p}
mod: 取余符号
P:一个很大的素数
x:自变量
y:因变量
secp256k1标准通过特别的算法,使得生成曲线的速度比别的曲线快30%。这在移动端等小型设备上是非常重要的。

对于比特币中的椭圆曲线算法,需要明确知道的是(p,a,b,G,n,h)。p是Fp的模的范围,比特币中定义的是:

p = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F = 2^256 − 2^32 − 2^9 − 2^8 − 2^7 − 2^6 − 2^4 − 1
p = pow(2,256)-pow(2,32)-pow(2,9)-pow(2,8)-pow(2,7)-pow(2,6)-pow(2,4)-1
p = 2**256-2**32-2**9-2**8-2**7-2**6-2**4-1
a,b是椭圆曲线的参数,a=0,b=7。
G是基点,可以理解为椭圆曲线中第一个点,列如前面的P。比特币中定义的点G 为 (02 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798,483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448 A6855419 9C47D08F FB10D4B8)。
n 是基点G的可倍积阶数,定义为能够使得点倍积nG 不存在的最小的整数n,比特币中它的值为:FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141。
h是一个整数常量,它跟椭圆曲线运算中得到点的集合以及 n 有关,
h 一般取值为01。比特币中也是01。



当i=1时


x=55066263022277343669578718895168534326250603453777594175500187360389116729240

y=32670510020758816978083085130507043184471273380659243275938904335757337482424

x_hex='%64x'%x
y_hex='%64x'%y
x_hex=0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
y_hex=0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8


非压缩公钥:前缀+x坐标+y坐标
前缀为'04'
pub=0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8

压缩公钥:前缀+x坐标
y为偶数时,前缀为'02'
y为奇数时,前缀为'03'
pub_compress=0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798



非压缩公钥:
@staticmethod
    def private_to_uncompressed_public(private_key):
        private_key_bytes = codecs.decode(private_key, 'hex')
        # Get ECDSA public key
        key = ecdsa.SigningKey.from_string(
            private_key_bytes, curve=ecdsa.SECP256k1).verifying_key
        
        key_bytes = key.to_string()
        key_hex = codecs.encode(key_bytes, 'hex')
        
        # Add bitcoin byte
        bitcoin_byte = b'04'
        public_key = bitcoin_byte + key_hex
        return public_key
#压缩公钥
    @staticmethod
    def private_to_compressed_public(private_key):
        private_key_bytes = codecs.decode(private_key, 'hex')
        # Get ECDSA public key
        key = ecdsa.SigningKey.from_string(private_key_bytes, curve=ecdsa.SECP256k1).verifying_key
        key_bytes = key.to_string()
        key_hex = codecs.encode(key_bytes, 'hex')
        x = key_hex[0:64]
        y = key_hex[64:]
        # print(x)
        # print(y)
        inty = int(y.decode('utf8'), 16)
        # Add bitcoin byte
        if(inty % 2 != 0):
            bitcoin_byte = b'03'
        else:
            bitcoin_byte = b'02'
        public_key = bitcoin_byte + x
        return public_key