参考:Java 安全加密算法 - MD5,SHA256,SHA512,PBKDF2,BCrypt,SCrypt
消息摘要算法(Message-Digest Algorithm 5 ,MD5)是一种 密码散列函数
返回一个128 bit(16 bytes)的 散列值
消息
(message):要编码的密码 就称为消息。摘要
(digest): 生成的散列值称为消息摘要。
它非常简单直接的基本思想是:
将 可变长度 的 数据集 映射到 数据集的 固定长度 的。
防止被篡改:
用一个文档生成一个MD5结果,之后如果文档被修改,再次生成的MD5结果必然与之前的不同。
如:Git、SVN等版本控制器
密码的存储:
由于不可逆性,不法分子拿到数据库中的MD5加密有的用户密码,不法分子也无法解析得到密码明文。
相反,通过唯一性,用户输入明文,服务器将明文进行MD5加密,然后跟数据库中的密文对比,能判断用户输入的明文是否正确。
防止抵赖(数字签名)
跟防止篡改一个道理。
第三方机构,通过 记录 文档的 MD5 加密后数据
和 作者
(或一些别的东西),形成映射关系。
当要追究文档责任时,能溯源找回 作者
(或一些别额东西)
- 字典攻击:https://www.cmd5.com/default.aspx,这个网站就是通过存储一些常见加密结果和原文的映射,来进行密码破解的。
(彩虹表:https://blog.csdn.net/davidhuang2017/article/details/80285366)
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;
}
}
考虑在安全性中添加一些 盐(salt)
维基百科将
salt
定义为 随机数据 ,用作哈希密码或密码短语的单向函数的附加输入。
更简单的说,salt是一些随机生成的文本,在获取哈希值之前会附加到密码中。
salting 的最初意图主要是打败预先计算的彩虹表攻击,否则可以用来大大提高破解密码数据库的效率。现在更大的好处是减慢并行操作,将一次密码猜测的哈希值与多个密码哈希值进行比较。
生成 salt
只要是随机数即可:
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 和 密文 存储在一起。否则,明文无法再次生成相同的密文
安全散列算法(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位散列)相比,它们生成以下长度哈希值:
更长的哈希更难以打破。这是核心理念。
将上面代码的获取实例部分修改即可:
MessageDigest.getInstance("SHA-1");
MessageDigest.getInstance("SHA-256");
... 384
... 512
参考:常见对称加密算法
看到这里,你应该要知道 对称加密算法
的概念。
在 对称加密算法
中:
明文(原始数据)
和加密 密钥(mi yue)
一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。加密用过的密钥
及 相同算法的逆算法
对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。
特点
明文
、密钥
、加密&解密算法
解密算法
优缺点
五种对称加密算法
- DES:已破解,不再安全,基本没有企业在用了
但是对称加密算法的基石,具有学习价值,马上讲- DESede(三重DES)
- AES:最常用的对称加密算法
下面下面第二个讲- IDEA:常用的电子邮件加密算法
- PBE:综合了消息摘要算法和对称加密算法,最常见的是
PBEWithMD5AndDES
参考:视频【⭐️⭐️⭐️】 - DES加密算法-《信息安全技术》课程微课设计
数据加密算法(Data Encryption Standard,DES),它是IBM公司于1975年研究成功并公开发表的。
DES详解(Java实现)
因为这是对称加密的典型案例,所以必要介绍一些理论知识。
从本质上来说,DES的安全性依赖于虚假表象,从密码学的术语来讲就是依赖于“混乱和扩散”的原则。
- 混乱:目的是为隐藏任何明文同密文、或者密钥之间的关系
- 扩散:目的是使明文中的有效位和密钥一起组成尽可能多的密文。
两者结合到一起就使得安全性变得相对较高。
其中,
扩散(Diffusion)
。 使明文和密钥产生更多的密文混乱
。隐藏明文和密文的关系初始置换IP(Initial Permutation)的作用在于将64位数据打乱重排,并分成左右两半,供后面的迭代使用。
即,通过初始置换和终止置换,各分组的排序不变
上面进行了扩展,这里进行压缩
在经过扩展的48位明文和48密钥进行异或运算后,就会使用8个S盒压缩处理,得到32位数据
和扩展过程一样,等分成八份(每份6位),每份压缩为4位
高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法标准
Rijndael是该标准下的具体算法
(微信小程序加密传输就是用这个加密算法的)
名字上看
Advanced Encryption Standard
和 Data Encryption Standard
就差第一个单词,就知道他们关系不简单。
可以理解:AES就是DES的升级版。
相同点:
- 均是分块加密(也均是对称加密)
- 均需要扩展密钥
- 均需要特定的表对明文进行转换
历史上看
DES早被破解了(不能对抗差分和线性密码分析),是不安全的。于是出了个三重DES
。
三重DES保证了安全性,但效率低。
于是,才出现了RSA,既保证安全性、又保证了效率
分组长度
DES分组比较短。
AES标准支持可变分组长度,分组长度可设定为32比特的任意倍数,最小值为128比特,最大值为256比特。
另外,RSA很好的抵抗差分密码分析及线性密码分析的能力。
实际中,一般是
AES的密钥
,传输到接收方AES密钥
,然后发送方和接收方用 AES密钥
来通信。参考:李永乐老师11分钟讲RSA加密算法
RSA( Rivest
- Shamir
- Adleman
),名字来源算法的三位研发者(美国麻 省理工 学院三 位学者 Ron Rivest
、 Adi Shamir
及 Leonard Adleman
)(左)。
另外,后来资料表明,右边三位大神,最早提出这种算法,但由于工作保密的原因,无法公布。
这个算法的核心,是基于大素数的数学难题。
记住两点:
- 公钥:是大家都能知道的(包括不法分子),用于加密方借助公钥对数据加密
(非对称加密的核心就是:加密用的是公钥,而不再是私钥)- 私钥:让不法分子知道了,数据就泄漏了,因为能用于对数据的解密
公钥是在一定约束内,随便取的
公钥
由两部分组成:n
和e
得到 公钥 e
e 必须是个整数,不能整除 公钥 n
,同时在一个范围内( 1 < e < φ ( n ) 1
这个 φ ( 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)
计算私钥,要用到
公钥 e
和 用于计算的 φ ( n ) = ( p − 1 ) ( Q − 1 ) \varphi (n)= (p-1)(Q-1) φ(n)=(p−1)(Q−1)
对于这个计算过程,我们只需要知道:
由于之前 对公钥
的 一些列限值,
这里在计算私钥
时,>d 肯定是能算开的(即不存在无限小数)
一堆乱七八糟,各种各样格式的信息,要加密,首先要转成加密方法认可的格式(如数字)
首先,将信息(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)
再复杂的加密,都需要能解密
(像MD5那样不可逆的,个人觉得不算完整加密算法,就像你把盒子用锁锁了,同时把钥匙丢海里,你不能说那把锁本身是把好锁,一个道理)
RSA 好在在复杂加密的情况下,有方便的解密过程。
通过和加密公式类似的公式:( c = D a t a d m o d n c=Data^{d}\mod n c=Datadmodn)
和加密公式的区别是,幂次从 公钥 e
变成了 私钥 d
即可
即可进行解密
生成钥匙:
公钥 n
公钥 e
私钥 d
通信:
公钥 n
和 公钥 e
对数据进行加密公钥 n
和 私钥 d
对数据进行解密参考:浅析DES与AES、RSA三种典型加密算法的比较
速度方面: AES优
从 RSA 加密过程中,需要对数据取模可以看出
(类似具体时间的测试很多)
安全方面:毋庸置疑,非对称加密方式安全性上优于对称加密。
因此,目前最常用的加密方式采用AES与RSA相结合的应用,使它们的优缺点正好互补
RSA
加密速度慢,安全性好,应用于 AES 密钥的加密
,传输到接收方,可解决DES 密钥分配的问题。AES
加密速度快,适合加密较长的报文,可用其 加密明文
,接收方 通过RSA解密出AES密钥,从而解密出加密数据;目前这种RSA和AES结合的方法已成为EMAIL保密通信标准。
done~