温故而知新 /比特币(Bitcoin)有关的 Base58 & Base58Check、私钥(Private KEY)、公钥(Public KEY)、地址(Address)

in cn •  7 years ago 

这两天在学习STEEM的交易签名,由于智商感人,所以进展缓慢。里边涉及有一些公钥私钥方面的内容,然后惊觉我之前对这部分内容的了解,已经忘干净了!从头再学,有些压力,还好之前学习的内容都记录在STEEMIT上,把之前的相关帖子都翻看一下,顺便摘录一些重点贴在这篇文章中,算是做笔记吧。

STEEM中照搬了借鉴了比特币(Bitcoin)的那一套东西,所以之前写的比特币(Bitcoin)一系列文章对自己还是很有参考价值的。

本文主要涉及以下方面内容:

  • Base58 & Base58Check
  • 私钥(Private KEY)
  • 公钥(Public KEY)
  • 地址(Address)

Base58 & Base58Check

因为涉及私钥、公钥的时候经常要用到Base58 & Base58Check编解码,所以首先简要介绍一下这两个东西。

Base58

Base58简单地说,就是把数字表示成不容易输入错误的文本编码,因为这组不容易出错的文本编码一共包含58个字符,所以叫Base58

编解码规则也很简单,编码就是把文本表示数字串,转换成一个大整数,然后再按58进制表示。

58进制和16进制类似,16进制数字0-15和0x0 - 0xF是一一对应的,而这个0-57,需要查表对应,仅此而已!解码就是逆过程!

码表为:
BASE58_ALPHABET = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

Base58Check

Base58Check在就是Base58基础上加上了版本信息以及校验,这样如果不小心输错一两个字符,就会检查出来。

Base58Check流程可以用下图表示:

Image source Here

整理成文字说明如下:

  • 把版本/程序信息字节和负载(payload)按字节连接到一起
  • 对结果一执行两次SHA256操作并取前四个字节
  • 按字节把结果一和结果二的四个字节连接起来
  • 把结果三当成一个大数字,对结果三执行Bash58编码
    (原链接第四步,分为4、5、6三个步骤,包括如何处理前导字节零)

私钥(Private KEY)

私钥是什么

私钥就是一个256位,取值处于1到n - 1之间的随机数
其中: n = 1.158 * 1077

私钥表示方式

私钥有几种表示方式

其中WIF亦即: Wallet Import Format (WIF)

  • 64位16进制串就是把私钥直接转换
  • Base58编码就是对64位16进制串直接编码 (https://blockchain.info中有用到)
  • WIF就是在64位16进制串对应的字节串前加上前缀0x80, 并用Base58Check编码
  • WIF-compressed就是在64位16进制串对应的字节串前加上前缀0x80,并加上后缀0x01, 并用Base58Check编码

私钥的生成

私钥可以用hashlib.sha256来生成(仅供参考,请勿使用)

>>> import hashlib
>>> from binascii import hexlify, unhexlify
>>> s = hashlib.sha256(bytes('Hello World', 'utf-8')).digest()
>>> print(hexlify(s).decode('ascii'))
a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e


公钥(Public KEY)

涉及到椭圆曲线等数学知识我就方了,直接上干货吧。

如何生成公钥

  • 公钥(K)可以通过椭圆曲线运算由私钥(k)计算得出
  • 私钥(k)公钥(K)计算公式:K=k∗G
  • 生成过程使用secp256k1标准中定义的椭圆曲线以及一组数学常量
  • 私钥(k)公钥(K)结果是确定的,并且只能单向运算
  • 使用Python的ecdsa库,可以轻松实现私钥(k)公钥(K)的计算

关于K=k∗G

其中小k是我们的私钥G生成点K是结果亦即公钥曲线上的另外一个点

因为生成点对所有的比特币用户都是相同的,所以同一个私钥k乘以生成点G,总会得到相同的公钥K。所以从k到K是确定的,并且只能单向运算。这就是为何比特币地址(由公钥生成)可以告诉任何人不用担心泄露私钥。

公钥压缩

公钥(K)是通过私钥(k)乘以生成点(G)得到的,并且是椭圆曲线上的一个点P(x, y)

点P(x, y)表示成公钥其实就是加上前缀04并把x和y连接起来

一共是520bits (8 + 256 + 256),使用16进制字符串表示,要130个字节,浪费网络资源。

公钥压缩原理:
根据椭圆曲线的方程,我们是可以通过x求得y的,所以我们只要保留x部分就可以了

公钥压缩流程:

公钥压缩的示意图( Source: 《Mastering Bitcoin》)

示例代码:私钥生成公钥

import ecdsa
from binascii import hexlify, unhexlify
secret = unhexlify('a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e')
order = ecdsa.SigningKey.from_string(secret, curve=ecdsa.SECP256k1).curve.generator.order()
p = ecdsa.SigningKey.from_string(secret, curve=ecdsa.SECP256k1).verifying_key.pubkey.point
x_str = ecdsa.util.number_to_string(p.x(), order)
y_str = ecdsa.util.number_to_string(p.y(), order)
compressed = hexlify(bytes(chr(2 + (p.y() & 1)), 'ascii') + x_str).decode('ascii')
uncompressed = hexlify(bytes(chr(4), 'ascii') + x_str + y_str).decode('ascii')
p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
x = int(hexlify(x_str).decode('ascii'), 16)
y = int(hexlify(y_str).decode('ascii'), 16)
(x ** 3 + 7 - y**2) % p


地址(Address)

比特币地址由公钥按固定流程生成。

生成流程如下:

根据地址生成流程可知:

  • 压缩公钥生成对应压缩公钥的地址
  • 未压缩公钥生成对应未压缩公钥的地址

地址和私钥本身是不压缩的,只是代表对应的公钥是压缩的而已

示例代码:公钥生成地址

def ripemd160(s):
        ripemd160 = hashlib.new('ripemd160')
        ripemd160.update(unhexlify(s))
        return ripemd160.digest()

def get_address(public_key):
        pkbin = unhexlify(public_key)
        addressbin = ripemd160(hexlify(hashlib.sha256(pkbin).digest()))
        address = base58CheckEncode(0x00, hexlify(addressbin).decode('ascii'))
        return address

参考资料(以前文章)

免责声明,本文为个人理解,示例仅供参考
因使用文中代码或地址造成的损失,概不负责!

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

讲的很详细的,但是发现看不懂的占绝大多数,我就放心了,😀

  ·  7 years ago 

记得很久之前想知道 WIF 是啥意思,一直没找到,结果才这里学到了,哈哈。

我知道啥叫wtf

awesome but can`t understand ur lang

虽然不太懂但感觉很cool

i will always support you man!!

腦細胞剩一個了..... T_T

看完我周二的大脑袋开始晕眩。。。反正只要你自己不丢,就都是特别特别安全很难很难解开的密码就是了。。

哈哈

智商感人➕1……

有种在读 Andreas M. Antonopoulos 的《Mastering Bitcoin》的感觉。

图都是从《Mastering Bitcoin》拿过来的啊 😀
是本超级好书,可惜我只读了一点点

之前看了一阵就停了,太多数学的东西看得好辛苦,读了你的理解再看回去应该会明白更多。

Good post!!Thank you:)

不错哦 椭圆曲线那部分说实话看了也看不懂 听了课 还是懵懵的

讲得挺详细,不过还没看太懂

Peace, mercy and blessings of God

沒想到你還真的有點料啊?我都帶泳褲來了,卻沒得游泳~~~~

那就把泳裤也脱了吧

很好的信息..投票给你

不明觉厉