常见加密学算法
RSA (Rivest–Shamir–Adleman)(1977年)
基于大数(1024bits以上)的质因数分解问题。
可用于非对称加密、数字签名。
ECC(Elliptic-curve cryptography)(1985年)
基于在椭圆曲线上的离散对数的求取问题。
可以结合其他算法来用,变成:ECDSA(数字签名算法,但不推荐的)、ECDH(密钥交换算法)。
DSA (1991年)
DSA,即Digital Signature Algorithm,直接就叫数字签名算法,显然被发明的时候就是专门用来做数字签名的。
数学上基于离散对数问题。
可惜因为DSA要基于强随机数k,有安全隐患,导致现在基本没有被使用的价值了。
AES (2001年)
AES的意思是高级加密标准(Advanced Encryption Standard),使用的算法是Rijndael,Rijndael是当时加密算法竞赛的top 1。
AES是目前被使用最广泛的对称加密算法。
DH(1976年)
DH,即Diffie-Hellman key exchange,是密钥交换算法。
基于离散对数问题,所以数学原理和DSA是一样的。
现在基于离散对数的算法都不常用了,包括这个DH。
ECDH (21世纪)
DH标准算法的变种,是基于椭圆曲线算法的DH密钥交换算法,和离散对数无关。
使用非常广泛。
分组加密算法的模式
分组加密算法,都需要考虑wrap模式(【Block Cipher Modes(https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation))。
模式多种多样,也很容易查到介绍资料。选择模式时主要考察几个点:
- 并发性:
- 如CTR、GCM计数器模式
- 安全性:
- 如ECB模式对重复出现的明文分组加密后结果是一样的,容易被猜出
- 如CBC模式,会遇到padding oracle attacks,这篇写得很详细:https://blog.csdn.net/qq_35078631/article/details/78484980
- 完整性(integrity)和可验证性(authenticity):
- 其实就是指消息验证码MAC。加了MAC后,解密时,验证MAC,防止密文被篡改(tamper),保持完整。
- CCM模式,等于CTR加上CBC-MAC,不过做了2重加密,速度慢。
- OCB,有版权问题据说。
- GCM,等于CTR加上GHASH。这个是NIST官方标准了,绝对靠谱,性能据说很可以,openssl里面有一堆GASH的汇编代码,硬件级别上也有相应支持。
- 这2个性质不一定要由分组加密完成。也可以外部套一个非对称加密,用数字签名来保证完整性。
AES各种模式的选择问题,参考:
https://stackoverflow.com/questions/1220751/how-to-choose-an-aes-encryption-mode-cbc-ecb-ctr-ocb-cfb
此回答近300赞,在stackoverflow上算很多了。
如果没耐心看,就看作者的最后总结:
如果数据已经在外部做了非对称加密数字签名以支持验证,那么用CBC即可,否则用GCM。
完全前向保密 PFS(Perfect Forward Secrecy)
没有PFS之前:
- 如果攻击者曾经窥探并保存了用户和服务器的加密数据流,且包括被公钥加密的对称密钥
- 如果有一天攻击者通过某种办法获得了服务器私钥
- 攻击者同时拥有了:“用公钥加密的对称密钥”、“私钥”
- 攻击者用“私钥”对“用公钥加密的对称密钥”解密,获得了对称密钥
- 攻击者此时就可以用破解出来的对称密钥对已存的历史加密数据做解密
基于DH的PFS:
- 不再使用公钥加密对称密钥的方案
- 改为用DH密钥交换算法(key exchange),协商对称密钥,可以直接明文传输协商时需要的信息(并不怕这些信息被窃取)
- 每次会话都协商新的对称密钥
- 因为公钥私钥没有用来加密对称密钥了,所以即使服务器私钥被盗了也不会导致历史对称密钥被破解
- 即使单次会话的对称密钥被破解了,也不会影响到别的会话
为什么可行
关键在于,用于生成会话密钥的“数据”,根本就没通过网络发送出去。而用公钥加密的密钥,本身就是通过网络传输的。
后者显然更容易被攻击,只要获得私钥并记录了整个会话的数据流,就可以破解了。
而前者,对称密钥的协商,根本没有用到公钥私钥,经过网络的也不是什么被加密后的密钥,而只是协商信息。攻击者要想破解某次会话的内容,只能从该次会话的加密数据流入手,没有他法。
问题
要做到perfect,意味着每次会话都要协商密钥,意味着增加了计算开销,不然不能保证密钥的转瞬即逝性质(ephemeral)。
通讯的认证
认证问题是指,如何确定和自己通讯的对方不是其他假冒者?
目前有2个主要的解决方案:消息验证码(message authentication code,MAC)和数字签名(digital signature)。
消息验证码
前提:
- 通讯双方需要先约定好一个密钥,称为共享密钥,双方都把它安全地存起来
- 对任意长度的消息数据,用共享密钥可以计算出对应的固定长度的MAC
- 计算MAC必须用到共享密钥,除非密钥泄露,否则第三者无法计算出MAC值
流程:
- 协商密钥
- 发送方对消息计算MAC值
- 发送方把消息和MAC值都发给对方
- 对方收到消息后,也用共享密钥计算MAC值,并与收到的MAC值比对
- 如果2个MAC值一致,那么消息确实来自于发送方
各种问题:
一,密钥协商问题(上面已提过)。
二,重放攻击(replay attack):攻击者窃听通讯双方(例如2个银行)的数据,把汇款消息保存了下来(带有MAC值),然后重复发送这个汇款消息,接收方就会重复地向发送方发起汇款。其中,攻击者并不需要破解消息。
解决方法:每条消息都加序号,序号必须保证递增,从而每条消息的序号唯一;消息加时间戳,但时钟同步和时钟精度又是新的问题;每个消息加nonce,一个只能用一次的随机数。
三,密钥推测攻击:应确保攻击者不能通过MAC值逆向出共享密钥,否则攻击者就可以伪造发包了。
四,对第三方证明问题:共享密钥只能保证2个人之间的通讯认证,但是如果多于2个人时,理论上共享密钥无法解决认证问题。
例子:用户A向银行B用共享密钥传输了一个取款消息,如果B取款前需要告知C“A申请取款”,C是否可以相信A真的发出了取款消息,还是说消息是B杜撰的?答案是C没有办法知道。
五,防止否认问题:就上面的取款例子,如果A真的发起了取款消息,但是事后又矢口否认,A认为是B杜撰了这个消息,此时事实就说不清了,A和B都有共享密钥,无法知道消息是A说的还是B说的。
数字签名
简单来说,数字签名是公钥加密的逆向过程。
对比一下:
公钥加密
- 公钥:发送者加密时使用
- 私钥:接收者解密时使用
数字签名
- 公钥:验证者验证签名时使用
- 私钥:签名者生成签名时使用
这里面的公钥私钥是一样的东西,只是用法不一样。私钥依然需要保密地持有,而公钥依然可以任意地公开。
为什么公钥加密反过来就是数字签名,而不是反方向的加密呢?用心琢磨下就知道了:用私钥去加密消息,而谁都能拿到公钥去解密,有什么保密意义可言?
其中还有一个关键点是由公钥的数学原理保证的:用私钥加密的消息,只能用配套的公钥才能解密。
数字签名使用方法:
- 发送方计算消息的摘要(MD5,SHA-1)
- 发送方对摘要用自己的私钥加密,生成数字签名
- 发送方把消息和数字签名同时发出
- 任何人都可以用发送方公布的公钥对数字签名解密
- 通过对比解出来的摘要和自己算出来的摘要,就可以知道消息是不是来自发送方(识别修改)
注意,上面说的消息,可以是明文也可以是密文,也就是说数字签名支持对明文做签名。
公钥证书:
对签名用到的公钥私钥对中的公钥也进行签名,就得到了公钥证书。(是不是有一种递归的感觉。)
公钥证书可以用来判断收到的公钥是不是发送方的公钥。因为有可能收到假的公钥(中间人攻击)。
签名公钥时,用到的公钥密钥对,本身又要认证。这就产生了CA的概念。
一般公钥证书会简称证书。
数字签名的主要问题:
抛开一些攻击问题不讲,最主要的问题就是上面刚提到的中间人攻击。
因为要正确地使用数字签名,有一个大前提:用于验证签名的公钥必须属于真正的发送者。
这就陷入了死循环:数字签名是用来防止伪冒,但同时又必须从非伪冒的发送者拿到没有被篡改的公钥。
所以就得用上刚刚提过的公钥证书,给公钥附加一个第三方的签名,这样就把问题转移到了第三方。
第三方的背后也可以存在别的第三方,于是需要构造一个数字签名链条。
链条的末端,就是所谓的根证书了。
公钥基础设施:PKI(Public-Key Infrasture)
PKI的组成结构:
- 用户,使用PKI的人
- 认证机构(CA,Certification Authority),颁发证书的实体
- 仓库(Repo),也叫证书目录,保存证书的数据库
PKI可以有无数个。
重点要理解CA是怎么回事。
CA主要做三件事:
- 生成公钥密钥对。其实是可选的,如果由CA生成,那么需要安全地把私钥发给用户;如果是PKI用户生成,就简单多了。
- 生成颁发证书。需要用到CA自己的私钥来对第一步的公钥进行数字签名,同时还需要对用户身份进行认证。
- 作废(revoke)证书。作废比较复杂,因为用户会在本地缓存证书副本。于是就有了CRL,证书作废清单,(Certification Revocation List)。相当于是一个作废证书的公示榜单。其中每个证书有一个序列号可以作为id对应。用户通过查看CRL就可以知道证书有没作废。
CA可以形成层级关系,最顶层的叫根CA。验证某个公钥证书时,需要从根CA开始,一层层往下验证,确保整条链上的证书都是合法的。
对证书的攻击
有社会学的攻击也有非社会学的,具体建议看《图解密码技术》的第十章。
为什么要搞得这么复杂
- 如果用户有办法能够取得可信的公钥,则不需要CA
- 当持有可信的CA公钥,并相信这个CA,则可以相信该CA颁发的证书,从而获得可信的公钥。
我的理解是,目前的技术瓶颈导致只能如此,没有更靠谱的方法。
不过存在替代CA模式的其他解决方案:信任网络(web of trust),这个概念来源于PGP。
信任网络就好像人与人之间的关系网(六度分隔理论),通过熟人推荐,就可以建立起信任链,从而解决公钥认证问题。
PGP就是建立在信任网络的协议和软件。鉴于PGP的设计,PGP特别适合用于电子邮件传输,当然电子邮件又不仅限用PGP,还可以用基于CA的S/MIME。
参考资料
https://zhuanlan.zhihu.com/p/38920372
https://scotthelme.co.uk/perfect-forward-secrecy/
Elliptic Curve Crypto , The Basics
What is the math behind elliptic curve cryptography?
https://www.certicom.com/content/certicom/en/21-elliptic-curve-addition-a-geometric-approach.html
写作不易,您的支持是我写作的动力!