主页 > 怎么退出imtoken钱包 > 比特币源码研究(5)——私钥、公钥和地址
比特币源码研究(5)——私钥、公钥和地址
比特币中的私钥、公钥和地址类似于我们现实生活中的银行卡。私钥是密码,地址是卡号,公钥没有适当的类比。在转账过程中,我们有密码,知道对方的地址,转账就可以成功。谁有私钥,谁就可以花钱;谁拥有发送地址对应的私钥,谁就可以收到钱。
在比特币中,私钥、公钥和地址之间的关系如下:
私钥:随机生成的 256 位二进制数字。密钥由椭圆曲线乘法生成:公钥通过单向加密哈希算法得到
如下图
图片
私钥
比特币的私钥是一个1~2^256范围内的数字,非常非常大,保证了比特币的私钥不会被破解。那么数字 2^256 有多大呢?十进制大约是 10^77比特币私钥公钥地址,可见宇宙估计只有 10^80 个原子。超级计算机“神威太湖之光”的峰值性能为每秒12.50亿次,相当于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 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编码。