加密相关算法讲解
概述
本文将带你了解一些常见的加密算法和一些概念,比如:非对称加密、公钥加密、对称加密、密钥加密、分组加密、流加密、DES加密、AES加密、ECC加密、RSA加密等等。加密解密算法对于密码学体系来说,是最基础的操作,是实现一些操作的基本单元。
加解密的操作主要用于通讯,传递信息的信息不想被其他人知道,从来如此,以前多用于军方通讯。如今随着技术的发展和互联网盛行,人人之间通讯和人与第三方平台通讯大大增加,所以加密更多应用于我们的日常生活。 我们主要从两大块开始进行讲解那就是:对称加密
、非对称加密
。值得一提的是还有一种加密但是不能解密的算法就是Hash算法。
简要说明一下这些加密算法 的特性1
- 对称加密:就是
明文
加密成密文
和密文
解密成明文使用的同一个密钥。主要用于信的隐秘性。 - 非对称加密: 有两个密钥,一个密钥加密信息成密文,有且只能用另一个密钥解密成明文,主要用于认证、防抵赖和密钥交换
- 哈希函数: 使用特性算法把信息加密成简短的一段密文,这种加密不可逆。多应用于完整性的校验。
对称加密
对称加密(symmetric encryption
)可以称作:密钥加密(Secret key cryptography
)。对于对称加密来说,这个唯一的密钥需要被信息的发送者和信息者提前知道,让这双方都知道这个相同的密钥就不得不通讯,但是通讯没有使用加密又不安全,仿佛就变成一个悖论(这就需要我们的非对称加密了),后面会讲解,在本文章我们将了解几种常用的对称加密算法。
其实对称加密我们还能划分为两大阵营:流加密(stream ciphers
)和分组加密( block ciphers
)。
流加密
流加密包含一个状态更新函数和一个输出函数2。流加密的时候会有一个状态state
会在加密的过程中不断更新,输出函数会根据这个状态state
生成一个keystream
(其实是一个bits),当然keystream
也是在不断更新的。明文 不同位置的bits
会有不同的keystream
进行加密(怎么加密?例如异或操作)。 上面说的这个状态state
必然有初始状态(initial state
)存在,这个初始状态是怎么来的呢?通常有两种方式,第一种直接就是以key来生成初始状态,第二种是使用key和初始向量(IV
)来生成初始状态。
根据状态函数的更新方式还可以划分不同的流加密 ,如果状体更新不依赖我们发送的消息 称之为同步流加密
( synchronous stream cipher
);如果状态的更新依靠的是前N- bit的密文的话我们会称之为非同步流加密
(asynchronous
or self-synchronizing stream cipher
)。也有不属于两者的流加密(比如,可以依照明文进行状态的更新)。
必要常用的流密码 为ChaCha
,RC4, A5/1, A5/2, Chameleon, FISH, Helix, ISAAC, MUGI, Panama, Phelix, Pike, Salsa20, SEAL, SOBER, SOBER-128, WAKE.
分组加密
分组就加密就是把信息分成固定大小的块,然后对每一块进行加密。分组加密有不同的操作模式可以被选择,我们通过不同的操作方式对分组加密进行讲解。
加密的时候又有不同的加密算法。下面我们将了解一下加密模式,然后大致过一下有名的加密算法。
操作模式
- ECB模式(
Electronic Codebook
):这种模式就是首先把明文分成一块一块的,每一块大小相同,然后对每一组使用密钥进行加密生成密文快。这样会有一个问题,就是相同的明文块加密后的结果是相同的。这样的话很容易被插入攻击(直接在密文上删除一个密文块)和删除攻击(直接在密文上删除一个密文块)。
ECB加密图3:
ECB解密图3:
- CBC模式(
Cipher Block Chaining
): 这个是带有反馈机制的加密,怎么个反馈机制呢?就是之前的加密后影响我当前的加密。首先呢我们想要加密当前明文块,这时候我们就把上一把的明文块对应的密文块与当前的明文块做异或操作,生成的结果在进行加密进而生成当前明文块的密文块。一般来说第一个明文块加密的时候没有上一次的密文块,我们怎么办呢?这时候我们可以初始化一个向量。使用这个向量与第一个明文块做异或操作。
很明显CBC模式由于它的关联性避免了删除攻击和插入攻击。
CBC加密图3
CBC解密图3
PCBC模式(Propagating cipher block chaining)
和CBC差不多,就是在加密之前对明文块多做了一次异或处理. PCBC对明文做的处理为:
处理结果 = 明文块
xor
上一次明文块xor
上一次密文快PCBC加密图3:
PCBC解密图3:
Cipher Feedback (CFB)
把分组加密转化为流加密,略。
Output Feedback (OFB)
把分组加密转化为流加密,略。
Counter (CTR)
把分组加密转化为流加密,略。
具体的分组加密
具体的加密算法
- DES
全称为Data Encryption Standard
。它把数据分割为一个个64bits
的块,密钥为56bits
。由于密钥太短,当前计算机的算力都很高,暴力破解变得不是难事。2^56
的密钥尝试去暴力破解出当前的密钥。 变得不是很安全将被AES
所替代。 - 3DES
由于DES可以受到暴力破解, 人们就在DES的基础上做了一次升级,使用三个密钥(K1,K2,K3)对明文块进行DES加密。加解密如下
加密公式(E为加密的意思,D为解密的一次,ciphertext代表密文):
对明文使用K1进行一次加密,然后对结果使用K2进行解密,然后再对结果使用K3进行一次加密
解密公式
DES和3DES被爆出安全漏洞,在CBC模式下使用三重DES的HTTPS会话可能会“Sweet32”攻击。4,在今后会逐渐被AES所替代
- AES
AES全程为Advanced Encryption Standard
,AES 是基于代换-置换网络
(Substitution-Permutation Network
)设计的,安全性较高。加密时候会以密钥和明文作为输入到网络中,在网络中做多次代换操作和置换操作产生密文块。
对于AES加密的时候对于密钥长度有三种不同的选择,128
、192
、256
bits。但它们在加密分组的时候块大小都为128 bits
。 - SM4
国密对称算法。分组的块大小为128bit
,密钥的长度为128bit
。基于32轮非线性迭代结构、S盒实现。安全性较高。
Padding
有时候我们的分组加密,在分块的时候,最后一块是不满足固定长度的时候这就需要填充。对于ECB和CBC来说如果最后一块满足固定长度的话填充不填充都可以,如果不满足指定长度的话,不去填充就会报错无法加密。对于CFB、OFB和CTR填充不填充都可以,因为最后转化成流加密,不影响加密,这三种模式感觉也没人去填充意义不大。
下面我们简单介绍几种常用的填充规则。
PKCS#5 and PKCS#7
这两种是我们在分组加密的时候最常用,属于字节填充,这两种原理其实是一样只是针对块的大小不一样。
首先呢,填充的单位都是字节byte,还有一点为了防止填充的字节和源数据造成混乱,就是无论最后一个块够不够都得填充,如果最后一块够指定长度,那就在填充一整块。我们详细看下面。
如果最后一块缺一个字节,填充:
01
缺两个字节
02 02
缺三个字节
03 03 03
最后一块不缺字节,那就是缺一整块(假设一张块是16byte),那就填充16个0F
0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F
也就是说填充的每一个字节的数值,代表了这次填充的个数(字节为单位)。
在 PKCS#7的描述公式如下
01 -- if lth mod k = k-1
02 02 -- if lth mod k = k-2
.
.
.
k k ... k k -- if lth mod k = 0
lth
为加密的字节长度,k为块的字节长度。 k是>1的并且k最好小于256,这样的话填充函数才能更好的执行5。
PKCS#5
只针对块的为8字节定义的,从某种角度说PKCS#7
的填充包含了PKCS#5
的 。
Zero Padding
就是直接添加全是0的字节,以达到块的大小。这种填充很可能造成混淆。所以说,如果想要使用这种填充的话,要不就是知道源数据本来的长度,要不就是结尾有特殊标志(比如字符串)。要想使用这一种填充方式,加解密协商好即可。java平台实现字符串的Zero Padding
的话可以基于No Padding
包裹一层实现6
其他Padding
略
非对称加密
非对称加密(asymmetric cryptography
) 也称之为公钥加密(Public-key cryptography
)。
总结来说就是会有一对密钥(公钥和私钥),把其中的公钥公开,而私钥只有自己知道。数据的加密是由公钥
加密,有且只有对应的私钥
进行解密。
假如我有一对密钥,把其中的公钥公开,谁想给我发消息就用这个公钥加密然后发给我。非对称加密应用有很多重要的应用,其中包括数字签名、密钥协商等。本部分简单介绍三种非堆成加密的算法(RSA
、ECC
、SM2
),非对称详细应用请转到相对应文章。
RSA
RSA (Rivest–Shamir–Adleman)
是我们最初使用的公钥加密。现在我们看一下的它的内容结构。
首先的RSA的公私密钥生成是基于下面公式的,我们简单看一下。
代表什么意思呢?和m 都除以 n有相同的余数,这里的m代表我们的信息(在公式里面考虑成任意数值)。其中n和e代表公钥,d和n代表我们的私钥7。
具体的计算过程和算法的证明本文不涉及。
简单再说一下里面的数字都是怎么来的。n的话是有俩个质数p和q相乘得到的,即n=p*q
。n称为半素数。一般
其中n的长度代表密钥长度,rsa(2048Bits)
就代表这个n
的长度为2048Bits
。这个密钥长度的也代表了加密的强度。e和d就是通过一系列的复杂选择运算得到的。当n可以因式分解成两个素数,也就是宣布不安全了。为此RSA实验室曾经发起一个挑战,给出一组半素数,挑战分解因式分解这些数字获得相应报酬。
----加密
加密根据下面的公式
c是加密后的密文,m代表原文(公钥为e和n)
—解密
经过计算可得出m(原文),私钥为d和n。
ECC
ECC(Elliptic-curve cryptography
)是利用椭圆曲线实现公钥加密算法的。就是有一类特殊的椭圆曲线,可以通过某种数学操作来实现了非堆成加密,SM2就指定了一个椭圆曲线实现的公钥加密算法(非堆成加密算法)。
密钥生成过程8
上面这个线就是一个满足公钥加密的特殊的椭圆曲线,
- 首先我们找一个P点
- 通过P点做曲线做切线 ,交与椭圆曲线的点就是
2P'
,做x轴堆成,找到2P
点。2P点即为P点的2倍点; - 进一步,P点和2P点之间做直线,交与3P’点,在3P’点做竖线,交与3P点,3P点即为P点的3倍点;
- 同理,可以计算出P点的4、5、6、… 倍点;
- 选择一个大整数k, 找到P的k倍点
Q
上面的过程是生成公司密钥的过程,k为私钥,Q为公钥。当我们已知Q和P的时候是很难推导出k的,一般公钥加密都是基于数学难题的实现的。
同等密钥长度ECC算法比RSA更加安全。
加解密
略
域参数
域参数就是你要用哪一个曲线,指定一些初始参数。如果你给了一个公钥给别人,只告诉别人使用ECC加密的话,他们是不知道怎么去加密的,你得告诉具体的加密椭圆曲线算法。
比如TLS里面就是用了ECC公钥加密,在交互的时候就会告诉对方使用的什么算法。
有些时候证书里面携带的公钥是ECC公钥,当然也会说明出来使用的什么具体的椭圆曲线加密算法
SM2属于椭圆曲线算法,就指定了这些域参数。
SM2域参数:
现在。时至今日已经有了上百种了具体的椭圆曲线加密算法的实现了。有网站做了各个加密算法的域参数整理。
Reference
- TYPESOFCRYPTOGRAPHICALGORITHMS ↩︎
- Crypt analysis and Design of Stream Ciphers#1.2 Stream Cipher Design “A stream cipher consists of a state update function and an output function” ↩︎
- 对称分组加密模式流程图 “原理图” ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
- CVE-2016-2183 “The DES and Triple DES ciphers, as used in the TLS, SSH, and IPSec protocols and other protocols and products, have a birthday bound of approximately four billion blocks, which makes it easier for remote attackers to obtain cleartext data via a birthday attack against a long-duration encrypted session, as demonstrated by an HTTPS session using Triple DES in CBC mode, aka a “Sweet32” attack.” ↩︎
- rfc5652 " This padding method is well defined if and only if k is less than 256" ↩︎
- Java AES加密如何使用zero padding方式填充 “但Java提供No Padding这中方式,意思是不做填充,这肯定不行,那怎么办?其实要的就是你不填充,这样我才能自己填充,我想填什么就填什么” ↩︎
- RSA (cryptosystem#Operation) “The public key is represented by the integers n and e, and the private key by the integer d (although n is also used during the decryption process, so it might be considered to be a part of the private key too).” ↩︎
- SM2椭圆曲线公钥密码算法 “密钥生成过程参考” ↩︎