关键字:密码学,密码算法,单向哈希函数,对称加密,非对称加密,数字签名,数字证书,Merkle树,同态加密
在计算机科学中,密码学常常用来解决某些特定的难题:
密码学可以细分为密码协议,密码技术以及密码算法,本文不会详尽学习密码学的所有角落,而是专门针对区块链应用到的密码学知识进行学习。
博主曾在查找算法那一章中详细地从数据结构原理分析了哈希算法。哈希算法在密码学中有着非常重要的位置,是很多密码算法的基础。它可以将任意长度的二进制明文映射为较短的(通常为固定长度的)二进制串(Hash值),并且不同的明文很难映射为相同的哈希值(如果不同的明文映射为相同的哈希值了,就出现了碰撞,在查找算法那篇文章里面都做了详尽的分析。)所以,理想状态下,一个优秀的单向哈希函数包含以下几个特点:
实际上,单向哈希函数在密码学中还有很多种名字:压缩函数、收缩函数、消息摘要、指纹、密码校验和、信息完整性检验、操作检验码。
单向哈希函数的使用方法,通常都是一方对自己的明文进行映射得到哈希值,然后与另一方传过来的哈希值进行比对,如果一致,则说明两方的原文一致。
在这种操作过程中,明文不会涉及到数据传输,传输的是哈希值,这就对数据进行了有效的保护。
密码学中常见的单向哈希算法有:
以上单向哈希算法中,推荐使用SHA-256。
单向哈希函数可以说是对原文的一种隐蔽或者混淆,常用于对口令的保存。例如用户登录网站需要通过用户名密码的验证,网站后台就可以通过单向哈希函数来保存密码的哈希值,及时被窃听者偷到数据,他也无法直接推出密码的原文是什么。
然而,现今网站太多,用户往往不具备很高的安全意识,所以很有可能他们的多个网站上面都采用相同的密码,并且这个密码本身的强度也不够,有人专门收集了这些常见密码,计算出对应的哈希值放在一个字典里面。这样通过哈希值可以快速比对出密码原文。这种空间换时间的攻击方法被称为字典攻击,有人升级了字典攻击,只保存一条哈希值的首位值,相对字典攻击节省了大量空间,升级后的字典攻击被称为彩虹表攻击。
那么针对字典攻击以及彩虹表攻击,网站是否有有效的防御手段呢?
最有效的防御手段就是加盐(salt),即网站数据库保存的不是仅将密码映射出来的哈希值,而是密码明文再加上一段随机字符串(盐)之后的哈希值,同时将“盐”单独保存,这样一来字典里的哈希值就不再具备广泛性,从而也就失去了它的攻击能力。
单向哈希函数其实不算加密算法,因为它不能真正地对信息进行保护,它只能对数据进行哈希映射但不能翻译出原文。下面我们来介绍真正的加密算法技术,首先就是对称加密。
对称加密,就是加解密使用的密钥相同。
在单向哈希函数中,是没有密钥这个概念的,这也是它无法成为加密算法的原因之一。
如果把对称算法看成保险柜,密钥就是保险柜的号码组合。知道号码组合的人能够打开保险柜,放入文件,再关闭它,然后另一个也知道号码组合的人可以打开保险柜,取出文件。
对称加密算法的计算效率高,加密强度高,所以它适用于大量数据的加解密过程,但是缺陷是它必须提前将密钥共享出去,这期间一旦泄露则文件无加密可言。对称加密算法有DES,3DES,AES,IDEA。
对称加密算法推荐使用AES和IDEA。
针对对称加密,通常会采用选择密文攻击,它是指窃听者任意收集一定量的密文信息,让这些密文通过自己尝试的一些加密算法来解密获得明文,一旦尝试成功,窃听者可以在不知道密钥的情况下即可获得真正有效数据的明文信息。
有效办法是将明文信息先用单向哈希函数处理以后再进行加密传输,这样一来,窃听者即使试出了加密算法也无法对解密明文进行解析。
非对称加密是在对称加密之后诞生的算法,也叫做公开密钥算法,顾名思义,它的加密密钥和解密密钥是不同的,分别称为公钥和私钥。非对称加密算法要先通过随机数算法生成私钥,然后通过私钥生成公钥,将公钥公开出去,任何人都可以拿到公钥对数据进行加密,然而只有少部分持有结对私钥的人才能将文件解密。
非对称算法解决了密钥泄露的问题,但是它的加解密过程要比对称算法慢上几个数量级,同时加密强度也不如对称加密。非对称加密算法包括RSA、EIGamal、椭圆曲线、SM2等系列算法。
其中椭圆曲线又叫ECC算法,是当前比较推荐采用的非对称加密算法,另外SM2也可以。
针对非对称加密,通常会采用选择明文攻击。由于非对称加密公钥是公开的,窃听者就可以任意构造一个明文进行加密得到加密串,通过不断的尝试,窃听者可以掌握加密算法的一些信息,以方便日后破解同样加密算法加密的信息,最坏情况下,窃听者甚至可以直接获得解密的私钥。
现在的RSA和ECC已经具备了一定的保护机制来避免这种攻击风险,手段就是对同样的明文使用同样的密钥进行多次加密,得到的结果却完全不同,这就给窃听者试图从加密串中获得规律带来了难度,避免了选择明文攻击。
其实上面针对选择明文攻击和选择密文攻击的处理方案都是混合加密机制的思想。混合加密机制结合了对称加密和非对称加密的优点。
简单来讲,明文是靠对称加密算法加解密的,但是对称加密的密钥K是通过非对称加密进行发放,K通过公钥加密后的串是公开的,授权人必须通过自己持有的私钥来解密K,再用K来解密密文。
举一个非常经典的例子就是HTTPS协议,它是基于HTTP协议,更加安全的协议,现已成为最普遍的web通讯协议。它定义的交互过程为:
以上则是细致地分析了HTTPS协议的每个步骤的工作内容,可以看出,在保护对称算法密钥的这条路上,HTTPS真是不遗余力:它通过2个明文随机数加上一个非对称加密算法保护的随机数R3,在此基础上,将三个随机数进行了函数处理才得到最终的对称算法的密钥。即使外界知道加密协议版本,加密类型,压缩算法和前2个随机数,他们也不知道R3是多少,也就无法得知那个伪随机函数是怎么写的,所以会话密钥得到了更深层次的保护,外界只能看到被会话密钥加密后的密文,他们无法得知那个会话密钥是什么。
数字摘要是单向哈希函数最重要的一个用途,也可被称为文件完整性测试。通过对原文进行哈希运算,获得唯一的摘要值来指代原文,数字摘要解决了确保内容未被篡改过的问题。我们在从网络上下载文件时,都会被提供一个数字摘要值,我们可以通过对下载到本地的文件进行运算得到本地摘要值,然后与网络提供的进行对比,如果一致说明文件未被篡改,不一致说明有篡改过。
全称为“基于Hash的消息认证码”,英文缩写HMAC。
基本过程:对某个消息利用提前共享出来的对称密钥和Hash算法进行加密处理,得到HMAC值。该HMAC值持有方可以证明自己拥有共享的对称密钥,并且也可以利用HMAC确保消息内容未被篡改。
典型的HMAC包含三个因素(K,H,Message):
消息认证码一般用于证明身份的场景。任何拿到K和H的授权人可以通过发送明文消息给另一方,另一方通过K,H,Message得到HMAC值返回前人,前面的人自己算出HMAC来比对,如果一致则说明是自己人,如果不一致则停止通信。
然而,得到K和H的授权人可能不止一个,对于其中一个人来说,其他所有的授权人都是一样的,无法区分他们。这就引出了身份的进一步定义——数字签名的技术。
数字签名也有着签名的效力,它是基于非对称加密,既可证明某数字内容的完整性,又同时可以确认来源(或者作为证据,不可抵赖性),看上去它是以上两种技术的汇总升级版,既有数字摘要的文件完整性校验的功能,也有消息认证码的更明确的身份确认。下面是几点注意:
常见数字签名算法包括DSA和安全强度更高的ECDSA等。
注意:签名只是为了确认身份和文件完整性,而不是为了传输文件,切记切记。
下面来谈谈数字签名的安全性,它是由数学问题进行保障。目前常见的数字签名算法往往需要选取何时的随机数作为配置参数,配置参数不合理的使用或泄露都会造成安全漏洞,需要进行安全保护。之前索尼公司的PS3虽然采用了较为安全的ECDSA进行签名,然而错误地使用了重复的随机参数,最终导致私钥被破解,造成经济上的重大损失。
下面介绍几种特殊的签名类型:
在数字摘要之前的原始内容本身就是一个密文,作为签名者的我无法看到原始内容,我只能将原始内容做摘要然后私钥加密摘要进行签名。外人通过找到对应我身份的公钥解密签名获得摘要值比对确定我的身份以及文件完整性。而对于文件内容本身,我和外人都无从得知,因为从摘要是很难逆向得到明文的,而且得到的也是原始内容的密文,又不知道如何解密。
盲签名实现了对原始内容的保护,防止签名者看到原始内容,而且签名者也无法将签名内容和签名结果进行对应。 典型的实现包括RSA的盲签名算法等。
多重签名规定了总共n个签名者,收集到m个(n>=m>=1)签名并判断有效,则认为该文件合法。
多重签名可以有效地被应用在多人投票共同决策的场景中。多重签名的主要目的是在身份和文件完整性验证的基础上,由多人投票确认签名文件本身是否合法。
比特币交易中使用到的就是多重签名机制,可实现多人共同管理某个账户的比特币交易。也就是说当某个账户发生比特币交易的时候,多个人去记录这比交易形成交易文件,比特币规定,每笔交易的文件的格式内容是有一个最终标准的,只不过多人在形成这个文件的过程中要克服一些数学问题(挖矿),当他们中有一人完成了交易文件就会对它进行签名并广播,其他人收到签名以后会验证,如果签名没有问题,则该文件合法,所以这里对应的多重签名里的m值为1,有一个人的签名通过了,就可证明该文件合法,然后会将该交易文件合到比特币主区块链上去。
群签名即某个群组内的一个成员可以代表群组进行匿名签名。签名可以验证来自于该群组,却无法准确追踪到签名的是哪个具体成员。
群签名需要一个群管理员来添加新的群成员,因此存在群管理员可能追踪到签名成员身份的风险。
群组内的成员每人都有一个自己的私钥,而对于外人来讲,整个群组只有一个公钥,外人可以通过公钥来解密签名,匹配一致这说明是该群组的签名,然而该签名是群组内的某个人通过自己唯一的私钥进行的加密。类似于公钥对私钥是1对多的关系,真实的情况肯定还是一个公钥对一个私钥,那么这里的一对多是如何形成的呢?我想可能是对群组内的每个公钥做了一个处理,将群组内的公钥生成了一个统一的对外暴露的“群公钥”。
环签名属于一种简化的群签名。
签名者首先选定一个临时的签名者集合,集合中包括签名者自身。然后签名者利用自己的私钥和签名集合中其他人的公钥就可以独立地产生签名,而无需他人的帮助。签名者集合中的其他成员可能并不知道自己被包含在最终的签名中。
下面来分析一波,环签名旨在某个签名者想匿名签名,他自己拉起来一个临时的群组,他能够获得群组内其他人的公钥,然后他用自己的私钥加密了文件,通过一种手段,提供给外人解密的公钥变成了其他人的公钥,这就让外人无法定位到签名者本人。
环签名在保护匿名性方面有很多的用途。
对于非对称加密算法和数字签名来说,很重要的一点就是公钥的分发。理论上任何人可以公开的拿到对方的私钥。然而在这种前提下,如果窃听者伪造了公钥,在传输过程中对真实数据进行了钓鱼篡改。一旦公钥出了问题,整个安全体系也将随之崩塌。因此维护公钥的正确性是非常重要的。数字证书就是为了解决这个问题。
数字证书就可以证明某个公钥是某个实体(或组织或个人)的,并且确保一旦篡改能被探测出来,从而实现对用户公钥的安全分发。
证书保护的公钥分为两种,上面我们也都介绍过了:
这两种类型的公钥也可同时放在一个证书中。
一般情况下,证书需要有证书认证机构(CA)来进行签发和背书。权威的证书认证机构包括DigiCert、GlobalSign、VeriSign等。用户也可以自行搭建本地CA系统,在私有网络中进行使用。目前证书的规范均采用X.509证书规范,该规范中规定了证书所包含的信息,有版本号,序列化,签名算法,颁发者,有效期,主体,主体的公钥信息,颁发者唯一号,主体唯一号,扩展。此外,证书的颁发者还需要对证书内容利用自己的公钥添加签名,以防止别人对证书内容进行篡改。X.509规范推荐使用PEM格式来存储证书相关文件。证书文件的文件名后缀一般为.crt或者.cer,对应私钥文件的文件名后缀一般为.key,证书请求文件的文件名后缀为.csr。有时候也统一用.pem作为文件名后缀。PEM格式采用文本方式进行存储,一般包括首尾标记和内容块,内容块采用Bash64进行编码。
Merkle树,又叫哈希树,是一种典型的二叉树结构,由一个根结点、一组中间节点和一组叶节点组成。在区块链系统出现之前,广泛用于文件系统和P2P系统中。主要特点:
Merkle树可以推广到多叉树的情形,此时非叶子节点的内容为它所有的孩子节点内容的哈希值。Merkle树逐层记录哈希值的特点,让它具有了一些独特的性质。例如,底层数据的任何变动,都会传递到其父节点,一层层沿着路径一直到树根。这意味着树根的值实际上代表了对底层所有数据的“数字摘要”。Merkle树的应用场景有:
同态加密是一种特殊的加密方法,允许对密文进行处理得到仍然是加密的结果。即对密文直接进行处理,跟对明文进行处理后再对处理结果加密,得到的结果相同。从抽象代数的角度将,保持了同态性。
同态加密可以保证实现处理者无法访问到数据自身的信息。
本文简单介绍了应用密码学中区块链相关的一些问题和算法。掌握这些知识,对于帮助理解区块链系统如何实现隐私保护和安全防护都很有好处。区块链技术中大量利用了现代密码学的已有成果,包括Hash,加解密,签名,Merkle树数据结构等。另一方面,区块链系统和诸多新的场景也对密码学和安全技术提出了很多新的需求,反过来也将促进相关学科的进一步发展。