比特币中的私钥、公钥和地址,类比我们现实生活中银行卡,私钥是密码,地址是卡号,公钥还没有恰当的类比。在转账过程中,我们有密码,知道对方的地址,就可以转账成功。谁拥有私钥,谁就可以花费这个钱;谁拥有发送地址对应的私钥,谁就能接收这笔钱。
在比特币种,私钥、公钥和地址三者的关系是这样的:
- 私钥:随机生成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编码。
作者:区块链研习社比特币源码研读班,均益
原文地址:http://junyiseo.com/bitcoin/546.html