区块链钱包 - 1 公私钥生成原理及私钥管理

大纲:

  • 以比特币为例子介绍一下如何做签名和验证
  • 介绍密码学中的椭圆曲线函数生成公钥
  • 介绍比特币中的公钥使用哈希算法生成私钥

公私钥原理

公钥和私钥是基于密码学的概念,密码学可以用来证明数据的真实性(数字指纹)。在 Bitcoin 的世界里,bitcoin 的所有权是通过数字密钥、比特币地址和数字签名来确定的。

在计算机信息安全的发展过程中,在公钥加密被发明后,一些函数如素数幂和椭圆曲线乘法被发现,这些函数的特点是:不可逆,意思就是可以容易得从一个方向计算,但不可以反向推导。基于这种特性,生成数字密钥和不可伪造的数字签名就成为了可能。

公钥和私钥的数学关系,使得私钥可以生成特定消息的签名,签名可以在不泄露私钥的情况下同时对公钥进行验证。

私钥

私钥在本质上是一个随机数,这个随机数是用256bit进行表示的,关键的问题就在于如何安全的生成这个随机数。比特币软件使用操作系统底层的随机数生成器来产生256位的熵(随机性)。

不要自己写代码或使用你的编程语言提供的简易随机数生成器来获得一个随机数。使用密码学安全的伪随机数生成器(CSPRNG),并且需要有一个来自具有足够熵值的源的种子。使用随机数发生器的程序库时,需仔细研读其文档,以确保它是加密安全的。正确实施CSPRNG是密钥安全性的关键所在。

其实,这个随机数是一个非常大的数,十进制表示的话是 10^77, 整个宇宙估计也只含有 10^80 个原子。所以,如果真的想碰巧生成一对相同的私钥,比登天还难。

公钥

公钥是通过椭圆曲线乘法从私钥计算得到的,之前提过,椭圆曲线函数是一个不可逆的过程:K = k * G,k 是私钥,G 是一个常数,K 就是公钥。他的反向运算就是“寻找离散对数”。

ECC

椭圆曲线的数学原理中有几个点需要知道:

  • 有一个点被称为“无穷远点”,有点类似于我们认知中的 0 的作用
  • 椭圆曲线的加发运算:给定椭圆曲线上的两个点P1和P2,椭圆曲线上必定有第三个点P3 = P1 + P2
  • P3 可以通过画一条直线来确定:这条直线和椭圆曲线相交于另外一个点,P3’ = (x, y), 那么P3 = (x, -y)
  • 若 P1 和 P2 是同一点,则 P1 和 P2 的连线就是 P1 的切线,曲线上有且仅有一个点于该切线相交
  • 若 P1 和 P2 具有相同的 x 值,不同的 y,那么切线就完全垂直,P3 就是“无穷远点”
  • 若 P1 是“无穷远点”,P1 + P2 = P2,反之亦然
  • 曲线函数里的 + 符合结合律
  • 椭圆加法:kP = P + P + … + P (k次)

曲线函数

y^2 = x^3 + ax + b

比特币使用的曲线函数

y^2 = x^3 + 7

生成公钥

K = k * G, G 是生成点,是固定不变的,是 ECC 上的一个点;k 是随机生成的私钥,它是一个随机数,一个很大的随机数;那么,对 G 经过 k 次的椭圆曲线加法操作后就得到最终的点,这个点就是公钥 K。

So, K = (x, y), 举个例子

1
2
K = 1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD * G
K = (x, y) = (F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A, 07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB)

数学原理就是借助椭圆曲线函数,将G相加k次。在椭圆曲线中,点的相加等同于从该点画切线找到与曲线相交的另一 点,然后翻折到x轴。

比特币地址

地址的生成使用到了哈希算法;哈希算法是一种单向函数,接收任意长度的输入产生定长的指纹或哈希,具体的算法是:SHA256 和 RIPEMD160。

以公钥 K 为输入,计算其 SHA256 哈希值,并以此结果计算 RIPEMD160 哈希值,得到一个长度为160位(20字节)的数字:
A = RIPEMD160(SHA256(K))

地址生成过程

小插曲 - Base58Check

Base58 Check

数字签名

比特币中使用的数字签名算法是椭圆曲线数字签名算法ECDSA。 ECDSA是用于基于椭圆曲线私钥/公钥对的数字签名的算法。

  • 签名证明私钥的所有者,即资金所有者,已经授权支出这些资金
  • 授权证明是不可否认的(不可否认性)
  • 签名证明交易(或交易的具体部分)在签字之后没有也不能被任何人修改。

数字签名是一种由两部分组成的数学方案:第一部分是使用私钥(签名密钥)从消息(交易)创建签名的算法; 第二部分是允许任何人验证签名的算法,给定消息和公钥。

ECDSA 算法签名过程

((Sig = F{sig}(F{hash}(m), dA)))

  • dA 是签名私钥
  • m 是交易(或其部分)
  • F{hash} 是散列函数
  • F{sig} 是签名算法
  • Sig 是结果签名, Sig = (R, S), 签名结果有两个值组成,然后对Sig进行 Der 序列化

ECDSA 算法验证签名

要验证签名,必须有签名(R和S)、序列化交易和公钥(对应于用于创建签名的私钥)。本质上,签名的验证意味着“只有生成此公钥的私钥的所有者,才能在此交易上产生此签名。”

签名验证算法采用消息(交易或其部分的哈希值)、签名者的公钥和签名(R和S值),如果签名对该消息和公钥有效,则返回 TRUE 值

钱包

广义上,钱包是一个应用程序,为用户提供交互界面。 钱包控制用户访问权限,管理密钥和地址,跟踪余额以及创建和签名交易。 狭义上,即从程序员的角度来看,“钱包”是指用于存储和管理用户密钥的数据结构。

有两种主要类型的钱包,区别在于它们包含的多个密钥是否相互关联。

  • 第一种类型是非确定性钱包(nondeterministic wallet),其中每个密钥都是从随机数独立生成的。密钥彼此无关。这种钱包也被称为“Just a Bunch Of Keys(一堆密钥)”,简称JBOK钱包。

  • 第二种类型是确定性钱包(deterministic wallet),其中所有的密钥都是从一个主密钥派生出来,这个主密钥即为种子(seed)。该类型钱包中所有密钥都相互关联,如果有原始种子,则可以再次生成全部密钥。确定性钱包中使用了许多不同的密钥推导方法。最常用的推导方法是使用树状结构,称为分级确定性钱包或HD钱包

Ref