鄒秀清/ZOU Xiuqing
丁勇/DING Yong
(桂林電子科技大學,廣西桂林541004)
隨著互聯網行業的發展,越來越多新型的網絡平臺融入到了人們的生活,人們日常生活都要用到淘寶、京東等交易平臺,使用支付寶、小米錢包、微信等來支付。這些平臺都有一套獨立的注冊、登錄、認證和權限管理的系統,每一個用戶在系統中都充當不同的角色,并擁有不同的權限,這種中心化系統給人們帶來的弊端有以下幾點:
(1)如果有多個系統需要進行登錄、認證,管理員的維護和管理的成本將會大幅增加,并隨著規模的增加,維護難度會增加。
(2)用戶必須記住自己的多個賬號、密碼,如果賬號很多,使用起來將非常不便捷。
(3)容易被黑客攻擊,帶來損失。
(4)中心化系統不可信,管理員可以隨時篡改數據。
區塊鏈技術是一種利用去中心化共識的機制維護一個完整的、分布式的、不可篡改的賬本數據庫的技術,它能夠讓區塊鏈中的參與者在無需建立信任關系的前提下實現一個統一的賬本系統。近年來,區塊鏈以集成分布式數據存儲、點對點(P2P)傳輸、新型加密算法和共識機制等技術的特點,已越來越成為許多國家政府和國際組織研究討論的熱點,依靠互聯網的產業也紛紛加大了對其投入的力度[1],但是目前全球還沒有政府大力推廣將該技術應用于物聯網的身份識別系統。
如今新型的區塊鏈技術給人們帶來了解決方案:區塊鏈建立了動態的P2P網絡,沒有了中心化服務,帳本均分布在每個節點中,所有的節點一同維護;帳本上記錄了該區塊鏈自創建以來的記下的所有交易記錄,通過密碼學的安全機制,使得所有記錄不可修改、真實可信;每個人都是一個節點,通過彼此之間的信任來建立區塊鏈的信任。區塊鏈網絡沒有傳統的中心管理員,整個網絡的運作由線上的電腦共同進行維護,使得運營成本大幅降低。
本設計組成的框架主要包括四大模塊:數據層模塊、網絡層模塊、共識層模塊和接口層模塊。通過接入到同一個區塊鏈網絡中,使用統一的接口層進行交互,同時接口層還能和網絡層和共識層通過底層協議進行交互,網絡層負責發現區塊鏈網絡中的P2P節點和數據的傳輸,共識層負責身份認證,數據層負責存儲數據。
1.1.1 區塊鏈技術基本原理
假設Bob要在互聯網上向Alice轉賬,每次轉賬都會產生交易記錄,將所有的交易記錄進行連接,生成總帳單,總賬單包含每個人的余額。記賬時,應需保持公平、誠信的態度,使得雙方能夠相互信任;但記賬人可能會作假,使得雙方的信任程度降低,這是很典型的欺詐行為。區塊鏈技術則可以很好地解決這一問題,沒有人可以作假。
現把賬單模型進行縮小,規定:每次更新、修改數據必須在原有的賬單中進行,并且新賬單包含時間戳、前一個賬單的哈希值等數據。將這些帳本累加起來稱為總帳本,總帳本將所有的塊鏈接起來,組成區塊鏈,圖1表示一條區塊鏈中的3個區塊。
1.1.2 區塊鏈的去中心化
在2008年的金融危機中,比特幣的創始人中本聰發明了比特幣,它成為了第一個去中心化的數字貨幣。區塊鏈是一個分布式網絡,每個節點都會存放所有交易的副本,并自動同步。節點可以是用戶的電腦、手機,或是其他設備。如圖2所示,區塊鏈網絡節點是扁平化的,每個節點的地位相等、公平,并以扁平拓撲的方式向相鄰節點進行數據交互[2]。
假設Bob想給他人轉賬,Bob就得向全網廣播他要轉賬的消息,并需全網達成共識,才能認為他的消息是合法的,且每個節點都會保存他轉賬信息。全網沒有中心服務器,沒有人能擁有管理的權力,只要規則定好了,就必須照著規則做,沒有人可以改變,這其實就是區塊鏈去中心化的魅力所在。
所有節點都相當于“校驗員”,它們無時無刻不在檢查區塊中的交易信息是否正確,并且在檢查交易的時候,不斷嘗試產生隨機數,計算哈希值,使數據具有很強的安全性,黑客無法入侵,無法修改賬戶余額。隨著用戶的增加,越來越多的后續節點(用戶)加入到了比特幣網絡中,共同完成共識的過程[3];而整個過程中網絡中每個節點的地位是相同的。比特幣不是憑空產生,而是通過消耗了電力、物力并應運算而產生的,因此具有價值,可以兌換成現有的貨幣。

圖2 去中心化的節點圖
哈希函數也叫做哈希算法,不論輸入字符串的長短,生成簽名的長度都是固定的,因此可以作為一段數據的數字指紋,便于區分每個消息。生成的摘要可作為簽名,以確保數據的真實性。賬戶的創建需要一個非對稱加密密鑰對,以太坊選擇的是橢圓曲線加密算法(ECC)中的Secp256k1,依據速度、安全性等參數確定賬戶的地址,具體的方法如下:
(1)創建一個隨機私鑰,由64個十六進制的字符構成;
(2)從私鑰中導出公鑰;
(3)從公鑰中導出地址。
使用Secp256k1生成256位公鑰/密鑰,然后編譯成64位長度的十六進制字符串;采用公鑰的Keccak-256哈希算法,得到一個32字節的字十六進制字符串,接下來對該字符串進行取截,取字符串的最后20個字節(即刪除前12個字節),得到了40個字節的字符串,在簽名加上0x前綴,就可以得到一個42個字節長的地址,該地址就是以太坊用戶全網唯一的賬號。
Merkle樹在區塊鏈中尤其重要,相當于用大量的數據塊來進行哈希運算。Merkle樹將2個相鄰的認證請求進行哈希計算,逐步堆積到Markle樹根。這種哈希算法的好處就是讓歷史數據不可篡改、真實可信[4]。節點的值是它相連2個葉子節點的哈希,這就導致整個Merkle樹中的數據都是互相關聯的,改動其中一個數據,將會徹底改變整個區塊的結構,因此給身份的證明提供了一個非常簡潔的機制。
Merkle樹的最初應用是在比特幣中,即使用了Merkle樹來存儲每個區塊的交易。每個Merkle樹從塊到根都是由哈希的分支組成,如圖3所示。由于Merkle樹采用了非常強的哈希算法,且哈希后的摘要求逆幾乎不可能實現,因此Merkle樹提供了真實可信的數據驗證方法。
每個區塊頭包含如圖4所示的內容。將相連的數據區塊的數據進行相連,通過上一區塊的哈希值和當前區塊的哈希值將所有的區塊請求進行關聯。如果修改了其中一個數據,將影響所有在當前區塊鏈網絡上的區塊,因此數據不可能被篡改,所有的認證請求不可偽造,極大提高了區塊鏈的安全性。
ECDSA是數字簽名算法(DSA)的其中一個例子。和非對稱加密算法(RSA)進行對比,在相同的安全強度下,ECDSA可以使用的密鑰更短,從而節省網絡和存儲空間,具有較高的研究價值[5]。

圖3 Merkle樹的結構

圖4 數據區塊頭的結構
在本設計方案中,首先要避免數據明文傳輸的極大不安全因素,同時要保證交互雙方的身份真實性,因此需要利用公鑰加密算法中非對稱加密的優勢。使用本設計方案進行數據傳輸時,將服務器的公鑰輸出在客戶端,客戶端使用公鑰加密,在信息交互時數據以密文方式傳給服務器端,再由相應私鑰得到明文數據[6]。
Alice將要給Bob發送一條消息,要求消息包含數字簽名來進行身份識別,那么可以定義一組參數(CURVE,G,n),其中CURVE表示橢圓曲線的點域以及它所使用的幾何方程,G表示橢圓曲線基點,大素數n是橢圓曲線的階數[7]。接下來我們介紹數字簽名的具體過程和驗證數字簽名的具體過程。
(1)數字簽名的過程
如果Alice要發出認證請求,她希望能對消息m進行簽名,因此將橢圓曲線的參數設計為D=(p,a,b,G,n,h),其中對應的密鑰對為(k,Q),Q為公鑰,k為私鑰。Alice將按照如下步驟進行簽名:
1) 產 生 一 個 隨 機 數d,1≤d≤n-1;
2)計算dG=(x1,y1),將x1轉化為整數-x1;
3)計算r=-x1modn,若r=0,則轉向第1步;
4)計算d-1modn;
5)計算哈希值H(m),并將得到的比特串轉化為整數e;
6)計 算s=d-1(e+kr)modn,若s=0,則轉向第1步;
7)(r,s)即為Alice對消息m進行的簽名。
(2)驗證數字簽名的過程
如果Bob收到消息m之后,他需要驗證消息m的簽名(r,s),在得到橢圓曲線參數和Q之后,將按以下步驟操作來驗證數字簽名[8]:
1)首先驗證r和s是區間[1,n-1]上的整數;
2)計算H(m)并將其進行轉化變為整數e;
3)計算w=s-1modn;
4) 計 算u1=ewmodn以 及u2=rwmodn;
5)計算X=u1G+u2Q;
6)若X=0,則拒絕該簽名的有效性,否則將X的x坐標x1轉化為整數并計算
7)當且僅當v=r時,簽名驗證可以通過。
利用ECDSA算法,將認證信息進行數字簽名,確保了每條認證消息都是由正確的用戶發表的,防止他人假冒,還可以保證數據的完整性。在整個認證請求中,將不會有人對數據包進行惡意篡改。
每個節點用戶再發起認證請求時,都會利用自己的私鑰簽名,其他節點收到認證請求,也會一同參與簽名認證的操作。如果認證成功,將會將賬單記錄下來,完成認證;否則將拒絕認證請求。
1.5.1 Gas——以太坊系統計算工作量的單位
Gas是以太坊系統中執行交易所需要的計算工作量單位。所有的交易不論是轉賬交易,還是執行智能合約,都要消耗Gas。Gas的價格由交易的發起人和礦工的工作量決定,交易打包進區塊中需要礦工們進行哈希運算,礦工們付出了勞動,因此需要收取一定的費用。如果交易發起人設置的Gas價格過低,礦工們基本不會將交易打包進區塊里;如果交易設定較高的Gas,該交易將會得到較高的優先級。
1.5.2 以太坊的工作量證明和挖礦原理
工作量證明(PoW)的目的是阻止網絡攻擊,如當今網絡環境下常出現的分布式拒絕服務攻擊(DDoS),就是用來發送許多假的請求以耗盡計算機網絡系統資源,導致服務器宕機,真正的用戶則無法登錄到中心服務器上[9]。
PoW被定義為花費計算機算力來進行數據校對的要求,俗稱“挖礦”。挖礦的目的有以下幾點:
(1)驗證交易的合法性,避免出現多重交易的情況;
(2)用來獎勵礦工所做出的計算工作;
(3)維護以太坊系統的正常安全運轉。
通過挖礦的方式解決PoW的數學難題具有不可逆的特征。從技術角度來說,挖礦的過程就是一個不斷進行的哈希運算過程,它通過嘗試產生隨機數,找到滿足條件的隨機數后立即將區塊進行打包并全網廣播,找到該隨機數的節點也是贏得本輪記賬權利的節點。該區塊將在整個區塊鏈網絡廣播,進行共識的達成。如果達成共識,每個節點將會將該區塊添加到自己的區塊鏈中,同時該礦工將會得到以太幣獎勵。
隨機數的條件取決于系統設定的難度,例如:要求整個區塊加上隨機數計算出的哈希值要小于給定的值才算成功;而哈希值的產生沒有規律可循,只有算力越高的計算機才能更快得到符合條件的隨機數。
2.1.1 數據區塊和鏈式結構
首先,區塊是以太坊網絡的核心,所有的交易、數據存儲都是在區塊頭中進行的。不同的區塊頭之間通過頭指針(ParentHash)函數指向前一個區塊的頭指針,將它們串聯起來,形成單項鏈表。
區塊結構分為區塊頭和區塊的數據部分這2個部分,源碼在以太坊的/core/types/block.go中,數據層的函數關系圖如圖5所示。

圖5 數據層函數關系圖
其中,區塊的結構體定義為:
type Block struct


2.1.2 Merkle樹的使用
在以太坊中使用的是Merkle樹的改進樹(MPT),也是二叉樹的一種。節點的值是它相連2個葉子節點值的哈希。Merkle樹用于所有交易正確性的驗證,而MPT則大大提高了查找效率。樹的構造代碼在以太坊源碼的trie/trie.go中,關鍵代碼如下。
首先是從根節點進行遍歷:

if(t.db==nil){...}//如果數據已經存在數據,返回
return t.CommitTo(t.db)//父節點沒有數據,就調用下面的函數寫數據

查找、插入、刪除都是在trie/trie.go里進行使用的。
2.1.3 數據存儲的實現
以太坊的數據存放在StateDB中。StateDB是以太坊的數據庫,負責本地存儲數據及業務,還負責連接到底層的數據庫,它使用二級緩存機制來存儲賬戶的相關數據。
StateDB的相關代碼在core/state/statedb.go中,其定義的結構體以及作用為:DataBase類型的DB用于存放數據,Tire類型的tire用于存放MPT樹,stateObject表示以太坊賬戶,其中在stateObject中也有二級緩存機制,主要用來緩存和更新以太坊帳戶。
整個以太坊網絡的運作結構如圖6所示。

圖6 以太坊網絡的運作結構
2.2.1 網絡層傳輸協議
當一個節點有新的數據區塊產生,該節點將會進行全網廣播,其他收到請求的節點將會進行驗證。一個節點創建一個新的區塊,該新區塊很快會被發到網絡上所有的節點,然后每個節點都要驗證這個新的區塊,驗證其真實性。經驗證后,每個節點才會添加這個新的區塊到區塊鏈,區塊鏈網絡中的所有節點達成共識,一起決定哪個區塊有效而哪個無效,擅自篡改的區塊會被網絡上其他節點拒絕[10]。
在節點之間傳播數據時,采用加密網絡和傳輸協議(RLPx)加密握手協議。該協議在網絡層的上層,在以太坊網絡中新的節點建立后,首先進行端口監測偵聽、節點間連接及通信交互,當節點間都建立了連接,將會通過Msg的格式進行通信。每次在通信的過程中,都會做出如圖7所示的判斷,以確保握手協議運作正常,如果運作不正常,將會失去對該節點的連接。
RLPx加密握手協議的具體流程如圖8所示。
2.2.2 數據驗證機制
P2P網絡中的每個節點,只要在線,都在隨時監測偵聽其他節點的認證請求,驗證區塊數據的具體一些步驟如下:
(1)負責識別網絡中廣播的數據和區塊;
(2)如果接收到相鄰節點發來的認證,將會對認證請求進行分析,將檢查數據的完整性、語法的規范性、數字簽名是否正確等方面來校驗交易數據是否有效;

圖7 RLPx加密握手協議的建立

圖8 RLPx加密握手協議的流程
(3)如果數據有效,將會把數據放入存儲池中,即將認證請求記錄到本地,同時向相鄰節點轉發數據;
(4)如果數據無效,將會立即放棄該數據,確保數據不會在區塊鏈網絡中傳播。
2.2.3 P2P網絡的具體實現
以太坊的P2P網絡主要使用以下幾個工具實現。
(1)Discover:使用了 Kademlia協議,用于使用UDP的P2P節點發現的協議;
(2)discv5:用于發現新節點;
(3)nat:網絡地址轉換工具;
(4)netutil:有關網絡連接的工具;
(5)simulations:P2P網絡測試工具。
P2P網絡非常復雜,如果要使用它,就必須要包含節點查找、節點維護、節點建立連接的功能。在database.go文件中,newNodeDB函數用來存儲節點數據,存儲節點數據采用了Keccak-256的簽名哈希算法。以下是一些關鍵函數。
(1)查找節點的函數:func(db*nodeDB)node(id NodeID)*Node;
(2)插入數據的函數:func(db*nodeDB)updateNode(node*Node);
(3)刪除數據的函數:func(db*nodeDB)deleteNode(id NodeID)。
連接超時的處理辦法,即如果發現有個節點接收消息的時間超出了設定的值,那么就刪除節點不再連接,關鍵代碼如下:

2.3.1 PoW的機制
PoW通過計算機進行數學運算得到記賬權,但是每次要達成全網共識,都需要全網一起參與運算。本設計系統作了以下規定,使認證步驟準確進行:
(1)所有連接到以太坊網絡的地址都應該分為已被認證的和未被認證的;
(2)已認證的節點可以變成沒有經過認證的,沒有經過認證的節點也可以變成已認證的;
(3)一條認證請求包括認證的地址、認證的狀態等;
(4)認證成功之后不能再進行第2次認證。
2.3.2 共識記賬的設計方案
本設計方案的認證流程如下:
(1)請求的生成。以太坊的客戶端持續監測偵聽,如果網站調用了認證請求,那么客戶端將會向全網進行廣播。Alice使用她的私鑰對認證請求進行簽名,并在認證請求的末尾處添加簽名,以便能夠讓其他節點來進行校驗。
(2)請求的廣播。Alice將認證的請求向全網節點廣播,其他的節點將會收到并將共同參與數字簽名的校驗。若正確,則將其納入到礦工自己的區塊中;若不正確,則丟棄。
(3)區塊的生成。每當間隔一段時間,所有的節點通過挖礦進行PoW,通過解決數學難題來贏得記賬的權利,此過程也是所有節點進行區塊同步校對的過程。
(4)區塊的廣播。如果有節點通過算力找到了符合條件的隨機數,將會向全網廣播,該節點將是下個區塊的創建者,并會獲得獎勵;
(5)區塊寫入賬本。將對所有節點成功解出數學難題的廣播答案進行驗證,如果正確,它會將該區塊納入自己的賬本中,每個節點同步進行;否則,將丟棄該區塊。
2.3.3 共識記賬的實現
共識層的代碼在consensus/路徑中,本節具體介紹共識記賬的實現。
prepare函數主要用來處理區塊頭部信息,其定義如下:
diff=(parent_diff+(parent_diff/2048 * max(1- (block_timestampparent_timestamp)/10,-99)))+ 2^(periodCount-2)
其中parent_diff表示上一區塊的難度;block_timestamp表示當前區塊的時間戳;parent_timestamp表示上一區塊的時間戳;periodCount表示區塊數量。
結合官方的文檔,在測試階段,調節區塊難度的值為一個較低的值,讓登錄認證的交易盡快被礦工打包,避免用戶長時間等待,同時方便調試和使用。難度設定需基于創世區塊(創世區塊是指區塊鏈的第1個區塊,它是構建整個區塊鏈系統的基礎)。
seal函數用于處理挖礦的工作,需要一直遞歸調用,直到解決問題,解決問題之后退出。seal函數具有以下幾點作用:
(1)根據區塊頭部的信息中的挖礦難度系數來處理計算目標值。
(2)選取隨機數和區塊頭的哈希值,進行哈希運算。如果結果小于目標值,那么表示挖礦成功,自動退出;否則,則繼續循環進行哈希運算。
(3)如果從外部收到了這個塊,表示其他人已經挖礦成功并且已經得到了塊,那么就會馬上放棄打包當前塊。
(4)Finalize函數表示挖礦成功之后獎勵的事,它可以計算礦工的獎勵,使礦工得到獎勵。
verifyHeader函數主要用來校驗區塊的時間戳、校驗難度值、校驗區塊的gas。
VerifySeal函數主要用來驗證區塊頭部的簽名信息。
本設計系統使用的是以太坊的go-ethereum客戶端來連接到自己搭建的以太坊私有網絡,它提供的應用程序編程接口(API)可以給本設計系統進行調用,并用來創建新地址,驗證數字簽名、支付和轉賬、查看余額等。接口層包含了以太坊智能合約腳本、分布式計算、驗證加密簽名和數據存儲的技術。所有的請求數據通過post傳遞,使用json參數傳遞。
解析一個請求的具體的實現步驟如下:
(1)首先要對json數據進行實例化,使用NewJSONCodec編碼器;
(2)通過NewJSONCodec編碼器將請求轉換為jsonRequest,并且獲取參數有關服務名(service_name)、服務方法(service_method)和 數 據 片 段(params);
(3)通過服務名(service_name)和服務方法(service_method),查找已經注冊的rpc服務;
(4)向rpc服務進行請求,之后的操作都在rpc服務中進行;
(5)rpc返回結果,接著對json序列化,返回結果值。
例如:本設計系統使用Ethereum客戶端賬,在向rpc服務發送請求時,設定service_name為指定以太坊的服務名,并設定service_method為sendRawTransaction,通過調用 rpc服務,返回的結果是TxnHash字符串的json數據。
本設計方案最大的創新之處在于身份識別系統基于以太坊智能合約技術,立足于傳統互聯網行業的現狀,解決了中心化管理的麻煩,以及用戶信息容易被篡改、被黑客盜用,中心服務器被攻擊等事關國家信息安全痛點的問題。
在本設計中,認證請求者向系統提出認證請求,服務器節點在收到請求后,采用認證方案對識別認證者的請求,同時將認證信息加入到認證區塊鏈中。這個過程解決了分布式賬本的一致性和安全性問題,不需要第三方中介的引入。
該系統具有以下創新特點:
(1)去中心化,防止偽造。根據當今互聯網產業的需求,本系統使用P2P技術,改善了數據的存儲。所有的數據通過分布式存儲保存在各個節點,每個用戶都是一個節點,通過節點的共識,完成身份識別,不依賴第三方。
(2)數據校驗,真實可信。結合以太坊改進之后的MPT樹,以及通過RLPx加密握手協議,并充分利用ECDSA的非對稱加密的優勢,避免了黑客通過網絡傳輸作弊的行為。整個認證過程由節點們共同完成,使數據真實可信。
(3)安全性高,黑客止步。基于區塊鏈的去中心化特點,每個節點的地位都是對等的,即使某個或者部分節點被摧毀都不會影響整個系統的安全,也不會造成數據的丟失。黑客如果想篡改數據,需要攻擊、修改一半以上的節點數據,這幾乎是無法實現的。
(4)調用方便,拓展性高。本系統設計的接口層,通過json傳遞參數到以太坊客戶端,基于接口層方便調用的特點,可快速搭建更多不同開發語言的網站和程序,同時客戶端支持多個網站和程序,并調用獲取賬號的信息,實現了賬號的統一身份認證。
(5)部署簡單,用途廣泛。本設計方案可以部署在企業、政府機構、教育結構等,例如:在企業中,多個部門可以使用同一套以太坊網絡,無需在每個部門都進行部署,支持跨多個部門,適合部署在大型企業中。
本設計仍然有很多的可拓展之處,除了身份認證,還可以通過以太坊智能合約開發更多功能,例如:房屋出租、契約、貸款平臺等,能給使用者帶來顯著的安全效益、經濟效益、管理效益、科研效益。