# Cipher 消息加密
MornBoot提供统一加密组件,主要目的是屏蔽不同算法之间的差异,规避高昂的学习成本。JDK、Spring等框架虽然提供了非常完善的加密算法,但一些较为复杂的算法(例如:AES),则需要大量的时间学习概念和API的使用。
Since:v1.2.1
当前支持:
- AES
- ECB
- GCM
- BCrypt
- MD5
# 必要配置
application.properties
#加密密码(16位字符串)
morn.cipher.password=HZlhUvtwrscvQl2c
在网络安全中,一般来说不会防范有文件读写权限的攻击者,这应该是另一个维度的安全问题。应用中通常只能提高这类攻击者的破译成本,因此建议集成配置中心设置密码。如果对密码的安全要求极高,目前建议继承加密实现类,重写密码的读取方式,在后续版本中,可能会推出密钥的多种读取方式。
# AES
默认密钥长度为128位,向量长度为12位。配置参考:CipherProperties
。
根据目前的科学技术,128位的密钥已经达到了暴力破解远远无法承受的地步,比起盲目提高密钥长度,更应该保证的是密钥的安全。
注意:AES密文均采用Base64编码,将加密后的字节编译为可读文本。
# AES-ECB
ECB算法相对简单,没有防篡改功能,适合加密有隐私性,但不重要的数据。
public class CiphersTest {
/**
* 原始文本
*/
private static final String PLAIN_TEXT = "password";
/**
* ECB加密
*/
public void testAESForECB() {
// 加密
Algorithm algorithm = AlgorithmBuilder.withName(AES).mode(AES_ECB_PKCS5PADDING).build();
String encrypt = Ciphers.encrypt(algorithm, PLAIN_TEXT);
// 解密
String decrypt = Ciphers.decrypt(algorithm, encrypt);
// 校验
boolean matches = Ciphers.matches(algorithm, PLAIN_TEXT, encrypt);
}
}
密文示例:
3Rfxf5ENwbS924owowS9QA==
# AES-GCM
GCM算法更加复杂,并且验证了完整性、真实性,同时MornBoot几乎屏蔽了ECB和GCM的使用差异(随机向量、连接消息),大部分场景比ECB更加适用。
public class CiphersTest {
/**
* 原始文本
*/
private static final String PLAIN_TEXT = "password";
/**
* GCM加密
*/
public void testAESForGCM() {
// 加密
Algorithm algorithm = AlgorithmBuilder.withName(AES).mode(AES_GCM_NO_PADDING).build();
String encrypt = Ciphers.encrypt(algorithm, PLAIN_TEXT);
// 解密
String decrypt = Ciphers.decrypt(algorithm, encrypt);
// 校验
boolean matches = Ciphers.matches(algorithm, PLAIN_TEXT, encrypt);
}
}
密文示例:
AAAADOiw5/1GeSwJpxcM/mcskV9Dkn6DXl1hpFkgTmKdi1uYFMB6XA==
# BCrypt
准确来说是SpringBCrypt,是SpringSecurity (opens new window)的默认加密算法,作用类似MD5,通常用于加密登录密码。SpringSecurity (opens new window)会在加密文本中记录算法标识,与BCrypt (opens new window)略有差别。
public class CiphersTest {
/**
* 原始文本
*/
private static final String PLAIN_TEXT = "password";
public void encryptBCrypt() {
// 加密
String password = Ciphers.encrypt(SPRING_B_CRYPT, PLAIN_TEXT);
// 匹配
boolean matches = Ciphers.matches(SPRING_B_CRYPT, PLAIN_TEXT,
"{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG");
}
}
密文示例:
{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
# MD5
信息摘要算法,主要用于防篡改,验证信息完整性。
public class CiphersTest {
/**
* 原始文本
*/
private static final String PLAIN_TEXT = "password";
public void encryptMD5() {
// 加密
String password = Ciphers.encrypt(MD5, PLAIN_TEXT);
// 匹配
boolean matches = Ciphers.matches(MD5, PLAIN_TEXT, "5f4dcc3b5aa765d61d8327deb882cf99");
}
}
密文示例:
5f4dcc3b5aa765d61d8327deb882cf99
# Other
针对MornBoot尚未收录的算法,或业务项目中的特殊算法,MornBoot也支持自由扩充算法池。
# 扩充加密算法
使用@AlgorithmName
标注算法名称,实现AlgorithmEncryption
接口,即可编写自定义算法。同理,实现AlgorithmDecryption
接口,即可编写自定义解密算法。
通常还需要继承
SimpleAlgorithmHolder
,可以访问Algorithm
对象。
@AlgorithmName(SPRING_B_CRYPT)
public class SecurityBCryptEncryption extends SimpleAlgorithmHolder implements AlgorithmEncryption {
@Override
public String encrypt(CharSequence text) {
return PasswordEncoderFactories.createDelegatingPasswordEncoder().encode(text);
}
}
注意通过
@Bean
/@Component
等任意方式注入Spring容器中,使用Ciphers
调用加密算法。
# 扩充匹配算法
实现方式和加密类似。一般来说,不可逆加密需要将明文加密后与密文匹配;可逆加密则需要将密文解密后与明文匹配,很多可逆加密会参入随机数进行运算。
@Slf4j
@AlgorithmName(SPRING_B_CRYPT)
public class SecurityBCryptMatcher extends SimpleAlgorithmHolder implements AlgorithmMatcher {
@Override
public boolean matches(CharSequence rawText, CharSequence encodedText) {
try {
return PasswordEncoderFactories.createDelegatingPasswordEncoder()
.matches(rawText, encodedText.toString());
} catch (Exception e) {
log.warn(e.getMessage(), e);
return false;
}
}
}
相对复杂的示例可以参考AES加密:
AESAlgorithms