Skip to content

密码学原理

🕒 Published at:

简介

加密货币主要用到密码学中的两个功能

  • 哈希函数
  • 签名

Hash Function(又名散列函数)

密码学中用到的哈希函数被称为 cryptographic hash function,他有几个重要的性质

哈希碰撞阻力(Collision resistance)

如果 x != y, 有 H(x) == H(y), 则被称为哈希碰撞。一般来说哈希碰撞是很难避免,因为输入空间远大于输出空间。举个例子,假设我们使用 256 位的哈希值作为输出,那么输出空间就有 2^256,但是输入空间却没有限制,输入可能是无限大的。

Collision resistence 并不是指不会有哈希碰撞,而是指没有高效的方法去人为地制造哈希碰撞。只能靠暴力求解,而这个在实际情况下是不可解的。 举个例子,给定一个 x,他的哈希值是 H(x),找一个 y,让 H(x)=H(y)。没有什么高效地方法去找 y,大部分情况下只能暴力枚举(brute-force) 所以,这个性质可以用来生成 msg 的签名 H(msg)。用来检测对于 msg 的篡改,因为如果 msg 被修改,hash 值 H(msg)也会随之改变。 理论上来说,没有哪一个哈希函数可以在数学上证明是 collision resistance。只是长久以来这么多的密码学专家和数学家都没有找到高效地人为制造哈希碰撞的方法,所以我们可以从经验上认为他是 collision resistance 的。另外,有些哈希函数,以前我们认为他是 collision resistance 的,但是后来人们找到了人为制造哈希碰撞的方法,所以他就不是 collision resistance 的了,比如 MD5,破解网站示例。

base64 是加密算法吗?

答:不是,base64 是一种用文本表示的二进制编码方式,是可逆的。

隐藏(Hiding)

hiding 指的是哈希函数的计算过程是不可逆的。

举个例子,给定一个值 x,可以算出他的哈希值 H(x);但是如果给定一个哈希值 H(x),并不能反推出他的输入值 x,也就是说,哈希值并不会泄漏有关他的输入值的任何信息,所以叫 hiding

但是实际上,hiding 也并不是完全成立的,同样我们可以用暴力枚举的方法,把所有可能的输入值都计算一遍,找到与我们想找的哈希值一样的值,那就找到了原始值,破解了他的 hiding

所以 hiding 这个属性成立的前提是,哈希函数的输入空间要足够大,让这种蛮力求解的方法不可行。而且输入的分布也要比较均匀 ,各种取值的可能性要是差不多的,因为如果取值集中在少数几个值,那么即使输入空间很大,那也是容易被破解的。

这个 hiding 的性质可以与 collision resistance 结合起来,用来 digital commitment。

举个例子,有一个人声称可以预测股市,那么有一种方法可以检验他是否预测准确,他提前一天公布自己的预测结果,当天去看他预测的对不对。这种方法看似可行,但是并不准确,假设他如果是一个名人,比如巴菲特,那么他提前公布预测结果可能会影响股市,因为大家会顺应他的预测结果去买卖股票。所以预测结果不能提前公开。

有一种更好的方式,他提前一天写好自己的预测结果,密封起来,交给第三方保管,等到当天再拆开比对结果。

但如何保证第三方的公正性?这里就可以使用哈希函数,他可以提前一天把自己的预测结果用哈希函数加密,然后把哈希值公布出来,当天再公开自己的预测结果。因为 hiding 的性质,大家不能通过他前一天公布的哈希值反推出他的预测结果,所以不会影响市场。而因为 collision resistance 的性质,大家能根据哈希值是否相等判断他当天公布的结果与前一天公布的是否一致。

当然,在这个例子下,其实输入空间并不满足要求,hiding 并不成立,因为股票就几千只,输入空间不够大。所以我们可以用特殊方法来处理,取一个随机数(nonce),计算哈希值的时候使用 H(msg+nonce),来保证输入值足够随机,分布足够均匀,输入空间足够大。

puzzle friendly

意思是指,哈希值的计算事先是不可预测的,也就是说你单看一个输入值,你是不能判断他的哈希值大概长什么样,或者落在什么范围的。如果你想找一个输入值,他的哈希值落在某个范围内,那么你只能暴力枚举,顺着一个个计算他的哈希值。

挖矿

挖矿本质上就是为了找一个 nonce,这个 nonce 和区块的块头里的其他信息合在一起作为输入,得到一个哈希值,这个哈希值要小与等于一个目标值 target。也就是不停地用不同的随机数去计算,直到满足条件

H(block header)<=target.

注意:nonce 本身就位于 block header 中

Puzzle friendly 的意思也就是说,挖矿的过程,没有捷径,只能通过不停地计算来得到,这个过程也叫做工作量证明(proof of work)

difficult to solve, but easy to verify

虽然挖矿的过程需要大量的计算来找到符合条件的 nonce,但是当挖矿完成后,他发布出去,其他人要验证他的 nonce 是不是符合要求却很容易,只需要一次哈希计算即可

常见的 hash function

btc 中用的哈希函数是 SHA-256,sha 的意思是 secure hash algorithm,这个算法满足 collision resistance、hiding、puzzle friendly

以太坊中的密码学哈希函数:Keccak-256,你会在以太坊的代码和文档中看到大量“SHA-3”的字样,这些多数都是指原始版本的 Keccak-256,而不是经过 SHA-3 标准化的 FIPS-202。

cosmos 中常用的是 sha-256

签名

账户管理

在本地创建一对公钥私钥(public key, private key),就可以作为加密货币中的账户

如何创建公钥和私钥?

涉及到钱包的部分,简单来说,钱包分为非确定性钱包、确定性钱包、分层确定性钱包(HD Wallet)

简单来说,就是先生成助记词,然后根据助记词生成种子,由种子生成私钥和一系列子私钥,我们从私钥开始,通过椭圆曲线乘法运算获得公钥

为什么私钥生成公钥要用椭圆曲线乘法运算?

答:因为椭圆曲线的乘法运算很容易,除法运算却很难,也就是说从私钥生成公钥很容易,但是从公钥反推私钥却几乎不可能。

公钥私钥是来源于非对称加密算法(asymmetric encryption algorithm),与之对应的是对称加密算法(symmetric encryption algorithm)

对称加密与非对称加密简单介绍

公钥相当于你的银行账号,别人想要给你转账,只需要知道你的公钥就行了。私钥相当于你的银行密码,知道这个私钥,就可以把这个账号的钱转走

前面我们提过,加密货币是不加密的,那这里的加密算法是用来干嘛的呢?实际上是用来签名的。

举个例子,小红向小明转账 1 个 btc,当在链上广播的时候,大家如何判断真的是小红向小明转账了,而不是冒名交易呢?可以用签名的方式,小红向小明转账的时候,会用自己的私钥对交易信息进行加密(也就是签名),大家收到广播的时候,就对这条信息用小红的公钥进行解密,看是否是正确的交易信息

既然账户是一对公私钥对,那么万一两个人生成了一样的公私钥对怎么办,那么就可以偷走另一外一个人的 btc?

答:理论上可行,实际不可行,假设是 256 位的公私钥,产生相同公私钥对的可能性微乎其微。当然,这就需要要求有很好的随机源;比如,btc 系统中一般都是先对一串交易 message 取 hash,然后再对 hash 进行签名

地址与公钥的关系?

答:地址是唯一标识符,从公钥通过哈希函数计算而来,比如以太坊地址就是通过 Keccak-256。

签名

数字签名是一种由两部分组成的数学方案:第一部分是使用私钥(签名密钥)从消息(交易)创建签名的算法;第二部分是允许任何人在给定消息和公钥时验证签名合法性的算法 比较常见的签名算法结构如下所示

使用另一个数学公式可以进行反向计算,也就是验证签名,不需要私钥,需要公钥(他的公式跟 Fsig 相对应,通常为椭圆曲线)

比特币和以太坊中使用的数字签名算法是椭圆曲线数字签名算法(Elliptic Curve Digital Signature Algorithm,也就是 ECDSA

Tendermint Core 中实现了多种数字签名算法,包括 ECDSA、Ed25519 以及 Sr25519,Tendermint Core 采用 Ed25519 数字签名算法完成共识投票过程中的投票,而 Cosmos-SDK 采用 ECDSA 进行交易的授权