文章目录
- 单向散列哈希算法
- md5
- DigestUtils(spring)实现md5
- 对称加密算法
- base64
- BASE64
- jdk自带base64工具
- base64有什么好处
- aes加密算法
- 代码
- AES加密时报错 Cannot find any provider supporting AES/CBC/PKCS7Padding
- aes加密时报错 Illegal key size or default parameters
- 非对称加密算法(又称:公开密钥加密算法)
- 对称加密和非对称加密的结合
单向散列哈希算法
摘要算法的特点:
1、无论输入的长度是多少,输出总是固定的长度。
2、如果输入有变化,摘要一定不同。
基于这个原理可以对数据的完整性和一致性进行校验。
由于是提取的不是全部内容,所以无法还原为原始值。
MD5、SHA(128、256)系列
描述 | 单向不可逆 |
场景 | 用户密码的加密 |
md5
摘要算法
DigestUtils(spring)实现md5
//md5 单向加密
String password="芝麻开门";
String digest = DigestUtils.md5DigestAsHex(password.getBytes()); // digest是摘要算法,这里只生成的字符串
System.out.println(digest);
对称加密算法
DES、3DES、AES、Blowfish、IDEA、RC5、RC6
base64
首先强调一点,base64属于编码算法,不属于加密算法,概念一定要搞清楚。
描述 | 双向可逆加密 |
场景 | 邮件中的信息 |
BASE64
base64工具类有很多。
jdk自带base64工具
jdk自带的base64工具就不错。 类路径为: java.util.Base64
// jdk自带的BASE64 加解密工具
String password="芝麻开门";
BASE64Encoder base64Encoder = new BASE64Encoder();
String encode = base64Encoder.encode(password.getBytes()); // 加密
System.out.println("加密为字符串: " + encode);
BASE64Decoder decoder = new BASE64Decoder();
try {
String decode = new String ( decoder.decodeBuffer(encode)); // 解密
System.out.println("解密为: " + decode);
} catch (IOException e) {
e.printStackTrace();
}
再来一个例子:
// 文件流到base64字符串
File refereeFile = new File("D://我的.jpg");
byte[] refereeFileOriginalBytes = FileUtils.readFileToByteArray(refereeFile);
String base64String = Base64.getEncoder().encodeToString(refereeFileOriginalBytes);
logger.info("base64字符串:{}",base64String);
//base64字符串到文件
byte[] bytes = Base64.getDecoder().decode(base64String);
File file = new File("D://base64转换为我的.jpg");
FileUtils.writeByteArrayToFile(file,bytes); // 执行完之后去文件系统查看是否有这个文件
字符串直接复制到java,因为太大可能报错,所以最好把字符串写在文件里面再读取,如下例子:
// 文件流到base64字符串
File refereeFile = new File("D://base64String.txt");
try {
String base64String = FileUtils.readFileToString(refereeFile);
//base64字符串到文件
byte[] bytes = Base64.getDecoder().decode(base64String);
File file = new File("D://base64转换为我的.jpg");
FileUtils.writeByteArrayToFile(file,bytes); // 执行完之后去文件系统查看是否有这个文件
} catch (IOException e) {
e.printStackTrace();
}
base64有什么好处
1是不直接显示文件流,稍微安全些。
另外,如果不考虑性能,数据之间的转移也比较方便,就当做是个大点的字符串。
对于需要反复读写的不是特别大的文件,可以把base64放在内存中。省去了io和网络rest的时间。
aes加密算法
五种加密算法:
ECB
CBC
CTR
OFB
CFB
不用纠结具体区别了,就是起个匹配的作用,和前后端匹配时一致即可。
主要参数:
key
偏移量(懒一点的话,可以设置为和key一样)
算法 例如:AES/CBC/PKCS7Padding
代码
aes属于通用工具,网上代码很多,随便来一段吧。
@Slf4j
@Component
public class AESUtils {
// AES密钥算法
private static final String KEY_ALGORITHM = "AES";
// 加密/解密算法/工作模式/填充方式
private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
@Value("${aesKey:kkkkkkkkkkkkkkkk==}")
private String tempAesKey;
public static String AES_KEY;
@PostConstruct
public void init(){
log.info("AES工具类初始化开始", tempAesKey);
AES_KEY=tempAesKey;
log.info("AES工具类初始化完成,aesKey={}",AES_KEY );
}
// 生成密钥
public static String generateAESKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
keyGenerator.init(128, new SecureRandom()); // 192 and 256 bits may not be available
SecretKey secretKey = keyGenerator.generateKey();
return Base64.getEncoder().encodeToString(secretKey.getEncoded());
}
// 加密
public static String encrypt(String data, String key) throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.getDecoder().decode(key), KEY_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] encrypted = cipher.doFinal(data.getBytes());
return Base64.getEncoder().encodeToString(encrypted);
}
// 解密
public static String decrypt(String data, String key) throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.getDecoder().decode(key), KEY_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] original = cipher.doFinal(Base64.getDecoder().decode(data));
return new String(original);
}
public static void main(String[] args) throws Exception {
// 这个方法只有第一次用,生成后以后固定用一个值即可 自己编写的key不一定符合位数等要求,所以第一次要自己生成
// String key = generateAESKey();
String key="kkkkkkkkkkkkkkkk==";
String originalText = "hello world";
String encryptedText = encrypt(originalText, key);
String decryptedText = decrypt(encryptedText, key);
log.info("key={}", key);
log.info("originalText={}", originalText);
log.info("encryptedText={}", encryptedText);
log.info("decryptedText={}", decryptedText);
}
}
注:一直以为aes很简单,眼高手低,实际使用的时候还是有些要注意。
例如用默认的方法,每次key都是重新生成,导致解密失败。
实际生成key后应该固定用这个key,就可以解密成功了。
AES加密时报错 Cannot find any provider supporting AES/CBC/PKCS7Padding
是因为jdk1.8不支持这个算法,需要下载补丁包,放到jdk jar包目录下。(不推荐,因为成本太多,从开发到服务器都要操作)
aes加密时报错 Illegal key size or default parameters
报错解释:
这个错误通常发生在使用Java加密时,尤其是AES加密算法。在JDK 8 Update 161及以后的版本中,引入了新的加密策略限制(称为JEP 261: JDK Cryptography Extension Policy),这意味着默认情况下,Java加密库中的一些加密算法可能被限制使用。Illegal key size or default parameters错误表明你正在使用的加密密钥大小超出了Java加密库的默认限制。
注:这堆内容啰哩吧嗦,知道是版本不对就行了。
解决方法:
1、更新JDK到8u161或更高版本,这样可以使用未受限制的加密策略。
2、下载补丁包。
jdk7的略。
# 这个是jdk8的,官网太慢,直接从这里下吧
下载完成后,解压缩下载的文件。你将会得到两个JAR文件:local_policy.jar和US_export_policy.jar。
下载包的readme.txt 有安装说明,即替换${jdk_home}/jre/lib/security
${jre_home}/lib/security
目录下的 local_policy.jar
和 US_export_policy.jar
文件。
自己下载的步骤
步骤 1:下载Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files打开Oracle官方网站,搜索"Java Cryptography Extension Unlimited Strength Jurisdiction Policy Files"。
进入下载页面,找到适用于你的Java版本的文件,并下载。
非对称加密算法(又称:公开密钥加密算法)
RSA,见rsa博客。
对称加密和非对称加密的结合