比特币中的私钥、公钥和地址,类比我们现实生活中银行卡,私钥是密码,地址是卡号,公钥还没有恰当的类比。在转账过程中,我们有密码,知道对方的地址,就可以转账成功。谁拥有私钥,谁就可以花费这个钱;谁拥有发送地址对应的私钥,谁就能接收这笔钱。
在比特币种,私钥、公钥和地址三者的关系是这样的:
- 私钥:随机生成256位比特的二进制数字
- 公钥:由私钥通过椭圆曲线乘法生成
- 地址:公钥通过单向的加密哈希算法得到
如下图
私钥
比特币的私钥就是1~2^256中的一个数字,这个数字非常非常大,保证了比特币的私钥不会被破解。那到底2^256这个数字有多大呢?用十进制表示的话,大约是10^77,而可见宇宙被估计只含有10^80个原子。超级计算机“神威·太湖之光”的峰值性能为12.5亿亿次/秒,相当于10^17,如果用这台目前世界第一的超级计算来碰撞比特币私钥,需要10^60秒,也就是3*10^52年。我们可以得出这样的结论,通过碰撞破解比特币的私钥是不可能的。
比特币代码中生成私钥的方法是MakeNewKey,这个方法在文件key.cpp。循环通过GetStrongRandBytes通过伪随机数生成器生成私钥,然后检查是否符合要求,如果符合则跳出循环。
// 在key.cpp void CKey::MakeNewKey(bool fCompressedIn) { do { GetStrongRandBytes(keydata.data(), keydata.size()); } while (!Check(keydata.data())); fValid = true; fCompressed = fCompressedIn; } //在random.cpp void GetStrongRandBytes(unsigned char* out, int num) { assert(num <= 32); CSHA512 hasher; unsigned char buf[64]; // First source: OpenSSL's RNG RandAddSeedPerfmon(); GetRandBytes(buf, 32); hasher.Write(buf, 32); // Second source: OS RNG 操作系统熵值 GetOSRand(buf); hasher.Write(buf, 32); // Third source: HW RNG, if available. if (GetHWRand(buf)) { hasher.Write(buf, 32); } // Combine with and update state { std::unique_lock<std::mutex> lock(cs_rng_state); hasher.Write(rng_state, sizeof(rng_state)); hasher.Write((const unsigned char*)&rng_counter, sizeof(rng_counter)); ++rng_counter; hasher.Finalize(buf); memcpy(rng_state, buf + 32, 32); } // Produce output memcpy(out, buf, num); memory_cleanse(buf, 64); }
公钥
公钥是私钥通过椭圆曲线乘法生成的,只能通过私钥生成公钥,不能通过公钥逆推出私钥,这是不可逆转的过程。这个太过于复杂,等以后均益搞明白了,再详细说说。
地址
地址是通过公钥单向的加密哈希算法,这也是不可逆的。
以公钥 K 为输入,计算其SHA256哈希值,并以此结果计算RIPEMD160 哈希值,得到一个长度为160位(20字节)的数字:
A = RIPEMD160(SHA256(K))
在产生的长32个字节的哈希值(两次哈希运算)中,我们只取前4个字节。这4个字节就作为检验错误的代码或者校验和。校验码会添加到数据之后。
结果由三部分组成:前缀、数据和校验和。最后Base58编码。