比特幣挖礦的背後 — SHA 與雜湊現金

陳鍾誠
程式人月刊
Published in
7 min readJun 5, 2018

比特幣的技術

最近筆者想瞭解比特幣的運作原理,於是找來比特幣的發明人「中本聰」的 Bitcoin 論文,研讀了一番,該論文可在「比特幣的官方網站」上看到,網址如下:

研讀了該論文之後,筆者寫了一篇「介紹比特幣運作原理」的文章,打算放在 2014 年 1 月 1 日出刊的「程式人雜誌」當中,目前該文暫時還在筆者的 dropbox 帳號內公開,連結如下:

雜湊現金

寫完「比特幣 (Bit Coin) 的運作原理」這篇文章之後,筆者發現比特幣裏最關鍵的技術是一種稱為「雜湊現金」(hashcash) 的技術,這種技術其實與金錢沒什麼關係,而是與 CPU 計算出某個雜湊值所需要花的時間有關係。1997 年,Adam Back 提出了雜湊現金的技術,後來這個技術逐漸展現強大的用途,於是 Adam Back 於 2002 年又寫了一篇介紹「雜湊現金與其應用」的論文如下:

要瞭解這種雜湊現金技術,必須先瞭解「單向雜湊函數」的概念,所謂的單向雜湊函數 (One Way Hash Function),就像是一般資料結構中建立雜湊表 (Hash Table) 時,用來計算雜湊值 (Hash Value) 的那種函數。只是該雜湊函數還具有很難逆向破解的特性,也就是給定雜湊值時很難反向計算出原文的特性,因此稱為「(單向) 雜湊函數」。

雜湊現金的機制,不只被用在「比特幣的挖礦」上面,也可以用來進行「垃圾郵件過濾」,以下文章就說明了如何用「雜湊現金」的機制來打擊垃圾郵件。

想要瞭解「雜湊現金」機制是如何運作的,比需先瞭解一個密碼學上的技術,那就是「單向雜湊函數」。

單向雜湊函數

在密碼學領域,最常被使用的「單向雜湊函數」有 MD5, SHA-1, SHA-2 等函數,MD5 的雜湊值長度為 128 位元,雖然廣為使用,但長度不夠,而且比較容易破解,因此現在已經不夠安全了。SHA-1 的摘要長度為 160位元,比 MD5 更安全一些,但最近也有些方法可以在大約在 2 的 60 次方計算後破解,因此美國國家安全局(NSA)與美國國家標準與技術研究院(NIST)又設計出了一些更複雜的 SHA-2 家族算法,SHA-2 包含 224, 256, 384, 512 等四種長度的雜湊值算法,SHA-2 會比 SHA-1 更安全一些。

在本文中,我們將示範如何用 SHA-1 函數來實現雜湊現金的機制,因此我們尋找到了一個開放原始碼的 C 語言 SHA-1 程式,其源碼如下:

上述程式有個測試主程式,若你定義 SHA1TEST 這個符號時,就會連同主程式一起編譯,該主程式顯然是在測試一些 「SHA-1標準」所提供的測試案例,以下是該測試主程式的執行結果:

D:\Dropbox\Public\web\codedata\code\sha1>gcc -Wall -DSHA1TEST -o sha1test sha1.cD:\Dropbox\Public\web\codedata\code\sha1>sha1testTest: FIPS 180-2 C.1 and RFC3174 7.3 TEST1Expect:a9993e364706816aba3e25717850c26c9cd0d89dResult:a9993e364706816aba3e25717850c26c9cd0d89dTest: FIPS 180-2 C.2 and RFC3174 7.3 TEST2Expect:84983e441c3bd26ebaae4aa1f95129e5e54670f1Result:84983e441c3bd26ebaae4aa1f95129e5e54670f1Test: RFC3174 7.3 TEST4Expect:dea356a2cddd90c7a7ecedc5ebb563934f460452Result:dea356a2cddd90c7a7ecedc5ebb563934f460452Test: FIPS 198a A.1Expect:4f4ca3d5d68ba7cc0a1208c9c61e9c5da0403c0aResult:4f4ca3d5d68ba7cc0a1208c9c61e9c5da0403c0aTest: FIPS 198a A.2Expect:0922d3405faa3d194f82a45830737d5cc6c75d24Result:0922d3405faa3d194f82a45830737d5cc6c75d24Test: FIPS 198a A.3Expect:bcf41eab8bb2d802f3d05caf7cb092ecf8d1a3aaResult:bcf41eab8bb2d802f3d05caf7cb092ecf8d1a3aaTest: FIPS 198a A.4Expect:9ea886efe268dbecce420c7524df32e0751a2a26Result:9ea886efe268dbecce420c7524df32e0751a2a26Test: FIPS 180-2 C.3 and RFC3174 7.3 TEST3Expect:34aa973cd4c4daa4f61eeb2bdbad27316534016fResult:34aa973cd4c4daa4f61eeb2bdbad27316534016f

使用 SHA-1 實做雜湊現金機制

有了上述的 SHA-1 雜湊函數程式之後,我們就可以來實作「雜湊現金」(hashcash) 系統了。

在以下程式中,主程式會從零開始一直向上調整 nonce 的值,直到找到一個 nonce 可以產生 24 bit (或說 3 個 byte 或 6 個十六進位值) 以上的前導零,才會停止程式並輸出該包含 nonce 的文件與雜湊摘要值。

檔案:hashcash.c

執行結果:

D:\Dropbox\Public\web\codedata\code\sha1>gcc hashcash.c -o hashcashD:\Dropbox\Public\web\codedata\code\sha1>hashcashCurrent local time and date: Mon Dec 16 19:33:03 2013msg=from:abc@gmail.com to:ccckmit@gmail.com title=hello! nonce=13973878hash=00000016aa26951d1653fe515f112fe41d8ebd45Current local time and date: Mon Dec 16 19:34:27 2013

您可以看到上述程式花了「1 分 24 秒」,從 nonce=0 開始向上不斷測試,直到 nonce=13973878 才找到了第一個符合有24 bit 前導零 nonce ,也就是總共測試了一千三百多萬次才發現符合條件的含 nonce 文件,這也就是雜湊現金(hashcash) 機制的實務用法。

一但找到符合這個條件的文件之後,就可以通過測試,假如這種雜湊現金是用來過濾垃圾郵件用的,那麼接收端就可以檢查這封郵件 “from:abc@gmail.com to:ccckmit@gmail.com title=hello! nonce=13973878″ 的接收者是否為自己,然後再檢查其雜湊值是否真的有 24 bit 的前導零,如果有的話就代表對方已經花了足夠的 CPU 時間 (換句話說就是已經付了「雜湊現金」,有付的人其信件就可以被接受了)。

同樣的,比特幣也是如此,如果一個人花 CPU 時間幫「比特幣網路」計算出符合條件的 nonce 值,那麼他就可以得到對應的代價,也就是一些「比特幣」,這也就是所謂的「挖掘比特幣」了。

參考文獻

  1. http://oauth.googlecode.com/svn../code/c/liboauth/src/sha1.c
  2. http://www.packetizer.com/security/sha1/
  3. http://zh.wikipedia.org/wiki/MD5
  4. http://en.wikipedia.org/wiki/SHA-1
  5. 維基百科:SHA家族
  6. 可愛的 Python: 用 hashcash 打擊垃圾郵件-想發送垃圾郵件,就要付出代價

--

--

陳鍾誠
程式人月刊

程式人、說書人、雜誌編輯、網站經營、金門大學教師