私钥,公钥,地址

私钥是一个256的2进制数, 总数是有1.158 * 10^77,略小于2^256次

取值: 1 ~ 1.158 * 10^77 (这是一个很大的值,别想着去迭代出所有的私钥,去盗别人的币)

生成私钥

def get_private_key(k, format='wif'):
    '''
    format: wif
            hex
            compressed
            p2sh
    '''
    

生成公钥(公钥由私钥椭圆曲线方程算出)

K = k * G (k是私钥, G是生成点) 求生成点可以用下面方法算出 (拷自《精通比特币》)

import ecdsa
import os
from ecdsa.util import string_to_number, number_to_string
# secp256k1, http://www.oid-info.com/get/1.3.132.0.10

_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
_r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
_b = 0x0000000000000000000000000000000000000000000000000000000000000007
_a = 0x0000000000000000000000000000000000000000000000000000000000000000
_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
_Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
curve_secp256k1 = ecdsa.ellipticcurve.CurveFp(_p, _a, _b)
generator_secp256k1 = ecdsa.ellipticcurve.Point(curve_secp256k1, _Gx, _Gy, _r)
oid_secp256k1 = (1, 3, 132, 0, 10)
SECP256k1 = ecdsa.curves.Curve("SECP256k1", curve_secp256k1, generator_secp256k1,
oid_secp256k1)
ec_order = _r
curve = curve_secp256k1
generator = generator_secp256k1


def get_G(k):
    '''获取数值k对应的生成点
    ''' 
    p = k * generator
    return p.x(), p.y()


def get_public_key(k, compressed=True):
    '''compressed: 是否压缩
    compressed:
        如果y是基数: 公钥是 '02'+x
        如果y是偶数: 公钥是 '03'+y
    uncompressed:
        公钥就是 '04'+x+y
    '''
    x, y = get_G(k)
    if compressed:
        if y % 2:
            return '02' + hex(x)[:2]
        else:
            return '03' + hex(y)[:2]
    return '04' + hex(x)[:2] + hex(y)[:2]


def test_get_G():
    x, y = get_G(1)
    assert x == 55066263022277343669578718895168534326250603453777594175500187360389116729240
    assert y == 32670510020758816978083085130507043184471273380659243275938904335757337482424
    
    public_key = get_public_key(1)
    uncompressed_public_key = get_public_key(1, compressed=False)
    assert public_key == '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'
    assert uncompressed_public_key == '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'

公钥有两种表示方法

是否压缩 (在上面的python代码里有) 不压缩: 04 + 生成点的x + 生成点y值 压缩:如果 生成点y % 2==0: 02 + 生成点x值 else: 03 + 生成点y值

生成地址 (公钥先一次hash160[或者说sha256+ripemd160],然后base58 check encode)

import hashlib

def hash160(pubkey):
    return hashlib.new('ripemd160', hashlib.sha256(pubkey.encode()).digest()).digest()
  
def _get_checksum(p):
    return hashlib.sha256(hashlib.sha256(p).digest()).digest()
    
def _get_value(p):
    result = 0
    while len(p) > 0:
        result *= 256
        result += p[0]
        p = p[1:]
    return result

def _to_base58(val):
    base58_string = ''.join([chr(i) for i in range(58)])
    result_bytes = b''
    while val > 0:
       curcode = base58_string[val % 58]
       result_bytes = bytes([ord(curcode)]) + result_bytes
       val /= 58
    return result_bytes.decode()
    
def base58(p):
    p = bytes([0]) + p
    # 计算前导1
    leading = 0
    for i in p:
        if i != 0:
            breadk
        leading += 1
        
    # 计算checksum 
    checksum = _get_checksum(p)[:4]
    return '1' * leading + _to_base58(_get_value(p))

def get_address_from_pubkey(pubkey):
    p = hash160(pubkey)
    p = base58(p)
    return p

def test():
    assert '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH' == get_address_from_pubkey('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798')
    assert '1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm' == get_address_from_pubkey('0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8')