作者: cklover
本文首發於cklover知乎專欄,題目:【小白入門】比特幣使用的SHA256算法究竟是什麼?
都說比特幣是加密貨幣,既然叫加密貨幣,那麼比特幣必然和加密技術有關。話雖是這麼說,但是加密技術包括的內容很多,那麼比特幣究竟使用了那些密碼學技術呢?我們從整個比特幣的設計當中可以看到,在比特幣系統裡有一個比較重要的加密算法,這就是SHA256算法。
SHA256的中文全稱叫做“安全哈希算法”。
所謂的“哈希”是Hash的音譯,而Hash就是進行Hash函數的意思。通常來說,Hash函數的運算有一個共同特點。就是不論原始數據有多少位,只要通過Hash運算後,得到結果的長度都是固定的。
概念往往是抽象的,那麼下面我們就用一個形象的例子進行說明。如果我們去圖書館借書,就會發現不管是什麼圖書,書的側面都會貼著一張便簽,便籤上通常都有一個與圖書對應的編號。為了方便管理,這些編號的長度通常都是一樣的。這個情況和Hash函數就非常類似。我們可以把輸入Hash函數之前的數據看作是書本,這些書本的字數都不一樣,有的有幾萬字,有的有幾十萬字。但是一旦這些數據通過Hash函數處理過以後,就全部都變成長度相同的編號了。
而且這些編碼必須要滿足以下幾點要求:
第一、輸入Hash函數之前的數據和通過Hash函數處理過後得到的編號必須一一對應。
第二、每一個編號的長度都是固定的。
第三、我們無法通過編號倒推出數據的內容。
Hash函數的類型有很多種,包括SHA224、SHA256、SHA384、SHA512、SHA512/224、SHA512/256等。但是比特幣僅選用了SHA256。這個256代表的意思是,數據經過函數運算後得到的結果必須是一個256位的2進制數字。也就是類似這樣的結果:“001100……11011”,這其中一共有256位。
在比特幣裡,為什麼要把數據轉換成256位的數字呢?其實之所以選擇SHA256,主要是為了驗證兩個文件是否相等。
比如:有一個商業間諜獲得了一份重要的商業報告。但是這個間諜害怕這份商業報告在網上傳遞的過程中被別人截獲並進行修改。於是就把這份商業機密進行了處理,通過SHA256運算,生成了一個數值,我們暫且稱這個數值為A1。
然後這位間諜就把這份商業報告和A1通過電子郵箱傳遞了出去,並在郵件裡註明了:“為了避免其他人對商業報告進行修改,報告下載完成後,請大家對報告做一次SHA256運算,然後看看這個計算結果和A1是否相符。如果和A1完全一致,那麼就意味著這份商業報告沒有被其他人動過手腳。如果和A1不同,那麼就說明你下載的報告很可能被別人篡改過。”
中本聰在設計比特幣的時候之所以選擇SHA256,主要是看中了SHA256在驗證改動方面有著巨大的優勢。因為只要輸入數據有微小的區別,通過SHA256計算出來的數值都會有巨大的差距。
比如下面這三句話,原文雖然有微小的不同,但是通過Hash函數處理,就會讓SHA256值產生巨大的差異,而且這種差異是毫無規律可循的。
原文1:動靜不失,人所易明。
S1: 284c4ddd2e5ef97924cc70e90cd02fd792e3fd62
原文3:動靜不失,人所易明
S2:991780940ced6e6f910013f2ba2ac732e23601ef
原文3:動靜不失人所易明
S2:62e07ce4d7d529a6268841d521bf882d3b385199
SHA安全加密標準,是至今國際上使用最為廣泛的較為安全的壓縮算法之一,由美國NIST和NSA兩個組織共同開發。此算法於1993年5月11日被美國NIST和NSA設定為加密標準。
那麼比特幣是如何應用SHA256的呢?
我們拿一個日常情況為例子。
老王最近手頭緊,於是找老趙借錢,說等發工資了他就把借的錢還上。借錢自然要寫借條了。於是老王就給了老趙寫了一張借條:老王今天向老趙借了100元人民幣。但是如果單單是一張借條,是非常不安全的。萬一老趙日後把人民幣三個字改成了美元,又或者在100後加了個萬字,那老王豈不是虧大了?
在這種情況下,SHA256算法的價值就會凸顯出來了。 “老王今天向老趙借了100元人民幣。”這條信息的SHA256值是確定的,在發出這條信息的同時,我們再給出SHA256值,那麼之後任何的改動都會被發現。
但是只保證了支付信息沒有被改動過,也還是不夠的。如果老趙自製了很多“老王今天向老趙借了10億元人民幣。”這樣的借條。那麼老王這輩子恐怕都還不清債了。所以為了確定借條的唯一性,我們還要在藉條上加上簽名。這個步驟在比特幣系統中則體現為數字簽名。在比特幣系統裡,數字簽名是一段字符串,但這段字符串只有信息的發送者才能產生,別人無法偽造。這段字符串同時也是對信息的發送者發送信息真實性的一個有效證明。所以有了借條和數字簽名以後,支付信息的內容就可以被明確證明了。
現在支付信息可以確定了,但是還有另外一個問題。這就是我們又如何確定老王發了工資以後確實就能夠還上這100塊錢呢?
這個問題在中心化運作的系統裡不成問題。但是則比特幣不同,比特幣是去中心化的。在比特幣的系統裡,賬戶裡的錢有多少自己說了不算,因為沒人會相信你。要解決這個問題的話,就要用另一種方法。那就是每筆交易都必須把以前的交易作為基礎。當老王確定要還老趙的100塊錢時,那麼我們就要確定老王確實發工資了,工資額大於100元人民幣,而且這筆錢沒有用於其他支出。
於是在老王還錢的時候系統就會核實以下信息:
老王的公司給老趙發了1000元的工資,老王支付100元給老趙。然後再附上老王的數字簽名和公鑰。等老趙收到信息後,就會用SHA256算法進行確認,然後用私鑰解鎖。那麼這筆交易也就可以確認了。
我們看上面這個過程,好像是從老王的工資中扣除了100元給老趙。但是在比特幣系統中運行的實際情況並不是如此。
在比特幣系統中,老王是沒法把之前的1000塊錢拆成一個100塊和一個900塊的。因為這個網絡中每個支付信息都是由SHA256的簽名標記過的,無法再進行拆分。所以這個支付過程其實是這樣的。首先老王會一次過把1000塊錢全部打給老趙。然後老趙會還給老王900塊錢。
如果我們用現實世界的邏輯去看這個支付過程會覺得怪怪的。
你就不能一次給到位?怎麼非要別人找錢?
但是在比特幣系統裡,我們只能這麼支付。因為所有寫入賬本的信息必須以之前的交易為基礎。這就導致了,我們無法將一筆錢拆成兩個部分或者多個部分。
在比特幣被發明的時候SHA256被公認為全球最安全最先進的算法之一。到目前為止,仍然沒有公開的證據表明SHA256有漏洞,SHA256依舊牢牢抗住保衛比特幣安全的大旗。但回顧人類歷史,我們可以看到加密和解密總是相伴而生的。世界上沒有永遠安全的算法,SHA256被替代也是早晚的事,所以比特幣要想持續穩定的運行那就必須與時俱進,不斷升級完善。