魏 艳,毛燕琴,沈苏彬
(南京邮电大学 计算机学院,江苏 南京 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 结束语