比特幣的私鑰,公鑰和地址是什麼?
原文:https://www.jianshu.com/p/af6328cc693e
在比特幣中,經常出現三個詞:私鑰,公鑰和地址
。他們是什麼意思呢?他們之間又有什麼樣的關係呢?搞清楚他們之間的關係和區別,是瞭解比特幣的基礎。
私鑰
先說說私鑰,一般我們看到的私鑰是下面這樣的一段字串:
5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss
支援比特幣協議的應用都可以正確把這段字串轉換成比特幣的私鑰,再轉換出公鑰,再得到一個地址,如果該地址上面有對應的比特幣,就可以使用這個私鑰花費上面的比特幣。
私鑰本質上是隨機數
私鑰本質上是一個隨機數,由32個byte組成的陣列,1個byte
1 ~ 0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4141
之間的數。這個數量已經超過了宇宙中原子的總數,想要遍歷所有的私鑰,耗盡整個太陽的能量也是不可能的。
我們所說的比特幣私鑰的是密碼學上面安全的,並不是說不可能出現重複的私鑰,而是說不可能通過遍歷的方式找到某一個特定的私鑰,或者通過其它的方式找,而不通過私鑰就能花費地址上面的比特幣,私鑰的安全性是由數學上保證的。
私鑰的總數量很大,但是私鑰的生成是依賴隨機數的,真正的隨機是很難做到的,大部分私鑰的生成都是依賴於偽隨機演算法(PRNG)
偽隨機是用函式生成隨機數。它並不真正是隨機的。只是一個比較近似真隨機的隨機數。
私鑰生成的隨機性就很重要的,密碼學上安全的隨機是指:
隨機是不可預測的,隨機的結果是不可遍歷的,如果不是安全的隨機數生成器,生成的私鑰就有可能被別人碰撞到。不依賴隨機生成的私鑰就會大大的降低其生成的概率空間。
公鑰和地址的生成都依賴私鑰,所以我們只需要儲存私鑰即可,有了私鑰就能生成公鑰和地址,就能夠花費對應地址上面的比特幣。
- 私鑰到字串
上面提高的私鑰字串是按照一定的規律從32位byte資料格式化生成的,32個byte的陣列是由256個0或者1組成的,如果顯示出來,不僅僅是識別率不高,而且私鑰太長。
因此私鑰字串就是對於原始的隨機數進行一定的轉換,轉換為識別率高的形式,上面私鑰的是對32個byte陣列就做了Base58
Base58是用於比特幣中使用的一種獨特的編碼方式,主要用於產生Bitcoin的錢包地址和私鑰。相比Base64,Base58不使用數字"0",字母大寫"O",字母大寫"I",和字母小寫"l",以及"+"和"/"符號。這樣做的主要原因是為了肉眼容易識別,在輸入的時候不容易打錯,
不過上面那段沒有規律的字串輸入起來還是挺費勁的,當然也可以把私鑰轉換其他形式,比如以單詞的形式(12或者24個單詞),腦錢包的形式,又或者自己記住的某一句話來生成私鑰,注意腦錢包生成的私鑰隨機的安全性並不高。
我們看到的私鑰除了以5開頭的以外,還有以L
和K
開頭的私鑰,為什麼會出現這樣的情況呢?5,L,K
又帶代表什麼呢?這就要說到公鑰了。
公鑰
比特幣的根基是橢圓曲線數字簽名演算法
:
橢圓曲線數字簽名演算法(ECDSA)是使用橢圓曲線密碼(ECC)對數字簽名演算法(DSA)的模擬
橢圓曲線加密法(ECC)
是一種公私鑰加密技術:
ECC以橢圓曲線理論為基礎,利用橢圓曲線等式的性質來產生金鑰,而不是採用傳統的方法利用大質數的積來產生,其特點是:金鑰長度小,安全效能高,整個數字簽名耗時小。
DSA(DigitalSignature Standard)數字簽名技術:
在DSA數字簽名和認證中,傳送者使用自己的私鑰對檔案或訊息進行簽名,接受者收到訊息後使用傳送者的公鑰來驗證簽名的真實性。
這裡明確了私鑰
用來簽名
,而公鑰
用來驗證簽名
。
公鑰是由私鑰生成的,通過橢圓曲線(ECPoint)
生成,一個私鑰經過橢圓曲線
變換之後能夠得到公鑰,公鑰是一個65個byte陣列,一般我們會看到這樣的一個公鑰:
04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235
顯示出的公鑰一般把byte陣列是經過hex(16進位制)
的處理之後顯示,不經過Base58的原因是: 公鑰是用來驗證私鑰的簽名,一般我們很少會看到公鑰,使用私鑰簽名交易之後,會把自己的公鑰一起和交易傳送出去,這樣對於一個完整的交易開說,他就使用交易裡包含的公鑰驗證私鑰的簽名是否正確。
私鑰和公鑰是成對出現的,一個私鑰簽名的資料,只有對應的公鑰才能對其進行驗證,而地址也是從公鑰生成的,這樣就可以驗證花費的交易是不是屬於這個地址了!
- 回答下上面的問題為什麼會出現5開頭或者L,K開頭的私鑰?
出現這種情況是因為公鑰的不同格式而產生了不同的私鑰格式,早期的比特幣開發者沒有使用壓縮的公鑰(橢圓曲線是對稱的,知道了一半的資訊就可以推匯出來另外一半的資訊了),因此只需要儲存一般的公鑰資訊即可。壓縮的公鑰只有33個byte,而未壓縮的公鑰有65個byte。
私鑰開頭的第一位的不同,是用來區分該私鑰使用的公鑰是否支援壓縮格式
壓縮的公鑰對比特幣的意義很大,比特幣是去中心化的p2p加密貨幣
,每個節點都會擁有完整的交易記錄,除了coinbase
(挖礦得到的比特幣)以外,每個交易都需要傳送公鑰,支援壓縮格式的公鑰,每個交易的資料就可以減少32個位元組,這對整個比特幣網路是非常有意義的,整個比特幣網路的資料在傳輸和儲存中都可以提高不少效率。
而對私鑰進行Base58編碼的時候,老版本未壓縮公鑰的私鑰是33位byte陣列,第一位存放私鑰的Version資訊
,當前值為128,生成的Base58都是以5開頭。
老版本未壓縮私鑰=Base58(version+32位隨機數)
支援壓縮公鑰的私鑰是34位,同樣是第一位是version資訊,它的值也是128,而多出來的一位是最後一個byte是用來存放是否壓縮資訊的資訊
,1就表示是支援壓縮格式的公鑰
。經過Base58處理之後正好是L或者K開頭
新版本私鑰格式=Base58(version+32位隨機數+是否支援壓縮)
例子中的私鑰不僅僅包含了32個byte陣列的資訊,還是私鑰version的資訊以及其公鑰是否壓縮的資訊(通過位數和值來判斷)
公鑰是否壓縮除了對私鑰的顯示有影響以外,還會對地址有影響。
地址
公鑰太長了,所以就有更短一些的地址的概念,另一方面沒有傳送過交易的地址,並不想暴露自己的公鑰,而地址是通過摘要演算法
生成的,不會暴露公鑰的真實內容:
地址是由公鑰產生的,地址長度為25byte,經過base58處理,地址未尾添加了4個位元組的校驗位。
我們看到的地址一般都是Base58
編碼處理的,地址的生成比較複雜,公鑰到地址生成的過程是,先對公鑰做一次SHA256
(雜湊演算法)。
sha-256-hash= SHA-256(public key)
再經過了hash160
處理, hash160:RIPEMD(PACE integrity Primitives Evaluation Message Digest)
是一種原始完整性校驗訊息摘要,160標準對應20位元組:
hash160=hash160(sha-256-hash)
對結果進行hash160處理可以得到一個20個byte的陣列,在這個20位的byte陣列前面再加上一個byte,這個byte就是地址的Version資訊,地址的Version當前值為0,Version資訊在比特幣的test網路
上會使用不同的值,比特幣地址完成的表示就是:
address=Base58(version+hash160(SHA-256(public key))+checksum)
checksum是用來對於比特幣地址進行檢驗的,再得到的hash160中加入地址的version資訊 ,再對該資訊做兩次SHA-256
之後取前4位就是checksum:
checksum=get_front_four( SHA-256(SHA-256(version+hash160)))
其中hash160是這個過程中最重要的資訊,從這個值就可以到地址的前21位(第一位是version)和後面的checksum, 進而可以生成Base58格式的地址。而從Base58格式的地址中也可以得到hash160,也就是說hash160格式可以和Base58格式的地址互換。
私鑰的不同對於地址有什麼樣的影響呢?
前面已經說了:
一個隨機數可以有一個壓縮的公鑰,和一個未壓縮的公鑰
而每個公鑰都會生成一個地址,上面私鑰其實可以有兩個地址分別為:
1HZwkjkeaoZfTSaJxDw6aKkxp45agDiEzN(未壓縮公鑰)
1F3sAm6ZtwLAUnj7d38pGFxtP3RVEvtsbV (壓縮公鑰)
這兩個地址都是這一個隨機數生成的地址,每個地址上面的比特幣都可以用這個隨機數對應的私鑰花費。目前大多數的應用預設都使用壓縮格式的私鑰。
- 總結
對於私鑰,公鑰和地址來說,公鑰
作為私鑰到地址的中間橋樑,他在交易的驗證是最關鍵的:對於一個交易的驗證,公鑰的作用:
- 公鑰生成地址,驗證傳送交易的地址是否和該公鑰生成的地址一致
- 公鑰驗證私鑰的簽名,用來驗證該交易是否使用了正確的私鑰簽名
- 私鑰生成公鑰是成對出現,公鑰可以生成對應的唯一地址,這樣就能確認了該地址傳送的交易是否使用了對應的私鑰