1. 加密算法
对称加密: 加密和解密用到的密钥是相同的, 这种加密方式加密速度非常快, 适合经常发送数据的场合. 缺点是密钥的传输比较麻烦.
非对称加密: 加密和解密用的密钥是不同的, 这种加密方式是用数学上的难解问题构造的, 通常加密解密的速度比较慢, 适合偶尔发送数据的场合. 优点是密钥传输方便.
2. 对称加密算法
2.1 AES
2.1.1 简介
AES(Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的).对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图:
实际中, 一般是通过RSA加密AES的密钥, 传输到接收方, 接收方解密得到AES密钥, 然后发送方和接收方用AES密钥来通信.
2.1.2 Java中使用AES
1 | import javax.crypto.Cipher; |
3. 非对称加密算法
3.1 RSA
3.1.1 算法步骤
- 找出质数 P, Q
- 计算公共模数 N = P * Q
- 计算欧拉函数 φ(N) = (P - 1) (Q - 1) , 说明: 符号φ(N)表示小于 N 且与 N 互质的正整数的个数
- 计算公钥E: 1 < E < φ(N), 其中, E 的取值必须是整数, E 和 φ(N) 必须是互质数
- 计算私钥D: E * D % φ(N) = 1
- 加密: C = M^E mod N, 其中, C-密文 M-明文
- 解密: M =C^D mod N, 其中, C-密文 M-明文
- 公钥=(E, N) , 私钥=(D, N)
3.1.2 算法示例
- 找出质数 P,Q (P=3, Q=11)
- 计算公共模数, N = P Q = 3 11 = 33
- 计算欧拉函数 φ(N) = (P - 1) (Q - 1) = 2 * 10 = 20
- 计算公钥E: 1 < E < 20, 因为 E 和 φ(N) 必须是互质数, 所以E 的取值范围 {3, 7, 9, 11, 13, 17, 19} 任取 E =3, 满足条件
- 计算私钥D: E D % φ(N) = 1, 即 3 D % 20 = 1, 取 D = 7 满足条件
- 公钥加密: 设 M = 2, C = M^E mod N = 2^3 % 33 = 8
- 私钥解密: M =C^D mod N = 8^7 % 33 = 2
- 公钥=(E, N) = (3, 33), 私钥=(D, N) = (7, 33)
3.1.3 JDK 自带 RSA 算法示例
1 | import sun.misc.BASE64Decoder; |
3.2 MD5算法
MD5的英文全称是Message Digest Algorithm MD5,译为消息摘要算法第五版,是众多哈希算法中的一种(哈希算法是一种可以将任意长度的输入转化为固定长度输出的算法)
因此MD5算法是一种哈希算法,严格来说不能称之为一种加密算法.
3.2.1 MD5算法的优点
- 容易计算:主流的编程语言基本都支持MD5算法的实现,所以非常容易计算出一个数据的MD5值.
- 不可逆性:无法通过常规的方式从MD5值倒推出它的原文.
- 压缩性:任意长度的数据,其MD5值都是一个32位长度的十六进制字符串,区分大小写.
- 抗修改性:对原数据做一丁点的改动,MD5值就会有巨大的变动.
- 抗碰撞性:知道了原数据的MD5值,想要碰撞出这个MD5值,从而猜测出原数据,是非常困难的.所有的MD5值一共有2的128次方种可能性.
3.2.2 MD5算法的不足
目前存在比较优的碰撞算法,因此在对安全性要求较高的场合,不建议直接使用MD5算法.
3.2.3 应用场景
数据库中用户信息的存储.
但是因为彩虹表的存在,所以也并不可靠.(彩虹表就是一个庞大的数据库,这个数据库里收集了着所有人常用的密码,以及这些密码对应的MD5值,SHA-X值等哈希值)
针对彩虹表问题,可以使用加盐的解决方案.
加盐一般的做法:
- 客户端MD5(pwd)
- 服务端MD5(客户端MD5(pwd)+salt),服务端保存密码 和 盐
3.2.4 Java中的使用MD5
1 | import java.security.MessageDigest; |
3.2.5 MD5算法原理
数据填充: 对消息进行数据填充,使消息的长度对512取模得448,设消息长度为X, 即满足X mod 512=448. 根据此公式得出需要填充的数据长度. 填充方法:在消息后面进行填充, 填充第一位为1, 其余为0. 填充完后, 信息的长度就是512 * N+448.
添加消息长度: 用剩余的位置(512-448=64位)记录原文的真正长度,把长度的二进制值补在最后.这样处理后的信息长度就是512*(N+1). 如果消息长度大于2^64, 则只使用其低64位的值, 即 消息长度 对 2^64取模. 在此步骤进行完毕后, 最终消息长度就是512的整数倍.
数据处理(设置初始值):MD5的哈希结果长度为128位,按每32位分成一组共4组.这4组结果是由4个初始值A,B,C,D经过不断演变得到.MD5的官方实现中,A,B,C,D的初始值如下(16进制):
4个常数:
A = 0x01234567
B = 0x89ABCDEF
C = 0xFEDCBA98
D = 0x76543210数据处理(循环加工):
使用如下四个函数循环加工,每一次循环都会让旧的ABCD产生新的ABCD.最后一次循环的结果即为MD5值.
4个函数:
F(X,Y,Z)=(X & Y) | ((~X) & Z)
G(X,Y,Z)=(X & Z) | (Y & (~Z))
H(X,Y,Z)=X ^ Y ^ Z
I(X,Y,Z)=Y ^ (X | (~Z))
4. 参考文献
AES 加密算法的原理详解
Java实现AES和RSA算法
RSA公钥密码体制的原理及应用
RSA 非对称加密原理(小白也能看懂哦~)
Java 实现 RSA 非对称加密算法:生成密钥对、保存/读取密钥、加密/解密
第一篇、MD5算法和SHA-1算法
java中使用MD5加密技术
MD5算法底层原理
MD5加密算法原理及实现