橢圓曲線數(shù)字簽名算法
橢圓曲線數(shù)字簽名算法(ECDSA)是使用橢圓曲線對數(shù)字簽名算法(DSA)的模擬,該算法是構(gòu)成比特幣系統(tǒng)的基石。
私鑰
非公開,擁有者需安全保管。通常是由隨機算法生成的,說白了,就是一個巨大的隨機整數(shù),256位、32字節(jié)。大小介于1 ~ 0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4141之間的數(shù),都可以認為是一個合法的私鑰。于是,除了隨機方法外,采用特定算法由固定的輸入,得到32字節(jié)輸出的算法就可以成為得到私鑰的方法。于是,便有了迷你私鑰(Mini Privkey),原理很簡單,例如,采用SHA256的一種實現(xiàn):
private key = SHA256(<passphase>)
迷你私鑰存在安全問題,因為輸入集合太小,易被構(gòu)造常見組合的彩虹表暴力破解,所以通常還是使用系統(tǒng)隨機生成的比較好,無安全隱患。
公鑰
公鑰與私鑰是相對應(yīng)的,一把私鑰可以推出唯一的公鑰,但公鑰卻無法推導(dǎo)出私鑰。公鑰有兩種形式:壓縮與非壓縮。
早期比特幣均使用非壓縮公鑰,現(xiàn)大部分客戶端已默認使用壓縮公鑰。這個貌似是比特幣系統(tǒng)一個長得像feature的bug,早期人少活多代碼寫得不夠精細,openssl庫的文檔又不足夠好,導(dǎo)致Satoshi以為必須使用非壓縮的完整公鑰,后來大家發(fā)現(xiàn)其實公鑰的左右兩個32字節(jié)是有關(guān)聯(lián)的,左側(cè)(X)可以推出右側(cè)(Y)的平方值,有左側(cè)(X)就可以了。
現(xiàn)在系統(tǒng)里兩種方式共存,應(yīng)該會一直共存下去。兩種公鑰的首個字節(jié)為標識位,壓縮為33字節(jié),非壓縮為65字節(jié)。以0x04開頭為非壓縮,0x02/0x03開頭為壓縮公鑰,0x02/0x03的選取由右側(cè)Y開方后的奇偶決定。
壓縮形式可以減小Tx/Block的體積,每個Tx Input減少32字節(jié)。
簽名
使用私鑰對數(shù)據(jù)進行簽署(Sign)會得到簽名(Signature)。通常會將數(shù)據(jù)先生成Hash值,然后對此Hash值進行簽名。簽名(signature)有兩部分組成: R + S。由簽名(signature)與Hash值,便可以推出一個公鑰,驗證此公鑰,便可知道此簽名是否由公鑰對應(yīng)的私鑰簽名。
通常,每個簽名會有三個長度:73、72、71,符合校驗的概率為25%、50%、25%。所以每次簽署后,需要找出符合校驗的簽名長度,再提供給驗證方。
地址
地址是為了人們交換方便而弄出來的一個方案,因為公鑰太長了(130字符串或66字符串)。地址長度為25字節(jié),轉(zhuǎn)為base58編碼后,為34或35個字符。base58是類似base64的編碼,但去掉了易引起視覺混淆的字符,又在地址末尾添加了4個字節(jié)校驗位,保障在人們交換個別字符錯誤時,也能夠因地址校驗失敗而制止了誤操作。
由于存在公鑰有兩種形式,那么一個公鑰便對應(yīng)兩個地址。這兩個地址都可由同一私鑰簽署交易。
公鑰生成地址的算法:
Version = 1 byte of 0 (zero); on the test network, this is 1 byte of 111 Key hash = Version concatenated with RIPEMD-160(SHA-256(public key)) Checksum = 1st 4 bytes of SHA-256(SHA-256(Key hash)) Bitcoin Address = Base58Encode(Key hash concatenated with Checksum)
下圖是非壓縮公鑰生成地址的過程:
對于壓縮公鑰生成地址時,則只取公鑰的X部分即可。
推導(dǎo)關(guān)系
三者推導(dǎo)關(guān)系:私鑰 >> 公鑰 >> 兩個地址。過程均不可逆。擁有私鑰便擁有一切,但通常為了方便,會把對應(yīng)的公鑰、地址也存儲起來。
交易
比特幣的交易(Transation,縮寫Tx),并不是通常意義的交易,例如一手交錢一手交貨,而是轉(zhuǎn)賬。交易由N個輸入和M個輸出兩部分組成。交易的每個輸入便是前向交易的某個輸出,那么追蹤到源頭,必然出現(xiàn)一個沒有輸入的交易,此類交易稱為CoinBase Tx。CoinBase類交易是獎勵挖礦者而產(chǎn)生的交易,該交易總是位于Block塊的第一筆。
擁有一個輸入與輸出的Tx數(shù)據(jù):
Input: Previous tx: f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6 Index: 0 scriptSig: 304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d10 90db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501 Output: Value: 5000000000 scriptPubKey: OP_DUP OP_HASH160 404371705fa9bd789a2fcd52d2c580b65d35549d OP_EQUALVERIFY OP_CHECKSIG
一旦某個Tx的第N個輸出成為另一個Tx的輸入,那么該筆比特幣即為已花費。每個交易有唯一Hash字符串來標識,通過對交易數(shù)據(jù)做兩次SHA256哈希運算而來:
Tx Hash ID = SHA256(SHA256(Tx Data))
礦工費
礦工費(Transaction Fee)是鼓勵礦工將Tx打包進Block的激勵報酬。計算一筆交易的礦工費:
Transaction Fee = SUM(Input's amount) - SUM(Output's amount)
每筆Tx的礦工費必然大于等于零,否則該筆Tx即為非法,不會被網(wǎng)絡(luò)接收。
數(shù)據(jù)塊
數(shù)據(jù)塊(Block)是存儲Block Meta與Tx的地方。Block的第一筆Tx總是CoinBase Tx,因此Block中的交易數(shù)量總是大于等于1,隨后是這段時間內(nèi)網(wǎng)絡(luò)廣播出來的Tx。
找到合適的Block是一件非常困難的事情,需要通過大量的數(shù)學(xué)計算才能發(fā)現(xiàn),該計算過程稱為“挖礦”。首個發(fā)現(xiàn)者,會得到一些比特幣作為獎勵。
數(shù)據(jù)鏈
多個Block連接起來成為數(shù)據(jù)鏈(Block Chain)。
為了引入容錯與競爭機制,比特幣系統(tǒng)允許Block Chain出現(xiàn)分叉,但每個節(jié)點總是傾向于選擇最高的、難度最大的鏈,并稱之為Best Chain,節(jié)點只認可Best Chain上的數(shù)據(jù)。
首個Block稱為Genesis Block,并設(shè)定高度為零,后續(xù)每新增一個Block,高度則遞增一。目前是不允許花費Genesis Block中的比特幣的。
- 每個Block中的Tx在此Block中均唯一
- 一個Tx通常只會在一個Block里,也可能會出現(xiàn)在多個Block中,但只會在Best Chain中的某一個Block出現(xiàn)一次
貨幣存儲
比特幣是密碼貨幣、純數(shù)字化貨幣,沒有看得見摸得著的硬幣或紙幣。一個人持有比特幣意味著:
- 其擁有一些地址的私鑰
- 這些地址是數(shù)筆交易的輸出,且未花費
所有貨幣記錄均以交易形式存儲在整個blockchain數(shù)據(jù)塊中,無交易無貨幣。貨幣不會憑空產(chǎn)生,也不會憑空消失。遺失了某個地址的私鑰,意味著該地址上的Tx無法簽署,無法成為下一個Tx的輸入,便認為該筆比特幣永久消失了。
貨幣發(fā)行
既然所有交易的輸入源頭都是來自CoinBase,產(chǎn)生CoinBase時即意味著貨幣發(fā)行。比特幣采用衰減發(fā)行,每四年產(chǎn)量減半,第一個四年每個block的coinbase獎勵50BTC,隨后是25btc, 12.5btc, …并最終于2140年為零,此時總量達到極限為2100萬個btc。
減半周期,嚴格來說,并不是準確的四年,而是每生成210000個block。之所以俗稱四年減半,是因為比特幣系統(tǒng)會根據(jù)全網(wǎng)算力的大小自動調(diào)整難度系統(tǒng),使得大約每兩周產(chǎn)生2016個block,那么四年約21萬塊block。
該函數(shù)GetBlockValue()用于計算挖得Block的獎勵值:
int64 static GetBlockValue(int nHeight, int64 nFees) { int64 nSubsidy = 50 * COIN; // Subsidy is cut in half every 210000 blocks, which will occur Approximately every 4 years nSubsidy >>= (nHeight / 210000); return nSubsidy + nFees; }
當達到2100萬btc以后,不再有來自CoinBase的獎勵了,礦工的收入來源僅剩下交易的礦工費。此時,每個block的收入絕對值btc很低,但此時比特幣應(yīng)當會非常繁榮,幣值也會相當?shù)母撸沟玫V工們依然有利可圖。
杜絕多重支付
傳統(tǒng)貨幣存在多重支付(Double Spending)問題,典型的比如非數(shù)字時代的支票詐騙、數(shù)字時代的信用卡詐騙等。在比特幣系統(tǒng)里,每筆交易的確認均需要得到全網(wǎng)廣播,并收錄進Block后才能得到真正確認。每筆錢的花銷,均需要檢測上次輸入交易的狀態(tài)。數(shù)據(jù)是帶時間戳的、公開的,BlockChain由巨大的算力保障其安全性。所以比特幣系統(tǒng)將貨幣的多重支付的風險極大降低,幾近于零。通過等待多個Block確認,更是從概率上降低至零。一般得到6個確認后,可認為非常安全。但對于能影響你人生的重大支付,建議等待20~30個確認。
匿名性
任何人均可以輕易生成大量的私鑰、公鑰、地址。地址本身是匿名的,通過多個地址交易可進一步提高匿名性。但該匿名性并不像媒體宣傳的那樣,是某種程度上的匿名。因為比特幣的交易數(shù)據(jù)是公開的,所以任何一筆資金的流向均是可以追蹤的。
不了解比特幣的人為它的匿名性產(chǎn)生一些擔憂,比如擔心更利于從事非法業(yè)務(wù);了解比特幣的人卻因為它的偽匿名性而苦惱。傳統(tǒng)貨幣在消費中也是匿名的,且是法律保障的,大部分國家都不允許個人涂畫紙幣。
地址本身是匿名的,但你可以通過地址對應(yīng)的私鑰簽名消息來向公眾證明你擁有某個比特幣地址。
其他名詞
哈希
哈希(Hash)是一種函數(shù),將一個數(shù)映射到另一個集合當中。不同的哈希函數(shù)映射的空間不同,反映到計算機上就是生成的值長度不一樣。同一個哈希函數(shù),相同的輸入必然是相同的輸出,但同一個輸出卻可能有不同的輸入,這種情況稱為哈希碰撞。
常見的哈希函數(shù)有CRC32, MD5, SHA1, SHA-256, SHA-512, RIPEMD-160等,哈希函數(shù)在計算中有著非常廣泛的用途。比特幣里主要采用的是SHA-256和RIPEMD-160。
腦錢包&紙錢包
前面提到過的腦錢包與紙錢包,這其實不算是錢包的分類,只是生成、存儲密鑰的方式而已。腦錢包屬于迷你私鑰的產(chǎn)物。腦錢包就是記在腦袋里的密鑰,紙錢包就是打印到紙上的密鑰,僅此而已。
有同學(xué)提到過,以一個計算機文件作為輸入,例如一個數(shù)MB大小的照片,通過某種Hash運算后得到私鑰的方法。這個方案的安全性還是不錯的,同時可以防止盜私鑰木馬根據(jù)特征掃描私鑰。文本形式存儲私鑰是有特征的,而一個照片文件卻難以察覺,即使放在云盤等第三方存儲空間中都是安全的。