地址產生方法如下:

  • 產生公鑰 P = s*G
  • 用公鑰產生壓縮或未壓縮的 SEC 格式
  • 對結果做 SHA-256,然後再做 RIPEMD160 (HASH160)
  • 加上前綴
  • 加上 4 bytes (32-bits) 的 checksum (double-sha256)
  • Base58 編碼

實作:

def address(self, compressed=True, testnet=False):
    sec = self.sec(compressed)
    h160 = hash160(sec)

    if testnet:
        prefix = b'\x6f'
    else:
        prefix = b'\x00'

    raw = prefix + h160
    checksum = double_sha256(raw)[:4]
    address = encode_base58(raw + checksum)
    return address.decode('ascii')

其中的 hash 函式是由 hashlib 引入:

BASE58_ALPHABET = b'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

def hash160(s):
    return hashlib.new('ripemd160', hashlib.sha256(s).digest()).digest()


def double_sha256(s):
    return hashlib.sha256(hashlib.sha256(s).digest()).digest()


def encode_base58(s):
    count = 0
    for c in s:
        if c == 0:
            count += 1
        else:
            break

    prefix = b'1' * count
    num = int(s.hex(), 16)
    result = bytearray()
    while num > 0:
        num, mod = divmod(num, 58)
        result.insert(0, BASE58_ALPHABET[mod])

    return prefix + bytes(result)

私鑰也有格式,稱為 WIF (Wallet Import Format),產生方式如下:

  • 私鑰本身是 256-bits 的數字
  • 用 16 進位表示
  • 加上前綴
  • 如果是壓縮格式加上後綴
  • 結尾加上 4-bytes 的 sha256 checksum
  • Base58編碼

定義 PrivateKey

class PrivateKey:

    def __init__(self, secret):
        self.secret = secret
        self.point = secret * G

    def hex(self):
        return '{:x}'.format(self.secret).zfill(64)

    def wif(self, compressed=True, testnet=False):
        secret_bytes = self.secret.to_bytes(32, 'big')

        if testnet:
            prefix = b'\xef'
        else:
            prefix = b'\x80'

        if compressed:
            suffix = b'\x01'
        else:
            suffix = b''

        return encode_base58_checksum(prefix + secret_bytes + suffix)

順便也實作簽名方法,讓私鑰本身可以當作被簽名的訊息

def sign(self, z):
    k = randint(0, 2**256)
    r = (k*G).x.num
    k_inv = pow(k, N-2, N)
    s = (z + r*self.secret) * k_inv

    if s > N/2:
        s = N - s

    return Signature(r, s)

results matching ""

    No results matching ""