01
密碼學的歷史
人們對于信息編碼的需求幾乎伴隨著寫作的發展出現。加密寫作這一形式最先被應用于古埃及、美索不達米亞以及古印度。隨著時間的推移,人們學會了使用特殊的工具來編碼文本。最早的加密工具之一是密碼棒(scytale),斯巴達軍方使用其來進行戰場通信。密碼學技術一直在不斷發展。一旦現有的加密方法不再奏效,人們就會發明出新的信息編碼方案。 在第二次世界大戰期間,第三帝國(德國)使用非常復雜的機電轉子密碼裝置(即Enigma裝置)來進行軍事通信編碼。Enigma裝置的主要構造包括鍵盤、轉子、電路板和燈。轉子將輸入文本轉換為密碼,其位置會隨著每次擊鍵發生改變。一個擁有一萬人的解密中心最終耗費多年才成功破解Enigma代碼。隨著計算機時代的到來,密碼學躍升到了一個新的高度。許多國家,尤其是美國,組建了全新的國家資助加密計劃,其中就包括由NIST開發的安全哈希算法SHA-256。如今,在眾多應用程序中,SHA-256哈希算法都被用于在比特幣中創建區塊。以太坊區塊鏈網絡使用的是Keccak算法。基于Keccak算法,一種新的哈希算法標準SHA-3問世,該新標準于2015年首次發布。
02
SHA-256和區塊創建過程
創建區塊的過程包括對交易進行驗證和記錄,此過程我們稱之為挖礦(mining)。交易經過哈希運算后被記錄在區塊中。所謂哈希,是指將任意長度的文本信息轉換為固定長度值的過程。比特幣交易就是使用SHA-256算法進行哈希處理。 以下是通過SHA-256算法將任意文本及其對應哈希的示例:
如上圖所示,哈希是由64個字符組成,通過SHA-256算法所得到的結果為256位,即64個16進制字符。。SHA-256算法對于輸入字母的大小寫十分敏感,比如單詞Hello和hello的哈希完全不同。挖礦的目的是確定所生成區塊的哈希,以保證該哈希將適合某個特定區塊鏈網絡中的所有交易。隨著創建單個區塊所需的算力越來越多,挖礦的難度也會逐漸增加。隨著創建區塊所需的算力增長,哈希碼中“零”的個數也在不斷增長。目前在比特幣中,其哈希的開頭有20個連續的零,創建區塊需要消耗大量的計算資源(computational resources)。然而,產生區塊的時間上限是不變的,依舊保持在10分鐘。在每生成2016個區塊以后,比特幣挖礦的難度將進行自動調整,這個調整的切換率在比特幣代碼發布時已經確定。因此,創建區塊的過程在于記錄該區塊內所有交易的哈希值。每一個比特幣區塊均包含以下字段(fields):幻數(magic number)、區塊大小(blocksize)、區塊頭(blockheader)、交易計數器(transaction counter)以及包含相關交易信息的交易字段(transactions field)。每個區塊頭包含以下部分:版本號
前一個區塊頭的哈希
Merkle根哈希
時間戳
難度目標
隨機數
Merkle根顯示當前區塊交易的哈希值,并根據Merkle樹算法進行計算,也被稱為二進制哈希樹。其工作原理如下:
首先,系統計算區塊內所有交易的哈希值;
其次,系統將這些交易成對劃分,并計算出每個交易對的哈希;
最后,系統再次將所有這些交易對的哈希按對配對,并依次反復計算,直到計算出唯一的哈希碼,即得到所謂的根。
下圖展示的就是Merkle二進制哈希樹結構:
可以看出,Merkle樹的結構是兩兩配對的,因此它必須擁有偶數個元素。如果Merkle樹內的元素數量是奇數,那么系統會將落單的元素加倍以滿足配對條件。
具有奇數元素數量的Merkle樹如下所示:
區塊中的所有交易數據正是以這種方式進行計算與記錄在區塊中的。 在區塊鏈序列中,每個區塊都與前一個和后一個區塊相連。如果有人嘗試修改區塊中的某一筆交易,將會引起連鎖反應。首先,這將改變被修改后的交易的哈希,并向上擴散改變Merkle樹的分支,最終改變Merkle根的哈希。此后,被修改的Merkle根將改變該區塊的區塊頭,由此改變區塊鏈序列中的所有后續區塊。也就是說,哪怕只是一次修改也將導致此前用于創建該特定區塊序列的計算工作的報廢,并引發重新計算。
03
用于驗證比特幣和以太坊交易的密碼學知識
比特幣和以太坊網絡中的交易數據通過一種稱為橢圓曲線數字簽名算法(ECDSA)所產生的簽名來進行驗證,這種算法主要運用的是橢圓曲線和有限域。
簽署交易和驗證交易的過程是截然不同的。我們使用一個被稱為私鑰(private key)的工具來簽署交易,而使用另一個被稱為公鑰(public key)的工具來驗證交易。私鑰是在創建錢包的過程中隨機生成的。公鑰是基于有限域上的橢圓曲線乘法利用私鑰導出的,也就是說橢圓曲線數字簽名算法(ECDSA)就是用來產生公鑰的算法。只有簽署交易的人才知道私鑰,而公鑰可以被任何想要驗證交易的人(即礦工)獲取。橢圓曲線主要包含以下參數:一個方程式(an equation),一個素數模(a prime modulo)和一個具有素數階的基點(a base point with a prime order)。橢圓曲線的方程為 y²=x³+ ax + b。(備注:素數也稱質數,指在大于1的自然數中,除了1和該數自身外,無法被其他自然數整除的數,如2、3、5、7、11等都是質數)在比特幣,以太坊,BKX,EOS,Litecoin和許多其他加密貨幣中,其使用的橢圓曲線為secp256k1,該曲線方程的形式為y²=x³+ 7 mod p。secp256k1曲線的素數模是2²??–2³²–2?–2?–2?–2?–2?–1(或十六進制形式的FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F)。因為這個結果本質上是一個大素數,因此我們稱之為素數模。實數域上的橢圓曲線如下所示
基點G具有素數階n,從圖形化的角度來看,n可以被視為基點不斷相加直到其斜率無窮大或者成為垂線的次數。因此,在選定基點時,我們要確保其階數是大素數。 對secp256k1來說,基點G的壓縮形式為:G = 02 79 BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798,并且G的階數n為:n = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141。要生成公鑰,我們需要用私鑰乘以G,即: Keypub = Keypriv×G通過私鑰導出公鑰并不困難。但是,Keypriv是一個非常大的數字。因此,想要通過公鑰來獲取私鑰,并破解ECDSA算法,則需要進行計算 2¹²?個附加點的操作。對于普通計算機而言,這樣的操作將花費超過100億年,這是一個與整個宇宙的年齡相稱的時間過程。
在生成私鑰和公鑰后,我們必須使用私鑰對交易進行簽名。為此,我們需要完成以下操作:
計算z = hash( 交易 ) mod n;
選擇隨機整數k,其等于或大于1且小于或等于n-1(1≤k≤n-1);
通過將k乘以G得到點(x, y);需要注意的是,k 是一個臨時的秘密值,其必須在步驟5之后立即銷毀。泄漏秘密值 k 等同于泄漏私鑰:如果攻擊者知道 k 和簽名,那么她(或他)就可以計算私鑰。
計算r = x mod n。如果r = 0則返回步驟1;函數x mod p 僅返回除法的余數,例如78 mod 33 = 12 等同于 78 = (33*2)+12,98 mod 31 = 5 等同于 98 = (31*3)+5。注意,s 模 n的乘法逆表示為1/k mod n,并且1/k mod n 等于等式 kx = 1(mod n) 的解。這個方程在歐幾里德算法的幫助下以下列方式求解:假設 s = 3且 n = 5,則方程顯示為3x = 1(mod 5) ,或者利用歐幾里德算法,得3x = b(mod 5) 。如果我們將其擴展到線性丟番圖方程ax - by = c,或sx - ny = b,或 3x - 5y = 1,其中 x = 2且 y = 1(6–5=1) 中,那么 s-1將為2。
計算 s = (1/k mod n) × (z + r × Keypriv) mod n。如果s = 0,則返回步驟1;
計算對 (r, s) 將成為交易的簽名。
在交易簽名生成并被接收后,任何第三方都可以使用公鑰通過以下方式對其進行驗證:
確認簽名元素,數字 r 和 s 均落在1到n-1的范圍內;
計算 z = hash(交易) mod n;
計算 w = 1/s mod n;
計算 u = z × w mod n;
計算 v = r × w mod n;
計算點 (x, y) = (u × G) + (v × Keypub);
確認 r = x mod n。 如果r≠x mod n,則驗證的簽名無效。
如上所述,ECDSA算法的安全性依賴于整數 k 的隨機性以及使用普通算力在合理時間內不可能導出私鑰的特性。 這種全新的加密方式賦予區塊鏈技術最高級別的安全性,打破它的唯一方法是創建一個具有超過2000個量子比特算力的量子計算機——這種做法,至少在目前看來,是不可能的。