1. 简介
这里也是从那几篇旧博客中抽出来的,不算一大部分了,主要介绍Java的加密相关知识点。本文先对加密算法进行整体的介绍,最后侧重的是散列算法。
常见加密如下:

对称加密算法的加密与解密 密钥相同;
非对称加密算法的加密密钥与解密 密钥不同;
散列算法 不需要密钥,生成摘要。
2. 非对称加密

-
如果使用 公钥 对数据 进行加密,只有用对应的 私钥 才能 进行解密。
-
如果使用 私钥 对数据 进行加密,只有用对应的 公钥 才能 进行解密。
3. 散列算法
散列算法如 MD5
、SHA1
是 不可逆的 (一般而言),不能用生成的散列值解密出原文。
-
MD5
MD5
用的是 哈希函数,它的典型应用是对一段信息产生 信息摘要,以 防止被篡改。严格来说,MD5
不是一种 加密算法 而是 摘要算法。无论是多长的输入,MD5
都会输出长度为 128bits
的一个串 (通常用 16
进制 表示为 32
个字符)。
-
SHA1
SHA1
是和 MD5
一样流行的 消息摘要算法,然而 SHA1
比 MD5
的 安全性更强。对于长度小于 2 ^ 64
位的消息,SHA1
会产生一个 160
位的 消息摘要(16进制表示为40个字符)。
散列算法虽然不可逆,却并不安全,因为hash算法是固定的,所以同一个字符串计算出来的hash串是固定的,所以,可以采用如下的方式进行破解。
- 暴力枚举法:简单粗暴地枚举出所有原文,并计算出它们的哈希值,看看哪个哈希值和给定的信息摘要一致。
- 字典法:黑客利用一个巨大的字典,存储尽可能多的原文和对应的哈希值。每次用给定的信息摘要查找字典,即可快速找到碰撞的结果。
- 彩虹表(rainbow)法:在字典法的基础上改进,以时间换空间。是现在破解哈希常用的办法。
4. 加盐散列算法
既然散列算法能够被破解,那就出现了通过加盐,来增强散列算算法,从而降低被rainbow破解的概率。
例如:md5(md5(password) + salt)
Bcrypt是一种该加盐散列算法,它内部自己实现了随机加盐处理,使用Bcrypt,每次加密后的密文是不一样的。
bcrypt(SH512(password), salt, cost)
对比普通加盐它多了一个cost参数,算法输入:明文、salt、cost,输出散列值。如下:
- hash产生过程:先随机生成salt,salt跟password进行hash,每次生成的hash不一样,hash中包含了salt
- 在下次校验时,从hash中取出salt,salt跟password进行hash;得到的结果跟保存在DB中的hash进行比对。
BCrypt算法将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题。
咋一看bcryptsalt、cost都提供,并没有比MD5等更安全,那是为什么呢?
主要是这个cost,使得bcrypt一个密码出来的时间比较长,需要0.3秒,而MD5只需要一微秒(百万分之一秒),一个40秒可以穷举得到明文的MD5,在bcrypt需要12年,时间成本太高。
代码:
BCrypt.hashpw(myPassword, BCrypt.gensalt());
BCrypt.checkpw(candidatePassword, dbPassword);
5. 应用:数字签名
签名是将原始数据通过散列算法形成唯一的散列码,然后随带原始数据一起传输,在接收侧再进行相同的处理,对比散列码确实是否有被修改过。
签名:原数据 => 散列 => 加密 => 签名
验证:签名 => 解密 => 散列值a, 原数据 => 散列 => 散列值b,对比a与b
ps:这种算法,需要对散列的算法或者秘钥保密,要是攻击者也把散列码也修改了,那这种应用也就无效了。
6. 参考
参考1、参考2、参考3