MD5 算法
消息摘要算法(Message-Digest Algorithm 5 ,MD5)是一种 密码散列函数
返回一个128 bit(16 bytes)的 散列值
消息
(message):要编码的密码 就称为消息。摘要
(digest): 生成的散列值称为消息摘要。
openssl 示例
它非常简单直接的基本思想是:
将 可变长度 的 数据集 映射到 数据集的 固定长度 的。
# 特点
- 数字指纹:输入任意长度的信息,经过处理,输出为128位的信息
- 唯一性:不同的输入得到的不同的结果
- 不可逆:无法通过密文得到明文
- 不抗冲突:这意味着不同的密码最终会导致相同的哈希
# MD5 用途
-
防止被篡改:
用一个文档生成一个MD5结果,之后如果文档被修改,再次生成的MD5结果必然与之前的不同。
如:Git、SVN等版本控制器 -
密码的存储:
由于不可逆性,不法分子拿到数据库中的MD5加密有的用户密码,不法分子也无法解析得到密码明文。
相反,通过唯一性,用户输入明文,服务器将明文进行MD5加密,然后跟数据库中的密文对比,能判断用户输入的明文是否正确。 -
防止抵赖(数字签名)
跟防止篡改一个道理。
第三方机构,通过 记录 文档的MD5 加密后数据
和作者
(或一些别的东西),形成映射关系。
当要追究文档责任时,能溯源找回作者
(或一些别额东西)
# 安全性
- 当加密内容过于简单或者有规律可循时,可以破解。(如生日,纯数字,身份证、电话号码等)
如:- 字典攻击:https://www.cmd5.com/default.aspx,这个网站就是通过存储一些常见加密结果和原文的映射,来进行密码破解的。
(彩虹表:https://blog.csdn.net/davidhuang2017/article/details/80285366)
- 字典攻击:https://www.cmd5.com/default.aspx,这个网站就是通过存储一些常见加密结果和原文的映射,来进行密码破解的。
- 当加密内容复杂时,(内容范围包含数字、字母大小写和其他字符,并且超过一定长度,如7时)普遍认为是安全的。
# 简单 JAVA 示例
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Enctypt {
public static void main(String[] args) {
// 密码
final String password = "123456";
// openssl算出来的 123456 的 MD5 加密结果
String passwordGenerated = "e10adc3949ba59abbe56e057f20f883e";
System.out.println(passwordGenerated.equals(Enctypt.MD5(password)));
}
public static String MD5(String message) {
String result = null;
try {
// Create MessageDigest instance for MD5
MessageDigest encoder = MessageDigest.getInstance("MD5");
// Add password bytes to digest
byte[] digest = encoder.digest(message.getBytes());
// This bytes[] has bytes in decimal format;
// Convert it to hexadecimal format
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
}
//Get complete hashed password in hex format
result = sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return result;
}
}
# 为 MD5 添加 salt 示例
考虑在安全性中添加一些 盐(salt)
维基百科将
salt
定义为 随机数据 ,用作哈希密码或密码短语的单向函数的附加输入。
更简单的说,salt是一些随机生成的文本,在获取哈希值之前会附加到密码中。
salting 的最初意图主要是打败预先计算的彩虹表攻击,否则可以用来大大提高破解密码数据库的效率。现在更大的好处是减慢并行操作,将一次密码猜测的哈希值与多个密码哈希值进行比较。
生成 salt
只要是随机数即可:
- UUID
- SHA1PRNG
Java 示例
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
public class Enctypt {
public static void main(String[] args) {
// 密码
final String password = "123456";
// openssl算出来的 123456 的 MD5 加密结果(无salt)
final String passwordGenerated = "e10adc3949ba59abbe56e057f20f883e";
System.out.println("no salt:" + Enctypt.MD5(password));
// 利用 UUID 生成 salt
String salt = UUID.randomUUID().toString();
System.out.println("salt:" + salt);
System.out.println("add salt:" + Enctypt.MD5(password, salt));
}
public static String MD5(String message) {
return MD5(message, null);
}
public static String MD5(String message, String salt) {
String result = null;
try {
// Create MessageDigest instance for MD5
MessageDigest encoder = MessageDigest.getInstance("MD5");
// Add salt bytes to digest
if (salt != null && !"".equals(salt)) {
encoder.update(salt.getBytes());
}
// Add password bytes to digest
byte[] digest = encoder.digest(message.getBytes());
result = parseToString(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return result;
}
private static String parseToString(byte[] digest) {
// This bytes[] has bytes in decimal format;
// Convert it to hexadecimal format
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
}
//Get complete hashed password in hex format
return sb.toString();
}
}
注意:如果加了 salt,必须把 salt 和 密文 存储在一起。否则,明文无法再次生成相同的密文
SHA 算法
安全散列算法(Secure Hash Algorithm,SHA)是 加密散列函数 族。
相同:
与MD5一样,两者均由MD4导出,SHA-1和MD5彼此很相似。
相应的,他们的强度和其他特性也是相似:
结果唯一、不抗冲突不可逆不同:
有以下几点不同:
- 对强行攻击的
安全
性:最显著和最重要的区别是SHA-1摘要比MD5摘要长32 位。使用强行技术,产生任何一个报文使其摘要等于给定报摘要的难度对MD5是2^128
数量级的操作,而对SHA-1则是2^160
数量级的操作。这样,SHA-1对强行攻击有更大的强度。速度
:在相同的硬件上,SHA-1的运行速度比MD5慢。
Java有4种SHA算法实现。与MD5(128位散列)相比,它们生成以下长度哈希值:
- SHA-1(160位哈希 - 最简单的一个 )
- SHA-256(256位散列 - 强于SHA-1)
- SHA-384(384位哈希 - 强于SHA-256)
- SHA-512(512位散列 - 强于SHA-384)
更长的哈希更难以打破。这是核心理念。
openssl示例
# JAVA 示例
将上面代码的获取实例部分修改即可:
MessageDigest.getInstance("SHA-1");
MessageDigest.getInstance("SHA-256");
... 384
... 512
概念:对称加密算法
看到这里,你应该要知道 对称加密算法
的概念。
在 对称加密算法
中:
- 数据发信方将
明文(原始数据)
和加密密钥(mi yue)
一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。 - 收信方收到密文后,若想解读原文,则需要使用
加密用过的密钥
及相同算法的逆算法
对密文进行解密,才能使其恢复成可读明文。
在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。
特点
- 有三样东西:
明文
、密钥
、加密&解密算法
- 密钥只有一个(发收双方持有相同密钥)
- 解密方需要事先知道
解密算法
优缺点
- 优点:算法公开、计算量小、加密速度快、加密效率高。
- 缺点:
1、使用同样钥匙,安全性得不到保证。
2、密钥管理困难(随通信次数,钥匙数量呈几何倍数增长,分布式情况尤为严重!)
五种对称加密算法
- DES:已破解,不再安全,基本没有企业在用了
但是对称加密算法的基石,具有学习价值,马上讲- DESede(三重DES)
- AES:最常用的对称加密算法
下面下面第二个讲- IDEA:常用的电子邮件加密算法
- PBE:综合了消息摘要算法和对称加密算法,最常见的是
PBEWithMD5AndDES
DES 算法
数据加密算法(Data Encryption Standard,DES),它是IBM公司于1975年研究成功并公开发表的。
DES 算法(理论部分)
因为这是对称加密的典型案例,所以必要介绍一些理论知识。
# 密码学基础
从本质上来说,DES的安全性依赖于虚假表象,从密码学的术语来讲就是依赖于“混乱和扩散”的原则。
- 混乱:目的是为隐藏任何明文同密文、或者密钥之间的关系
- 扩散:目的是使明文中的有效位和密钥一起组成尽可能多的密文。
两者结合到一起就使得安全性变得相对较高。
## Feistel结构
# DES 算法基础
- 分组:DES是一种分组加密算法,该算法每次处理固定长度的数据段,称之为分组。
- 填充:DES分组的大小是64位,如果加密的数据长度不是64位的倍数,可以按照某种具体的规则来填充位。
- 置换:对每个分组
# 一般结构图
其中,
- 扩展置换(P盒置换)的作用是
扩散(Diffusion)
。 使明文和密钥产生更多的密文 - S盒压缩(Substitution-box )的作用是
混乱
。隐藏明文和密文的关系
## 初始置换IP(initial permulation)和终止置换IP(final permulation)
初始置换IP(Initial Permutation)的作用在于将64位数据打乱重排,并分成左右两半,供后面的迭代使用。
-
置换,即对照置换表,一位一位的对数据分组进行置换
-
初始置换的结果(下图)
-
终止置换
终止置换的置换表和初始置换表示互逆的。
即,通过初始置换和终止置换,各分组的排序不变
## 扩展置换
- 经过初始置换的64位数据被分为左右32位数据(下图)
- 其中一边的32位数据进行扩展置换得到48位数据
- 具体填充过程如下
(其实,就是等分成8块,各自的首尾位置进行了添位操作)
## S盒压缩处理
上面进行了扩展,这里进行压缩
在经过扩展的48位明文和48密钥进行异或运算后,就会使用8个S盒压缩处理,得到32位数据
和扩展过程一样,等分成八份(每份6位),每份压缩为4位
以一份为例,演示压缩过程
AES 算法
高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法标准
Rijndael是该标准下的具体算法
(微信小程序加密传输就是用这个加密算法的)
# 与 DES 的异同
-
名字上看
Advanced Encryption Standard
和Data Encryption Standard
就差第一个单词,就知道他们关系不简单。
可以理解:AES就是DES的升级版。相同点:
- 均是分块加密(也均是对称加密)
- 均需要扩展密钥
- 均需要特定的表对明文进行转换
-
历史上看
DES早被破解了(不能对抗差分和线性密码分析),是不安全的。于是出了个三重DES
。
三重DES保证了安全性,但效率低。
于是,才出现了RSA,既保证安全性、又保证了效率 -
分组长度
DES分组比较短。
AES标准支持可变分组长度,分组长度可设定为32比特的任意倍数,最小值为128比特,最大值为256比特。
另外,RSA很好的抵抗差分密码分析及线性密码分析的能力。
# 加密流程(简述)
加密解密结构(下图)
加密函数(单次加密)的结构(下图)
# 现实应用
实际中,一般是
- 通过RSA(下面介绍)加密
AES的密钥
,传输到接收方 - 接收方解密得到
AES密钥
,然后发送方和接收方用AES密钥
来通信。
RSA 算法
RSA( Rivest
- Shamir
- Adleman
),名字来源算法的三位研发者(美国麻 省理工 学院三 位学者 Ron Rivest
、 Adi Shamir
及 Leonard Adleman
)(左)。
另外,后来资料表明,右边三位大神,最早提出这种算法,但由于工作保密的原因,无法公布。
这个算法的核心,是基于大素数的数学难题。
记住两点:
- 公钥:是大家都能知道的(包括不法分子),用于加密方借助公钥对数据加密
(非对称加密的核心就是:加密用的是公钥,而不再是私钥)- 私钥:让不法分子知道了,数据就泄漏了,因为能用于对数据的解密
1 生成公钥(generate public key )
公钥是在一定约束内,随便取的
公钥
由两部分组成:n
和e
-
得到
公钥 n
我们选择两个素数(prime) P 和 Q
通过 PxQ 我们得到公钥 n
-
得到
公钥 e
e 必须是个整数,不能整除公钥 n
,同时在一个范围内( 1 < e < φ ( n ) 1<e<\varphi (n) 1<e<φ(n))
这个 φ ( n ) \varphi (n) φ(n) “phi of n” 我们下面讲
-
“phi of n” 的计算公式 : φ ( n ) = ( p − 1 ) ( Q − 1 ) \varphi (n)= (p-1)(Q-1) φ(n)=(p−1)(Q−1)
是不是和 n 很像?
至此,我们得到:
- 公开的 : e 和 n
- 用于计算的:P、Q、 φ ( n ) = ( p − 1 ) ( Q − 1 ) \varphi (n)= (p-1)(Q-1) φ(n)=(p−1)(Q−1)
2 生成私钥(generate private key)
计算私钥,要用到
公钥 e
和 用于计算的 φ ( n ) = ( p − 1 ) ( Q − 1 ) \varphi (n)= (p-1)(Q-1) φ(n)=(p−1)(Q−1)
私钥 d
的计算如下:
对于这个计算过程,我们只需要知道:
由于之前 对公钥
的 一些列限值,
这里在计算私钥
时,>d 肯定是能算开的(即不存在无限小数)
3 用公钥加密数据(encrypt data with public key)
一堆乱七八糟,各种各样格式的信息,要加密,首先要转成加密方法认可的格式(如数字)
信息加密步骤1:转换
首先,将信息(data)转成(convert)数字形式
【注意,这不叫加密,只是一种方便处理的信息形式转换】
方法移异常多,如: ASCII、base64
这里简单把信息:Hi,转换成:89
信息加密步骤2:加密
计算密文,要用到完整的公钥,即:
公钥 n
和公钥 e
通过(下图)公式:( c = D a t a e m o d n c=Data^{e}\mod n c=Dataemodn)
得到我们的 密文 c
(encrypt data)
4 私钥解密数据(decrypt data with private key)
再复杂的加密,都需要能解密
(像MD5那样不可逆的,个人觉得不算完整加密算法,就像你把盒子用锁锁了,同时把钥匙丢海里,你不能说那把锁本身是把好锁,一个道理)
RSA 好在在复杂加密的情况下,有方便的解密过程。
这里要用到的参数:
.
加密数据 c
、私钥 d
和公钥 n
(不需要公钥 e
)
通过和加密公式类似的公式:( c = D a t a d m o d n c=Data^{d}\mod n c=Datadmodn)
和加密公式的区别是,幂次从 公钥 e
变成了 私钥 d
即可
即可进行解密
5 流程梳理
生成钥匙:
- 选取计算因子 P、Q
同时得到 φ ( n ) = ( p − 1 ) ( Q − 1 ) \varphi (n)= (p-1)(Q-1) φ(n)=(p−1)(Q−1) - 发布
计算出的公钥 n
和选取的公钥 e
- 保存
计算出的私钥 d
通信:
- 用
公钥 n
和公钥 e
对数据进行加密 - 用
公钥 n
和私钥 d
对数据进行解密
# 性能分析:RSA和AES对比
-
速度方面: AES优
从 RSA 加密过程中,需要对数据取模可以看出
(类似具体时间的测试很多) -
安全方面:毋庸置疑,非对称加密方式安全性上优于对称加密。
因此,目前最常用的加密方式采用AES与RSA相结合的应用,使它们的优缺点正好互补
RSA
加密速度慢,安全性好,应用于AES 密钥的加密
,传输到接收方,可解决DES 密钥分配的问题。AES
加密速度快,适合加密较长的报文,可用其加密明文
,接收方 通过RSA解密出AES密钥,从而解密出加密数据;
目前这种RSA和AES结合的方法已成为EMAIL保密通信标准。
done~