网络安全和加密
在网络学习中我们经常遇到很多和加密有关的名词,比如AES,RSA等,还有如HTTPS,TLS,SSL等,另外还有如IPSec等,那么他们分别是什么含义,到底有什么关系呢,之前一直是一些零零碎碎的理解,这里通过对网上一些文章的汇总,系统的整理一下,对这些概念介绍一下。
网络安全和加密的基本概念
先来回顾一下网络通信加密的发展过程,假设A和B之间要网络通信。
远古时代
远古时代自然是民风淳朴,路不拾遗,夜不闭户。A要发数据给B,根本不用担心窃听和篡改,直接发就好了。
上古时代
随着时代的发展,渐渐的有了一类人——C。C不仅会监听A和B之间的网络数据,还会拦截A和B之间的数据,伪造之后再发给A或者B,进而欺骗A和B。C就是中间人攻击(Man In The Middle Attack)。
为了应对C的攻击,A和B开始对自己的数据进行加密。A和B会使用一个共享的密钥,A在发送数据之前,用这个密钥对数据加密。B在收到数据之后,用这个密钥对数据解密。因为加密解密用的是同一个密钥,所以这里的加密算法称为对称加密算法。
在1981年,DES(Data Encryption Standard)被提出,这是一种对称加密算法。DES使用一个56bit的密钥,来完成数据的加解密。尽管56bit看起来有点短,但时间毕竟是在上古时代,56bit已经够用了。就这样,网络数据的加密开始了。
因为采用了DES,A和B现在不用担心数据被C拦截了。因为就算C拦截了,也只能获取加密之后的数据, 没有密钥就没有办法获取原始数据。
但是A和B之间又有了一个新的问题,他们需要一个共享的56bit密钥,并且这个密钥一定要保持私密,否则被C拿到了,就没有加密的意义了。首先AB不能通过网络来传递密钥,因为密钥确定以前,所有的网络通信都是不安全。如果通过网络传递密钥,密钥有可能被拦截。拦截了就没有加密的意义了。为了安全,A和B只能先见一面,私下商量好密钥,这样C就没办法获取密钥。如果因为任何原因,之前的密钥泄露了,那么AB还得再见一面,重新商量一个密钥。
现在A和B之间,最私密的信息就是这个密钥了,只要保证密钥的安全,那么AB之间整个网络通信都是安全的。
中古时代
A和B小心的保护着密钥,不让C知道。但是道高一尺,魔高一丈。随着技术的发展,计算机速度变得很快,快到可以通过暴力破解的方法来解密经过DES加密的信息。不就是56bit的密钥吗?C找了一个好点的计算机,尝试每一个可能的值,这样总能找到一个密钥破解A和B之间的加密信息。倒不是说DES在提出时没有考虑过这种情况,只是在上古时代,计算机没这么快,破解56bit的密钥需要的时间非常长。但是现在是中古时代,可能只需要几天就可以破解56bit的密钥。
为了应对这个情况,新的协议被提出,例如triple-DES(最长168bit的密钥),AES(最高256bit的密钥)。经过这些改进,至少在可以预见的未来,计算机是没有办法在有限的时间内,暴力破解这个长度的密钥。所以,在中古时代,将对称加密算法的密钥长度变长,来应对中间人攻击。但是A和B还是需要见面商量一个密钥。
现代
非对称加密
时间到了现代。网络通信变得十分发达,A不只与B通信,还同时还跟其他10000个人进行网络通信。A不可能每个人都跑去跟他们见个面,商量一个密钥。
所以一种新的加密算法被提出,这就是非对称加密算法。非对称加密使用两个密钥,一个是public key,一个是private key。通过一个特殊的数学算法,使得数据的加密和解密使用不同的密钥。因为用的是不同的密钥,所以称为非对称加密。可以想象成一把钥匙和一个锁头,只是全世界只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。
非对称加密最著名的是RSA算法,这是以其发明者Rivest, Shamir 和Adleman命名。非对称加密算法里面的public key和private key在数学上是相关的,这样才能用一个加密,用另一个解密。不过,尽管是相关的,但以现有的数学算法,又没有办法从一个密钥,算出另一个密钥。
非对称加密的好处在于,现在A可以保留private key,通过网络传递public key。这样,就算public key被C拦截了,因为没有private key,C还是没有办法完成信息的破解。既然不怕C知道public key,那现在A和B不用再见面商量密钥,直接通过网络传递public key就行。
那这样是不是A和B通信只需要A产生private key,然后把自己的public key给B,然后A发送给B信息时用自己的private key加密,B收到后用A的public key解密,B发给A就用A的public key加密,然后A用自己的private key解密。这样是否可行呢?答案是否定的。虽然在非对称加密中,一般一个密钥加密,另一个密钥就可以解密,但因为公钥是公开的,如果用来解密,那么就很容易被不必要的人解密消息(比如这里C拦截了A的公钥就可以解密A发给B的内容了),因此,如果使用非对称加密,一般遵从这样的原则:公钥只用来加密,私钥只用来解密。另外,我们注意到一点,因为私钥不会在公网上传播,因此,私钥也可以认为是个人身份的证明。
既然一对密钥不行,那使用两对密钥呢。现在A和B各有属于自己的public key和private key,A发送给B消息时用B的public key加密,B收到消息时用自己的private key解密,即下图的过程。
不难发现,如果在发送过程中,有人(例如C)修改了里面密文消息,B拿到的密文,解密之后得到明文,并非A所发送的,信息也不正确,但是B并不知道。所以这里就要解决两个问题:
1. A的身份认证(确保消息是A发出的)
2. A发送的消息完整性(确保消息没有被其他人篡改)
要解决这个问题就要引入一个概念——数字签名。要将数字签名,还需要先了解另一个概念——消息摘要。
消息摘要是将消息经过哈希转换成一个固定长度的,值唯一的字符串。值唯一的意思是不同的消息转换的摘要是不同的,并且能够确保唯一。该过程不可逆,即不能通过摘要反推明文(似乎SHA1已经可以被破解了,SHA2还没有。一般认为不可破解,或者破解需要耗费太多时间,性价比低)。利用这一特性,可以验证消息的完整性。
既然消息摘要可以保证消息的完整性,而private key又可以作为身份证明,那么用private key加密过的消息摘要就同时解决了上述的两个问题——身份认证和消息完整性,这个“由private key加密的消息摘要”也就是数字签名。
下面我们看一下使用数字签名后的消息通信过程:
A和B都各有一个public key和一个private key,这些key根据相应的算法已经生成好了。private key只保留在各自的本地,public key传给对方。
A:将数据明文进行摘要(hash)运算后得到摘要(消息完整性),再将摘要用A的private key加密(身份认证),得到数字签名,然后用B的public key加密数据加密得到密文,最后将密文和数字签名一块发给B。
B:收到A的消息后,先将密文用自己的private key解密,得到明文。在将数字签名用A的public key进行解密后,得到正确的摘要(解密成功说明A的身份被认证了)。对明文进行摘要运算,得到实际收到的摘要,将两份摘要进行对比,如果一致,说明消息没有被篡改(消息完整性)。
这里有个疑问:
摘要使用A的私钥加密,如果被拥有A的公钥的第三者截获,不就可以获取到摘要了么?会不会对安全造成威胁。
答案是不会的。因为摘要是不可逆推出原文的。
非对称加密的安全隐患
但是在一切的最开始,A和B要通过网络交换public key。如果C在中间拦截了呢?假设有这种情况,C拦截了A和B的public key,又分别用自己的public key发给A和B。A和B并不知道,他们还以为这个public key来自对方。当A给B发消息时,A先用自己的private key加密数据的hash值,之后用C传来的假的public key加密数据,再发出去。C拦截到之后,先用C自己的private key解密数据,C就获取了A的原始信息!之后,C可以篡改数据内容,再用自己的private key加密数据的hash值,用之前拦截的B的public key加密数据,再发给B。B收到以后,先用自己的private key解密数据,再用C传来的假public key解密hash值,发现匹配。这样,B收到了一条来自C的假的信息,但是B还以为信息来自于A。中间人攻击仍然可能存在!
完了,一切都崩了,加密搞的这么复杂,居然还不能保证网络数据的安全。回顾一下,问题出就出在最开始通过网络交换public key(虽然public key不怕被别人知道,但是别人如果拦截替换伪造就有问题了)。看起来为了保证public key不被拦截,A和B似乎还是要见一面,交换一下public key。这一下就回到了上古时代。
不过,虽然A和B现在还是要见一面,但见面的实质已经变了。在上古时代,见面是为了商量一个密钥,密钥的内容很重要,不能让别人知道密钥的内容。而在现代,见面是为了确认public key的真实性,public key的内容是可以公开的。
那如果有其他办法能保证public key的真实性,A和B是可以不用见面交换public key的。
CA
现实中,通过CA(Certificate Authority)来保证public key的真实性。CA也是基于非对称加密算法来工作。有了CA,B会先把自己的public key(和一些其他信息)交给CA。CA用自己的private key加密这些数据,加密完的数据称为B的数字证书。现在B要向A传递public key,B传递的是CA加密之后的数字证书。A收到以后,会通过CA发布的CA证书(包含了CA的public key),来解密B的数字证书,从而获得B的public key。
(备注:现实的数字证书不仅包含所有者public key,还包含证书信息:过期时间和序列号,所有者信息:姓名等)
但是等等,A怎么确保CA证书不被劫持。C完全可以把一个假的CA证书发给A,进而欺骗A。CA的大杀器就是,CA把自己的CA证书集成在了浏览器和操作系统里面。A拿到浏览器或者操作系统的时候,已经有了CA证书,没有必要通过网络获取,那自然也不存在劫持的问题。
现在A和B都有了CA认证的数字证书。在交换public key的阶段,直接交换彼此的数字证书就行。而中间人C,还是可以拦截A和B的public key,也可以用CA证书解密获得A和B的public key。但是,C没有办法伪造public key了。因为C不在CA体系里面,C没有CA的private key,所以C是没有办法伪造出一个可以通过CA认证的数字证书。如果不能通过CA认证,A和B自然也不会相信这个伪造的证书。所以,采用CA认证以后,A和B的public key的真实性得到了保证,A和B可以通过网络交换public key(实际是被CA加密之后的数字证书)。
除非有种情况,A内置的CA证书被篡改了,例如A使用了盗版的系统,“优化”了的非官方浏览器,或者被病毒攻击了,那这个时候,A有可能会认可非CA认证的数字证书,C就有机会发起中间人攻击。所以,用正版至少是安全的。
SSL/TLS的应用
非对称加密算法比对称加密算法要复杂的多,处理起来也要慢得多。如果所有的网络数据都用非对称加密算法来加密,那效率会很低。所以在实际中,非对称加密只会用来传递一条信息,那就是用于对称加密的密钥。当用于对称加密的密钥确定了,A和B还是通过对称加密算法进行网络通信。这样,既保证了网络通信的安全性,又不影响效率,A和B也不用见面商量密钥了。
所以,在现代,A和B之间要进行安全,省心的网络通信,需要经过以下几个步骤
l 通过CA体系交换public key
l 通过非对称加密算法,交换用于对称加密的密钥
l 通过对称加密算法,加密正常的网络通信
这基本就是SSL/TLS的工作过程了。
什么是HTTPS、TLS、SSL
,也称作HTTP over TLS。TLS的前身是SSL,TLS 1.0通常被标示为SSL 3.1,TLS 1.1为SSL 3.2,TLS 1.2为SSL 3.3。下图描述了在TCP/IP协议栈中TLS(各子协议)和HTTP的关系。
这里的核心问题是记住SSL/TLS是工作在TCP之上的(http之下的)。
HTTP和HTTPS协议的区别
1. HTTPS协议需要到证书颁发机构(Certificate Authority,简称CA),一般免费证书很少,需要交费。
2. HTTP是超文本传输协议,信息是明文传输,HTTPS则是具有安全性的SSL加密传输协议。
3. HTTP和HTTPS使用的是完全不同的连接方式,使用的端口也不一样,前者是80,后者是443。
4. HTTP的连接很简单,是无状态的。
5. HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比HTTP协议安全。
从上面可看出,HTTPS和HTTP协议相比提供了
l 数据完整性:内容传输经过完整性校验
l 数据隐私性:内容经过对称加密,每个连接生成一个唯一的加密密钥
l 身份认证:第三方无法伪造服务端(客户端)身份
其中,数据完整性和隐私性由TLS Record Protocol保证,身份认证由TLS Handshaking Protocols实现。
HTTPS的基本原理
从上面可知,HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。
HTTPS其实是有两部分组成:HTTP +SSL/ TLS,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据。具体是如何进行加密,解密,验证的,且看下图。
1. 客户端发起HTTPS请求
这个没什么好说的,就是用户在浏览器里输入一个HTTPS网址,然后连接到server的443端口。
2. 服务端的配置
采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面(startssl就是个不错的选择,有1年的免费服务)。
3. 服务端传送证书
这个证书其实就是服务端的公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等。
4. 客户端解析证书
这部分工作是由客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。如果证书没有问题,那么就生成一个随机值(用于后续的对称加密)。然后用证书对该随机值进行加密。就好像上面说的,把随机值用锁头锁起来,这样除非有钥匙,不然看不到被锁住的内容。
5. 传送加密后的随机值
这部分传送的是用证书(服务端的公钥)加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。
6. 服务端解密随机值
服务端用自己的私钥解密后,得到了客户端传过来的随机值,后续就可以用这个随机值进行对称加密了。
7. 传输加密后的信息
这部分信息是服务端用密钥(随机值)加密后的信息,可以在客户端被还原
8. 客户端解密信息
客户端用之前生成的密钥(随机值)解密服务端传过来的信息,于是获取了解密后的内容。整个过程第三方即使监听到了数据,也束手无策。
现在用户知道自己访问的网站是正规的网站,否则用户浏览器会报错说不能用CA证书解析。服务器通过CA授予的数字证书自证了身份。但这里的安全隐患在于,服务器怎么知道访问者就是真用户呢?之前介绍的双向认证是可以通过数字证书验明用户的正身,现在用户为了省钱没有数字证书。这种情况下一般是通过用户名密码来确认用户。所以,大家要保管好自己的密码。
IPsec原理介绍
IPsec(IP Security)是一系列为IP通信提供安全性的协议和服务的集合,工作在IP层,可以为上层协议和应用提供透明的安全服务。IPsec提供两种安全机制:认证和加密。认证机制使IP通信的数据接收方能够确认数据发送方的真实身份以及数据在传输过程中是否遭篡改。加密机制通过对数据进行加密运算来保证数据的机密性,以防数据在传输过程中被窃听。准确来说,IPsec不是一个单独的协议,而是一组协议。
IPSec是IPv6的组成部分,也是IPv4的可选扩展协议,能保证IP报文的数据保密性(加密)、数据完整性度量(防止数据被改动)以及防止数据回放攻击(即接收到多个相同报文)。
IPsec包括传输模式(Transport Mode)和隧道模式(Tunnel Mode)两种模式,区别在下文提到。
IPsec包含了三个最重要的协议:认证头AH(Authentication Header),封装安全载荷ESP(Encapsulating Security Payload),密钥交换协议IKE(Internet Key Exchange),这里主要介绍ESP报文的装包和拆包过程。
ESP协议
1. ESP (Encapsulating Security Payloads) 协议能够在数据的传输过程中对数据进行完整性度量和来源认证,可以选择加密,也可以选择防止回放保护。
2. ESP 服务依据建立的 SA (Security Association, 安全关联),对可选项目有所限制:
(1)完整性检查和认证一起进行;
(2)仅当与完整性检查和认证一起时才能选择防止回放保护;
(3)防止回放保护只能由接收方选择。
3. ESP 的加密服务是可选的,但如果启用加密,则也就同时选择了完整性检查和认证。因为如果仅使用加密,入侵者可能发动密码分析攻击。
4. ESP 可以单独使用,也可以和 AH 结合使用。
SA、SAD、SPI
SA:Security Associations,安全关联,包含很多信息,比如加密算法,密钥,认证算法、认证密钥等。
SAD: Security Associations Database,安全关联数据库。每一个SA在SAD中都会有一个与之对应的条目,通俗来讲就是SA的集合。
SPI:Security Parameter Index,安全参数索引,相等于SA的标志符。
传输模式ESP报文的装包和拆包
传输模式下 IPsec 保护的仅仅是原始 IP 报文的数据内容部分 (即 IP 报文的有效载荷,数据段),而不是整个IP报文。在这个过程中原报文结构被修改。
在处理方法上,原 IP 报文被拆解,在其有效载荷前面加上新的 ESP 或 AH 协议头(此处指ESP),再装回原来的 IP 地址,形成 IPsec 报文
装包
l 将IP数据包分为IP头部信息以及数据段两部分,在数据段末尾加上ESP trailer信息,该信息包括三部分,因为加密算法可能是块加密,所以长度不足时需padding填充,再加上padding Length填充的长度,最后还有Next header来标明封装的报文类型,如tcp、udp或icmp等。
l 将第一步得到的数据段+ESP trailer进行加密,加密算法和密钥由SA给出。
l 在数据段前添加ESP header,包括SPI以及Seq两部分,SPI用来查找对应SA,Seq是对包进行编号,防止多次接收,注意到被封装的原报文的协议类型(tcp、udp)受到保护,由加密的 ESP trailer 的 Next header 声明,而不出现在未加密的 ESP header 中。
l 将ESP header+2中加密数据进行认证,得到32位整数倍的完整性度量值(MAC),加在加密后的2后面,认证算法和认证密钥由SA给出。
l 原IP头部信息还是放在头部,即是一个装包后的ESP报文。
拆包
l 接收方接收到该报文,检查IP头部信息,发现这是一个IPsec的ESP包,查看ESP header,找到SPI,进而获取到对应的SA。
l 查看ESP header中的Seq,确定该包是第一次收到,防止数据回放攻击。
l 根据SA获得的认证信息,重新对除IP头部信息外的数据进行认证,再与末尾的MAC进行对比,验证数据完整性。
l 根据SA得到的加密信息,解密被加密的信息,得到原数据段以及ESP trailer。
l 根据ESP trailer的填充信息,删去填充得数据得到原来的数据段。
隧道模式ESP报文的装包和拆包
l 隧道模式下 IPsec 将要发送的原始 IP 报文作为数据内容,在这段整个IP报文前面加上 ESP 或 AH 协议头(此处指ESP),再加上新的 IP头,形成 IPsec 报文进行传输。
l 原始 IP 报文的传输就像在一个安全的隧道中进行一样。在整个传输过程中,原报文保持原有的完整结构,内容没有被修改。
装包
l 直接在IP报文末尾加上ESP trailer信息,该信息包括三部分,因为加密算法可能是块加密,所以长度不足时需padding填充,再加上padding Length填充的长度,最后还有Next header来标明封装的报文类型,如因为是对整个IP报文进行处理,所以此处IP=4。
l 将原 IP 报文以及第1步得到的 ESP trailer 作为一个整体进行加密封装。具体的加密算法与密钥由 SA 给出。
l 为第2步得到的加密数据添加 ESP header。ESP header由 SPI 和Seq 两部分组成。加密数据与 ESP header 合称为 “Enchilada”,构成认证部分。注意到被封装的原报文的协议类型(IP数据包)受到保护,由加密的 ESP trailer 的 Next header 声明,而不出现在未加密的 ESP header 中。
l 将上一步得到的加密数据进行认证,得到32位整数倍的完整性度量值(MAC),加在加密后报文的后面,认证算法和认证密钥由SA给出。
l 加上新的 IP header 构成 IPsec 报文。新构造的 IP header 附在ESP 报文的前面组成一个新的 IP 报文。注意这个新的 IP header的 IP 地址由路由器和安全网关解释,可以和原报文 (由主机创建的 IP 地址) 不同。协议类型为50,说明它封装的是一个 ESP报文。
拆包
l 接收方接收到该报文,检查IP头部信息,发现协议类型为50,这是一个IPsec的ESP包,查看ESP header,找到SPI,进而获取到对应的SA。
l 查看ESP header中的Seq,确定该包是第一次收到,防止数据回放攻击。
l 计算 “enchilada” 部分的摘要,与附在末尾的 ICV (MAC)做对比,验证数据完整性。
l 根据SA得到的加密信息,解密被加密的信息,得到原数据段以及ESP trailer。
l 根据ESP trailer的填充信息,删去填充得数据得到原来的IP报文。
IPSec VPN和SSL VPN
VPN(虚拟专用网络)是指在互联网上建立专用的网络进行加密通信,通过对数据包的加密和地址转换实现远程访问。常见的VPN有IPSec和SSL两种。下面大概讲一下两种VPN的适用场景。
前面我们知道了IPSec和SSL是工作在两个层面的不同协议。IPSec是在IP层,所以当需要对IP层以上的协议(如TCP和UDP)都加密或使用专用隧道通信,就需要采用IPSec。另外IPSec更适合在两个网络直接建立VPN,每个网络提供一个连接点。
SSL-VPN采用SSL/TLS协议,工作在TCP之上,一般用于应用的VPN连接,用于点到网的VPN,如手机的移动办公(手机通过VPN访问公司内部网络)。
常见加密算法和AES
前面我们讲了对称加密和分对称加密两种方式,以及SSL/TLS和IPsec两种不同层面的协议加密。但是具体加密的实施还是需要加密算法来完成的。
常见的对称加密算法有:DES、AES、ChaCha20-Poly1305等。常见的非对称加密算法有:RSA、DSA、ECDSA、 DH、ECDHE等。
这里在顺便提一下认证算法,也就是前面所述生成数字签名的算法。
认证算法的实现主要是通过杂凑函数。杂凑函数是一种能够接受任意长的消息输入,并产生固定长度输出的算法,该输出称为消息摘要。如果两个摘要是相同的,则表示报文是完整未经篡改的。例如IPsec使用两种认证算法:
MD5:MD5通过输入任意长度的消息,产生128bit的消息摘要。
SHA-1:SHA-1通过输入长度小于2的64次方bit的消息,产生160bit的消息摘要。
MD5算法的计算速度比SHA-1算法快,而SHA-1算法的安全强度比MD5算法高。
AES
这里主要介介绍AES算法,只介绍AES在使用上需要的知识,而不涉及内部算法。最后给出例子来帮助理解AES加密解密的使用方法。
首先我们要记清楚,AES是一种对称加密算法。
AES的麻烦
相比于其他加密,AES加密似乎模式很多,包括ECB、CBC等等等等,每个模式又包括IV参数和Padding参数,并且,不同语言对AES加密的库设计有区别。这些导致AES加密在不同人之间联调会很麻烦。
AES属于块加密
不难理解,对越长的字符串进行加密,代价越大,所以通常对明文进行分段,然后对每段明文进行加密,最后再拼成一个字符串。块加密的一个要面临的问题就是如何填满最后一块?所以这就是PADDING的作用,使用各种方式填满最后一块字符串,所以对于解密端,也需要用同样的PADDING来找到最后一块中的真实数据的长度。
加密模式
AES分为几种模式,比如ECB,CBC,CFB等等,这些模式除了ECB由于没有使用IV而不太安全,其他模式差别并没有太明显,大部分的区别在IV和KEY来计算密文的方法略有区别。具体可参考WIKI的说明。
另外,AES分为AES128,AES256等,表示期待秘钥的长度,比如AES256秘钥的长度应该是256/8的32字节,一些语言的库会进行自动截取,让人以为任何长度的秘钥都可以。而这其实是有区别的。
IV的作用
IV称为初始向量,不同的IV加密后的字符串是不同的,加密和解密需要相同的IV,既然IV看起来和key一样,却还要多一个IV的目的,对于每个块来说,key是不变的,但是只有第一个块的IV是用户提供的,其他块IV都是自动生成。
IV的长度为16字节。超过或者不足,可能实现的库都会进行补齐或截断。但是由于块的长度是16字节,所以一般可以认为需要的IV是16字节。
PADDING
AES块加密说过,PADDING是用来填充最后一块使得变成一整块,所以对于加密解密两端需要使用同一的PADDING模式,大部分PADDING模式为PKCS5, PKCS7, NOPADDING。
加密解密端
所以,在设计AES加密的时候
- 对于加密端,应该包括:加密秘钥长度,秘钥,IV值,加密模式,PADDING方式。
- 对于解密端,应该包括:解密秘钥长度,秘钥,IV值,解密模式,PADDING方式。
Nodejs实现
这里使用Nodejs的模拟AES加密解密
点击(此处)折叠或打开
-
var crypto = require("crypto");
-
-
var algorithm='aes-256-cbc';
-
var key = new Buffer("aaaabbbbccccddddeeeeffffgggghhhh");
-
var iv = new Buffer("1234567812345678");
-
function encrypt(text){
-
var cipher=crypto.createCipheriv(algorithm,key,iv);
-
cipher.update(text,"utf8");
-
return cipher.final("base64");
-
}
-
function decrypt(text){
-
var cipher=crypto.createDecipheriv(algorithm,key,iv);
-
cipher.update(text,"base64");
-
return cipher.final("utf8");
-
}
-
-
var text="ni你好hao";
-
var encoded=encrypt(text)
-
console.log(encoded);
- console.log(decrypt(encoded))
结果如下
点击(此处)折叠或打开
- WfH4hzIc3dc0pjxa9V/RgQ==
- ni你好hao
nodejs自带的并不能自动配置padding等参数,演示起来并不方便。于是使用另一个框架的nodejs库实现和之前完全相同的版本
点击(此处)折叠或打开
-
var CryptoJS = require("crypto-js");
-
var key ="aaaabbbbccccddddeeeeffffgggghhhh";
-
var iv = "1234567812345678";
-
-
function encrypt(text){
-
return CryptoJS.AES.encrypt(text,CryptoJS.enc.Utf8.parse(key),{
-
iv:CryptoJS.enc.Utf8.parse(iv),
-
mode:CryptoJS.mode.CBC,
-
padding:CryptoJS.pad.Pkcs7
-
})
-
}
-
-
function decrypt(text){
-
var result = CryptoJS.AES.decrypt(text,CryptoJS.enc.Utf8.parse(key),{
-
iv:CryptoJS.enc.Utf8.parse(iv),
-
mode:CryptoJS.mode.CBC,
-
padding:CryptoJS.pad.Pkcs7
-
})
-
return result.toString(CryptoJS.enc.Utf8)
-
}
-
-
var text="ni你好hao";
-
var encoded=encrypt(text)
-
console.log(encoded.toString());
- console.log(decrypt(encoded))
现在aes的参数都变成可配置的,接下来验证一下之前对AES的理解。
l 改变IV的长度,发现当IV大于16字节的时候,不管16字节之后的是什么,都不影响加密结果,应该是种自动截取机制(nodejs原生库IV不是16字节,就会报错)
l 改变IV的长度,当IV小于16字节,还可以成功加密,可能是自动补齐机制
l 加密IV和解密IV不同的时候,并不影响解密是否成功,但是解密的结果有差别,比如将解密的IV变成1234567813345678,则解密结果变为ni你好h`o
l 修改padding,加密解密的padding换成NoPadding,发现解密之后生成utf8字符串出错
l 经过多次尝试,加密为Pkcs7和ZeroPadding时,加密后的字符串变化显著,这时解密用任何padding模式,都可以成功解密。
ni你好hao,经过Pkcs7后,输出为
点击(此处)折叠或打开
- WfH4hzIc3dc0pjxa9V/RgQ==
nopadding后,输出为
点击(此处)折叠或打开
- OtSNypfx1SF6C2E=
zeropadding后,输出为
点击(此处)折叠或打开
- OtSNypfx1SF6C2GfyXMidA==
Pkcs7的结果和其他结果相差很大,很难相信其padding是补充最后一块。有趣的是Pkcs7的结果和zeropadding的结果通过同样的解密设置,能解出同样的字符串ni你好hao
总结
AES加密解密的秘钥有一对,一个是IV一个是KEY,并且他们的长度都有严格要求。
Padding的作用似乎不只是补齐最后,如果自己什么都对,但是加密失败,可以尝试不同Padding
参考资源
数字签名原理简介(附数字证书):https://www.cnblogs.com/kingsleylam/p/4985571.html
IPsec协议的ESP报文的装包与拆包过程:https://blog.csdn.net/chenxz_/article/details/85220199
理解AES加密解密的使用方法:https://blog.csdn.net/Vieri_32/article/details/48345023
详解 HTTPS、TLS、SSL、HTTP区别和关系:https://blog.csdn.net/chan70707/article/details/82932153
HTTPS 原理详解: