魏 艷,毛燕琴,沈蘇彬
(南京郵電大學 計算機學院,江蘇 南京 210023)
數據在當今時代是一項非常重要的資產,推動著不同領域做出具有戰略意義的決策。因為數據發揮著關鍵作用,使其成為網絡攻擊的一個目標。其攻擊目的是破壞數據的CIA(保密性、完整性、可用性)屬性,其中數據的完整性是數據是否可信的關鍵。2008年,一位署名為中本聰的人發表了一篇名為《比特幣:一種點對點的電子現金系統》的技術白皮書[1],具體闡述了交易、時間戳服務器、工作量證明、網絡、加密、區塊鏈技術等基于互聯網的、去中心的電子貨幣框架的重要理念,并且隨后上線了比特幣的系統。在比特幣的概念中,區塊鏈被稱為比特幣交易的公共賬本。區塊鏈的去中心化、分布式、持久性、不可篡改等屬性成為區塊鏈應用迅速發展的主要動力,也成為具有隱私保護應用需求的數據完整性驗證的主要關注焦點。
文中提出了面向區塊鏈數據完整性驗證的區塊鏈結構;提出了基于去中心化時間戳的數據完整性驗證機制,利用區塊鏈擁有的自身特性保證數據完整性。在以太坊平臺上模擬真實場景,具體實現了數據完整性驗證的智能合約。實驗結果表明,基于區塊鏈數據完整性驗證的模型,提高了數據的安全性,確保了數據的完整性。
數據在物聯網環境下采集、傳遞、存儲的過程中,如果缺少嚴密的安全防范措施,可能會出現假冒的、被篡改的或者過期的數據,這些缺乏完整性保護的物聯網數據會對物聯網應用造成極大的危害。區塊鏈提供的去中心化的、匿名信任管理機制,無需將數據傳遞到網絡服務器就可以驗證數據的完整性,這樣使得區塊鏈成為目前解決具有隱私保護需求的數據完整性問題的一種優選方法。數據完整性是指維護和確保數據在其整個生命周期內的準確性和一致性[2]。如果系統提供了完整性,那么系統就要保證數據是來自于經過身份驗證的數據源發送給接收者的,并且要保證數據沒有被篡改,這樣在某種意義上就具有了不可抵賴性[3]。
與基于區塊鏈的數據完整性驗證方法相關的技術包括區塊鏈、共識協議、激勵機制、可信時間戳,以及已有的數據完整性驗證機制。
區塊鏈由區塊鏈接組成,每個區塊包含一個區塊頭和一系列交易作為其負載。這一系列交易通過所有交易作為梅克爾樹的葉子節點構成的梅克爾樹的根被包含在區塊頭中。另外這個區塊頭包含一個時間戳和前一區塊頭的哈希,一次性數等。時間戳服務器對區塊進行散列并公開發布它,從而證明區塊內的數據在散列時就已經存在。時間戳服務器必須驗證區塊的時間戳大于前一區塊的時間戳。區塊鏈中的每個區塊都通過包含前一區塊表示的哈希值來“鏈接”前一個區塊。這些哈希值連接成一條鏈,被稱為區塊鏈[4]。區塊中的每個交易被散列成一棵梅克爾樹[5]。梅克爾樹是具有很多葉子節點的二叉樹,而且葉子節點的樹根是它子節點的哈希[6]。

圖1 區塊的結構
如圖1所示,一個比特幣的區塊的一部分是交易哈希值的梅克爾樹。樹中的任何不一致都會在區塊鏈中被反映,所以梅克爾樹對于區塊鏈的長期維護非常重要。區塊鏈是基于網絡的、可以分散可信存儲、交換和訪問數據的管理系統。區塊鏈不僅僅是一個數據結構,必然包括可信數據存儲、交換和數據訪問的相關操作機制。區塊鏈可以看作是一種去中心化的數據管理系統,也可以看作是對等網絡上的一類應用。
基于工作量證明的區塊鏈擁有的許多特性都和數據完整性相關,主要是因為淘金過程和區塊鏈的副本存在于大量的節點中。當一個區塊是區塊鏈的一部分,所有的淘金者都要同意其內容,所以這個內容是不可抵賴和持久的[7]。區塊鏈對存儲的數據的不變性有很強的保證,并且隨著時間的推移這個保證更強,因而適用于時間戳應用程序。區塊鏈的安全性通過工作量證明保證。在區塊鏈網絡中,淘金者通過在區塊中增加一個一次性數直到區塊的散列滿足指定條件的值,過程需要花費巨大的算力,因而稱工作量證明。新生成的區塊被添加在整條鏈的尾部,攻擊者若想改變此區塊中的信息,只能通過重做這個區塊之后的所有區塊的工作量證明工作才能完成,代價巨大。
面向區塊鏈數據完整性驗證的區塊鏈結構模仿比特幣的激勵機制。通過對淘金者提供獎勵,在保持去中心化的同時利用自我利益的力量驅動區塊鏈網絡的高速發展。比特幣系統對區塊的創建者提供了比特幣的激勵,對驗證交易的一方也提供了比特幣的激勵。區塊中的第一筆交易會產生一個新的比特幣獎勵給區塊的創建者。這會激勵節點驗證交易,然后將比特幣投入流通領域,因為沒有中央機構發布比特幣。第一筆交易稱為創幣(coinbase)交易。使用這種方法,可以激勵節點保持誠實。比特幣網絡大約10分鐘產生一個區塊。除了基于區塊創建產生的獎勵,節點通過驗證交易也會被獎勵比特幣。這種將新區塊添加到區塊鏈的過程稱為淘金[8]。最初的區塊獎勵設置為50個比特幣,后來每210 000個區塊獎勵會減半。區塊鏈的第一個區塊是創世區塊,用來向網絡提供最初的50個比特幣。區塊創建獎勵的減半策略會持續到獎勵低于一個聰。
區塊鏈對存儲的數據的不變性有很強的保證,并且隨著時間的推移這個保證更強[9-10]。這個保證使得區塊鏈很適用于時間戳應用程序,因為它們保證了數據在未來不會發生變化。區塊鏈可以說是一個去中心化的時間戳服務器技術[11-13],該技術被比特幣數字貨幣系統引進。時間戳證明數據在某個特定時間點肯定存在,例如報紙就可以充當一個時間證明。在區塊里,每個區塊都包含有一個時間戳,這個時間戳是淘金者根據本地系統時間設定的,表明區塊被成功挖掘的時間。區塊頭中包含的時間戳可以確保區塊的順序,有效預防對區塊中數據的篡改和偽造。可信時間戳是驗證在某一時間點未改變的數字數據的存在的一個過程。隨著加密貨幣的推出,區塊鏈首次實現了防篡改、不可信、匿名和可自動編程的“去中心化可信時間戳”。該技術展現了如果數據的哈希值被嵌入到加密貨幣的交易記錄中,加密貨幣的區塊鏈(例如比特幣)充當一個去中心化的可信時間戳服。證明數據在某個時間存在某個狀態,并且之后沒有被更改。通過使用區塊鏈技術保證和驗證數據的完整性。這個和已經建立好的時間戳協議相比有以下優點:(1)時間戳的去中心化的密碼完整性驗證的過程。(2)高度激勵計算節點致力于去中心化過程。區塊鏈不受限于單個實體,而是由加入到加密貨幣網絡中的所有計算節點進行維護,任何人都可以公開訪問。
傳統的方法都是使用中心化的方式為存儲的數據完整性驗證指明了光明的未來,但是這些都是依賴第三方進行數據完整性驗證的方法,存在的主要問題是第三方仍不可信。相對于傳統的數據完整性驗證,文中利用區塊鏈技術,拋棄第三方審查機構,采用去中心化的數據完整性驗證,保證了數據完整性驗證的可信性[14-17]。
使用密碼哈希函數SHA-256實現數字簽名可以提供數據的完整性。數字簽名需要一對密鑰(公鑰和私鑰),這來自于橢圓曲線算法[18]。使用哈希函數用來簽名和驗證報文的完整性。數字簽名被用來簽署交換的報文。時間戳證明數據在某個時間存在某個狀態,并且之后沒有被更改。通過使用區塊鏈技術保證和驗證數據的完整性。
數字資源一般使用URIs或者DOIs進行標識[19]。但是它們都依賴于某些信任方或者權威機構,而且不能保證隨著時間的推移可以檢索到相同的資源。所以在不被信任的環境下,數字資源應該通過可以唯一識別內容的機制進行識別,也就是數據標識具有唯一性。隨著需要處理不同的媒體類型和慣例表示的資源,以及處理被編碼的資源,使用字節內容的哈希值已經成為一個普遍適用的方法。擁有可以識別資源及其數據的賬戶,就要關注數據真實性的問題,也就是允許數據的所有者提供證明,是由他們自己提供的數據。區塊鏈是一個合適的解決方案,因為區塊鏈允許數據的擁有者添加交易到區塊鏈中,在區塊鏈中可以加密證明數據的出處,而且不能被刪除。目前在區塊鏈領域,驗證數據完整性的方法是將標識符-哈希值映射類型存儲在智能合約中。但是通過查看智能合約中的這些數據很難推斷出和其相關的任何信息。文中提出的實現方法是在智能合約中存儲一些與源數據相關的元數據以及哈希值。該方法通過在智能合約中增加一個Identifier結構實現,這個結構包含一些附加信息也就是元數據,有數字簽名(bytes dsign),時間戳(uint256 timestamp),哈希值(bytes hash),數據的所有者(address owner)。然后將這個結構代替數據哈希值映射到智能合約中。因此標識符的基本結構引進去中心化的概念,具體Identifier結構定義如下(使用solidity語言):
struct Identifier
{
bytes dsign;//數字簽名
uint256 timestamp;//時間戳
bytes hash;//哈希值
address owner;//數據的所有者
}
以太坊有兩種賬戶類型,一種是由賬戶控制的外部賬戶,此賬戶是由用戶控制的公-私鑰對,用A、B……表示這些賬戶。另一種是合約賬戶存儲執行的智能合約代碼,用x表示。這兩種賬戶類型都可以存儲以太坊的貨幣“以太幣”。如果沒有用戶交互,以太坊不會在合約中執行計算。所以,合約賬戶在它的代碼被執行之前必須被外部賬戶激活。智能合約是一種分布式執行代碼的機制,為了淘金者執行代碼消耗的計算工作,以太坊會支付成比例的費用。淘金者執行此交易的交易費是執行代碼實際消耗的燃料乘以燃料單價。如果某些執行需要燃料比還要高,則執行將以異常的形式終止,狀態將恢復為初始狀態,就像一切沒有發生一樣。在這種情況下,發件人仍然必須向淘金者支付所有限定的燃料量,作為對抗資源枯竭攻擊的對策。總之,執行代碼需要使用燃料,這些燃料由外部賬戶使用以太幣購買。燃料的成本實際上是一個交易費用,鼓勵淘金者去執行代碼。
如圖2所示,A在區塊鏈上創建了一個合約,合約代碼放置在交易的數據字段被發送到區塊鏈。合約的地址是X。B使用第二個交易發送一定量的燃料到地址X來調用合約的一個函數。
以太坊的交易結構如圖2所示,每個字段的含義如下:
簽名字段:來自外部賬戶的簽名,用于授權交易,也就是可以標識發送方證明他們發送一筆交易。
接收方字段:交易的接收方,既可以是外部賬戶也可以是合約賬戶。
數據字段:數據字段是可選字段,在圖2中是指發送給一個合約賬戶的消息,包含合約代碼,用于創建一個新合約或者執行合約指令。
燃料價格:使用以太幣購買燃料的轉換率,每個燃料單位的價格。
最大燃料量:這筆交易花費的燃料總量,也就是當用戶發送交易以調用合約時,用戶必須指定愿意為執行提供多少燃料。
以太坊中交易定義,交易是被使用在以太坊中是指已經被簽名的數據包(data package),這個數據包會被從一個外部賬戶(EOA)發送給區塊鏈中的另一個賬戶。這個賬戶可以是外部賬戶,也可以是合約賬戶。這個數據包存儲了一個消息(message),這個消息數據可以是以太幣也可以是合約執行參數(數據字段)。基于自己的產品有兩種類型的交易,一個是創建新賬戶,也就是圖2的合約創建交易,另一個是用于消息調用,也就是調用合約交易。

圖2 基于區塊鏈的數據完整性驗證的區塊鏈結構
(1)節點需要使安全哈希函數對數據進行哈希運算,得到數據的哈希值。得到的結果記為hash。
(2)節點對這個哈希值進行數字簽名,得到數字簽名dsign。利用去中心化時間戳和唯一數據標識技術。將哈希值hash、數字簽名dsign以及交易發生的時間戳timestamp和數據所有者owner都作為附加信息添加到Identifier結構中。最后將這個結構代替數據哈希值映射到智能合約中。
礦體受構造控制作用明顯。區域性的大型構造控制著巖體的分布,次級構造控制著礦體的分布。本區位于朱陽關—夏館—大河區域性斷裂的南側,該構造給巖漿和成礦物質提供了上升通道;郭莊組及劉山巖組地層內的次級構造為鉬礦體提供的成礦空間,發育有脈狀的鉬多金屬礦床。
(3)用戶將數據存入本地服務器中,并保留數據標識中的元數據信息,以便實時的數據完整性驗證。
(4)用戶需要進行完整性驗證服務時,首先計算出在本地服務器中存儲的數據的哈希值hash0,然后根據保留的時間戳信息timestamp0,再進行哈希計算,最終得到一個新的哈希值hash1,最后利用用戶自身的私鑰,對hash1進行數字簽名,得到新的數字簽名dsign0。
(5)節點和數據完整性智能合約進行交互,通過使用數字簽名dsign0,搜索智能合約中Identifier結構對應的存儲在區塊鏈的數據哈希值hash。
(6)對比兩個哈希值hash和hash0,驗證數據的完整性。如果兩個值相同,該源數據就順利完成數據完整性驗證,說明數據沒有被篡改,反之,源數據就遭到篡改或者破壞。
實驗的硬件環境是Intel(R)Core(TM)i7-8550U CPU (1.80 GHz),RAM為8 GB。以太坊平臺運行在Ubuntu16.04LTS 64位操作系統上。智能合約由solidity語言實現,區塊鏈環境使用以太坊solidity編程語言開發框架truffle和可視化私有鏈客戶端ganache。
基于去中心化時間戳的數據完整性驗證機制如下:通過數據完整性驗證的智能合約實現。智能合約包含存儲函數put以及驗證函數get。該過程可以使用式1和式2表示。其中h是哈希函數本身,m是將要轉換成哈希值的報文,生成哈希值hash,timestamp是交易的時間戳,利用用戶的私鑰private,執行數字簽名sign,生成唯一的數字標識dsign,通過存儲函數put,數字簽名dsign,時間戳timestamp,哈希值hash,數據所有者owner被永久地存儲在以太坊區塊鏈中。通過使用唯一數據標識符dsign作為驗證函數put的輸入,返回與此數據標識符相關的數據。用戶交易會以交易列表的形式作為區塊的一部分。每個區塊必須指向前一區塊,因此新的區塊會確認前一區塊的內容。因為區塊鏈的激勵機制的存在,就會激勵節點發布一組新的交易,進而形成新的區塊。一旦區塊被確認之后,就無法改變一個交易的時間戳。這個過程可以幫助證明數據在某一時間點存在,自某一時間點之后就沒有被改變,確保數據的完整性。存儲到區塊鏈中的數據是很難被篡改或者偽造的,所以數據可以被安全存儲。

(1)
get=(dsign)
(2)
以太坊設計了兩種方法存儲數據。一種利用賬戶存儲數據,另一種利用事件存儲數據,也稱為日志存儲。這兩種方法都在合約代碼中實現。以太坊中的每個賬戶都有額外的空間用于數據存儲。該存儲在以太坊虛擬機中實現,為256位字大小的鍵值存儲。它在合同的執行期間可以使用值類型或者引用類型進行讀取或者寫入。將腳本編譯成以太坊虛擬機代碼之后,必須由外部賬戶發送一個特殊的報文來完成合約的創建。在以太坊中存儲數據的第二種方法是日志存儲,也被稱為事件。其用途就是發送返回值或者日志事件到一個特定用戶。實驗使用兩種方法結合的存儲數據方式,提高實驗的存儲效率及精確度。以太坊區塊鏈上的智能合約允許數據作為變量直接存儲在這些合約中。因為區塊鏈不易篡改的屬性,可以保證這些數據只能使用智能合約的功能進行更改,并且每次和智能合約的交互都會被看作一個交易記錄在區塊鏈上。根據區塊鏈和智能合約的這些屬性,確保數據完整性的最簡單辦法就是將所有數據通過智能合約直接存儲在區塊鏈上。
圖3為部署智能合約的過程。首先啟動一個以太坊節點(如Geth),使用智能合約編程語言(如Solidity)編寫智能合約(后綴為.sol)。用solc編譯器將.sol合約代碼編譯成以太坊虛擬機字節碼。將編譯好的合約代碼部署到以太坊區塊鏈,需要消耗燃料,并且需要合約發起用戶使用自己的外部所有賬戶對將要部署的合約進行簽名,通過淘金者確認后,將合約代碼存于以太坊區塊鏈上。在這一步中,用戶可獲得合約的地址,以及調用合約所需的接口,以便之后使用。編譯智能合約過程如圖4所示,部署合約過程如圖5所示。

圖3 部署智能合約的過程

圖4 編譯合約

圖5 部署合約
具體實現的智能合約包含一個存儲函數,該函數允許通過數據標識包含的元數據傳遞給此函數并存儲到區塊鏈中,其中元數據dsign,timestamp,hash,owner分別代表數字簽名,時間戳,哈希值和數據所有者。運行結果如圖6所示。
contract DataIntegrity{
function put(bytes dsign,bytes hash,uint256 timestamp) public returns (bytes) {
address owner=msg.sender;
bytes32 message=prefixed(keccak256(hash,timestamp));
address recovered=recoverSigner(message,dsign);
require(recovered==msg.sender);
identifiers.push(Identifier({
dsign:dsign,
timestamp:timestamp,
hash:hash,
owner:owner
}));
}

圖6 數據存儲階段的實驗結果
智能合約包含一個驗證函數,該函數允許通過將標識符和哈希值傳遞給此函數并將它們與存儲的值進行比較來驗證存儲的數據。
contract DataIntegrity {
function get(bytes dsign) public returns (bytes,uint256,bytes,address) {
uint len=identifiers.length;
for(uint i=0;i bytes memory sig=identifiers[i].dsign; if(isEqual(sig,dsign)) { return(identifiers[i].dsign,identifiers[i].timestamp,identifiers[i].hash,identifiers[i].owner); } } //bytes dsign; uint256 timestamp; bytes hash; address owner; return(dsign,timestamp,hash,owner); } } } 節點通過唯一標識dsign作為輸入,輸出與此標識相關聯的數據,其中與存儲數據相對比可以看出,存儲階段和驗證階段的數據完全相同,結果如圖7所示。 但是如果以一個錯誤的標識作為輸入,經過對比數據,此數據無法通過數據完整性驗證,結果如圖8所示。 以上實驗可以看出,基于區塊鏈的數據完整性驗證技術可以保證數據的存儲和驗證的正確性,從而進一步確保數據的完整性。 圖7 數據驗證階段的實驗結果 圖8 數據驗證階段的測試結果 區塊鏈提供有關數據完整性的可信特性,使得區塊鏈成為一項引人注目的技術。使用區塊鏈來解決數據完整性的威脅似乎是一種自然的選擇。區塊鏈的去中心化、分布式、持久性、不可篡改等屬性成為數據完整性驗證的主要關注點。文中提出的基于區塊鏈的數據完整性驗證解決方案理論上證明該方案可以保證數據完整性,并在以太坊平臺上進行實驗驗證,結果表明基于區塊鏈的數據完整性驗證的結構確保了數據的完整性。但是依舊要考慮利用智能合約存儲到區塊鏈中的效率,以及實驗的驗證規模較小,希望未來的工作可以對此有所優化。在未來的工作中,將計劃設計和構建一個應用程序,以使用豐富的數據存儲格式支持更加復雜的數據完整性驗證,并借助強大的評估模型,確定應用程序的安全性。

4 結束語