BTC-比特币的数字签名与安全问题
我们用支付宝付款时,需要输入密码或通过其它方式验证身份,借以控制自己的账户。对于比特币,如何证明你发出的支付信息是你发出的呢?如何确保发出的信息不被篡改呢?换言之,如何控制自己的比特币呢?这就涉及到一种叫数字签名的技术了。
与银行开户不同,比特币的账户无需申请注册,可随机生成。首先,我们可以随机生成一个私钥,私钥也是一个256位的二进制数。抛256次硬币,正面朝上记成1,反面朝上记成0,这样也能随机生成一个私钥。然后用椭圆曲线数字签名算法(ECDSA)对私钥进行运算,生成公钥,再对公钥进行哈希运算,就得到了地址。私钥生成公钥的过程也是不可逆的,从公钥无法反推私钥,想试出私钥得试到天荒地老。用椭圆曲线数字签名算法生成的公钥可以配合私钥,进行非对称加密。
非对称加密是什么意思呢?我们先来了解一下对称加密,对称加密中,加密解密的密钥都是一样的。比如有一条信息是1234567,我们用密钥9对它进行加密,1234567×9就得到了密文11111103,解密的时候11111103÷9就解密出了1234567,加密解密的密钥都是9(当然实际的加密解密过程肯定比我这个例子复杂得多)。但在非对称加密中,加密解密的密钥则互不相同。
比特币里,私钥可以用来加密信息,而公钥则用来解密该信息。比特币里没有人的概念,只有地址的概念,提到你有多少个比特币,其实是说你的地址上有多少个比特币。那要怎么才能控制你地址上的币呢?就要靠私钥。公钥和地址都可以公开,但私钥一定不能泄露。
比如小明要给小强一个比特币,小明的比特币地址是A,小强的比特币地址是B,小明就要将“A地址给B地址一个比特币”这条账单进行哈希运算,得到的哈希值再用A地址的私钥加密,加密得到的密文连同A地址的公钥、“A地址给B地址一个比特币”这条账单一起,广播出去。收到该信息的人会进行检查,计算公钥得到地址,判断该信息中公钥和地址是否对应,再用公钥把密文解密成哈希值,同时也对账单进行哈希运算,得到另一个哈希值。这时候比较一下两个哈希值,如果哈希值相同,就说明这条信息确实是地址的主人发出的,也没有被篡改。
如果有人伪造了“A地址给B地址一个比特币”这一信息,首先,伪造信息里A的公钥不能变,因为公钥可以推算出地址,变了公钥推算出的地址就会与A不符,别人立马就能发现这是假消息了。其次,伪造者没有A地址的私钥,他伪造的账单哈希值密文必然与真实密文不同,这时候别人用公钥解密,解密出的哈希值也必然不同于用账单计算出的哈希值,这条信息就肯定不真实。还有一种情况是信息内容遭到篡改,比如把信息篡改成“A地址给B地址十个比特币”,这种情况下,账单变了,但公钥和账单哈希值密文都没变。按上面的思路分析一遍,你也会发现,篡改信息会导致两个哈希值相异。
可以看出,私钥犹如地址对应的一支独一无二的签字笔,能签出独一无二的签名,证明你是对应地址的主人,所以我们也把该过程称为数字签名。你用私钥签名了,你这个地址的付款信息才会被别人接受。要是你丢了私钥,你就无法使用地址上的币,尽管你地址上有多少币都是清清楚楚地记录在区块链账本上的。要是别人知道了你的私钥,他就可以转走你地址上的币,比特币的世界里,是只认私钥不认人的。所以,说私钥安全性重于泰山也不为过。
不过,私钥并不像登录时输入的密码,它本身是可以完全不触网的,完全可以在离线状态下对付款信息签名(其实就是用私钥加密付款信息的哈希值),然后把付款信息和签名信息发送到网上即可,别人也无法从签名反推私钥,这是由椭圆曲线数字签名算法的性质决定的。比特币的“钱包”,存放的不是币而是私钥,所谓的“冷钱包”就是不联网的钱包,可以有效防御黑客盗取私钥。用比特币钱包付款时输入的密码,实际上起到的作用是授权调用私钥进行签名,而非是私钥本身。
由于地址之类信息用二进制表示非常长,比特币采取了一种叫Base58的编码方式,将二进制数转换成58进制数表示,所以我们看到的地址之类信息就是一串大小写字母和数字的组合。
为便于记忆及管理私钥,人们又设计出了助记词,助记词一般是12个单词,出自2048个常见单词构成的词库,助记词对应着一个随机生成的种子,是种子一种易于记忆的形式。种子可生成一个主私钥,主私钥可通过确定性的、不可逆的算法,生成多个币种的子私钥,子私钥又可继续生成孙私钥……子子孙孙无穷匮也。这样,用一组助记词就可以统一管理多个币种的多个私钥,省去了很多麻烦,这样的加密货币钱包,被称为HD钱包(分层确定性钱包)。不要以为助记词只有12个词就不安全,2048^12≈5.4×10^39是个天文数字,指望随机输入助记词碰巧试出一个有币的地址,是根本不可能的。
需要补充的是,比特币记账实际上是UTXO(未花费的交易输出)模型,比特币的账户余额实际上是地址上的UTXO总和。UTXO模型类似于不断销毁用掉的旧币又不断创造可用的新币。