比特幣中的私鑰泪喊、公鑰和地址,類比我們現實生活中銀行卡髓涯,私鑰是密碼袒啼,地址是卡號,公鑰還沒有恰當的類比纬纪。在轉賬過程中蚓再,我們有密碼,知道對方的地址包各,就可以轉賬成功对途。誰擁有私鑰,誰就可以花費這個錢髓棋;誰擁有發(fā)送地址對應的私鑰,誰就能接收這筆錢。
在比特幣種按声,私鑰膳犹、公鑰和地址三者的關系是這樣的:
- 私鑰:隨機生成256位比特的二進制數字
- 公鑰:由私鑰通過橢圓曲線乘法生成
- 地址:公鑰通過單向的加密哈希算法得到
如下圖
私鑰
比特幣的私鑰就是1~2^256 中的一個數字,這個數字非常非常大签则,保證了比特幣的私鑰不會被破解须床。那到底2^256 這個數字有多大呢?用十進制表示的話渐裂,大約是10^77 豺旬,而可見宇宙被估計只含有10^80 個原子。超級計算機“神威·太湖之光”的峰值性能為12.5億億次/秒柒凉,相當于10^17 ,如果用這臺目前世界第一的超級計算來碰撞比特幣私鑰族阅,需要10^60 秒,也就是3*10^52年膝捞。我們可以得出這樣的結論坦刀,通過碰撞破解比特幣的私鑰是不可能的。
比特幣代碼中生成私鑰的方法是MakeNewKey,這個方法在文件key.cpp蔬咬。循環(huán)通過GetStrongRandBytes通過偽隨機數生成器生成私鑰鲤遥,然后檢查是否符合要求,如果符合則跳出循環(huán)林艘。
// 在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字節(jié))的數字:
A = RIPEMD160(SHA256(K))
在產生的長32個字節(jié)的哈希值(兩次哈希運算)中宇植,我們只取前4個字節(jié)。這4個字節(jié)就作為檢驗錯誤的代碼或者校驗和埋心。校驗碼會添加到數據之后指郁。
結果由三部分組成:前綴、數據和校驗和拷呆,最后Base58編碼闲坎。
作者:區(qū)塊鏈研習社比特幣源碼研讀班疫粥,均益
原文地址:http://junyiseo.com/bitcoin/546.html