加密分为三种:
对称加密(symmetric),例如:AES、DES等SecureUtil.aes
SecureUtil.des
非对称加密(asymmetric),例如:RSA、DSA等SecureUtil.rsa
SecureUtil.dsa
摘要加密(digest),例如:MD5、SHA-1、SHA-256、HMAC等SecureUtil.md5
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.7.21version>
dependency>
SecureUtil.generateKey 针对对称加密生成密钥
SecureUtil.generateKeyPair 生成密钥对(用于非对称加密)
SecureUtil.generateSignature 生成签名(用于非对称加密)
对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。有时又叫传统密码算法,就是加密密钥能够从解密密钥中推算出来,同时解密密钥也可以从加密密钥中推算出来。而在大多数的对称算法中,加密密钥和解密密钥是相同的,所以也称这种加密算法为秘密密钥算法或单密钥算法。它要求发送方和接收方在安全通信之前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信的安全性至关重要。
String content = "test中文";
// 随机生成密钥 [B@4411d970
byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();
// 构建
AES aes = SecureUtil.aes(key);
// 加密为16进制表示 f2106f5c351f372b7f977022b65ba4df
String encryptHex = aes.encryptHex(content);
// 解密为字符串 test中文
String decryptStr = aes.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);
<dependency>
<groupId>org.bouncycastlegroupId>
<artifactId>bcprov-jdk15to18artifactId>
<version>1.68version>
dependency>
AES aes = new AES("CBC", "PKCS7Padding",
// 密钥,可以自定义
"0123456789ABHAEQ".getBytes(),
// iv加盐,按照实际需求添加
"DYgjCEIMVrj2W9xN".getBytes());
// 加密为16进制表示
String encryptHex = aes.encryptHex(content);
// 解密
String decryptStr = aes.decryptStr(encryptHex);
用法同AES
byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DES.getValue()).getEncoded();
DES des = SecureUtil.des(key);
最常用的就是RSA和DSA。非对称加密有公钥和私钥两个概念,私钥自己拥有,不能给别人,公钥公开。根据应用的不同,我们可以选择使用不同的密钥加密:
- 签名:使用私钥加密,公钥解密。用于让所有公钥所有者验证私钥所有者的身份并且用来防止私钥所有者发布的内容被篡改,但是不用来保证内容不被他人获得。
- 加密:用公钥加密,私钥解密。用于向公钥所有者发布信息,这个信息可能被他人篡改,但是无法被他人获得。
//new一个RSA对象
RSA rsa = new RSA();
//如果没有秘钥(公钥私钥)可以生成
//获得私钥
PrivateKey privateKey = rsa.getPrivateKey()
rsa.getPrivateKeyBase64()
//获得公钥
PublicKey publicKey = rsa.getPublicKey()
rsa.getPublicKeyBase64()
//也可以自定义秘钥生成
KeyPair pair = SecureUtil.generateKeyPair("RSA自定义秘钥");
PrivateKey aPrivate = pair.getPrivate();
PublicKey aPublic = pair.getPublic();
//公钥加密,私钥解密
byte[] encrypt = rsa.encrypt(publicKey, KeyType.PublicKey);
byte[] decrypt = rsa.decrypt(encrypt, KeyType.PrivateKey);
//私钥加密,公钥解密
byte[] encrypt2 = rsa.encrypt(privateKey, KeyType.PrivateKey);
byte[] decrypt2 = rsa.decrypt(encrypt2, KeyType.PublicKey);
//私钥
String PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIL7pbQ+5KKGYRhw7jE31hmA"
+ "f8Q60ybd+xZuRmuO5kOFBRqXGxKTQ9TfQI+aMW+0lw/kibKzaD/EKV91107xE384qOy6IcuBfaR5lv39OcoqNZ"
+ "5l+Dah5ABGnVkBP9fKOFhPgghBknTRo0/rZFGI6Q1UHXb+4atP++LNFlDymJcPAgMBAAECgYBammGb1alndta"
+ "xBmTtLLdveoBmp14p04D8mhkiC33iFKBcLUvvxGg2Vpuc+cbagyu/NZG+R/WDrlgEDUp6861M5BeFN0L9O4hz"
+ "GAEn8xyTE96f8sh4VlRmBOvVdwZqRO+ilkOM96+KL88A9RKdp8V2tna7TM6oI3LHDyf/JBoXaQJBAMcVN7fKlYP"
+ "Skzfh/yZzW2fmC0ZNg/qaW8Oa/wfDxlWjgnS0p/EKWZ8BxjR/d199L3i/KMaGdfpaWbYZLvYENqUCQQCobjsuCW"
+ "nlZhcWajjzpsSuy8/bICVEpUax1fUZ58Mq69CQXfaZemD9Ar4omzuEAAs2/uee3kt3AvCBaeq05NyjAkBme8SwB0iK"
+ "kLcaeGuJlq7CQIkjSrobIqUEf+CzVZPe+AorG+isS+Cw2w/2bHu+G0p5xSYvdH59P0+ZT0N+f9LFAkA6v3Ae56OrI"
+ "wfMhrJksfeKbIaMjNLS9b8JynIaXg9iCiyOHmgkMl5gAbPoH/ULXqSKwzBw5mJ2GW1gBlyaSfV3AkA/RJC+adIjsRGg"
+ "JOkiRjSmPpGv3FOhl9fsBPjupZBEIuoMWOC8GXK/73DHxwmfNmN7C9+sIi4RBcjEeQ5F5FHZ";
//new一个rsa对象
RSA rsa = new RSA(PRIVATE_KEY, null);
//秘文
String a = "2707F9FD4288CEF302C972058712F24A5F3EC62C5A14AD2FC59DAB93503AA0FA17113A020EE4EA35EB53F"
+ "75F36564BA1DABAA20F3B90FD39315C30E68FE8A1803B36C29029B23EB612C06ACF3A34BE815074F5EB5AA3A"
+ "C0C8832EC42DA725B4E1C38EF4EA1B85904F8B10B2D62EA782B813229F9090E6F7394E42E6F44494BB8";
//将秘文解码为16进制字符串
byte[] aByte = HexUtil.decodeHex(a);
//采用rsa解码方式解密秘文
byte[] decrypt = rsa.decrypt(aByte, KeyType.PrivateKey);
//秘文为 虎头闯杭州,多抬头看天,切勿只管种地
StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8);
摘要算法是一种能产生特殊输出格式的算法,这种算法的特点是:无论用户输入什么长度的原始数据,经过计算后输出的密文都是固定长度的,这种算法的原理是根据一定的运算规则对原数据进行某种形式的提取,这种提取就是摘要,被摘要的数据内容与原数据有密切联系,只要原数据稍有改变,输出的“摘要”便完全不同,因此,基于这种原理的算法便能对数据完整性提供较为健全的保障。
但是,由于输出的密文是提取原数据经过处理的定长值,所以它已经不能还原为原数据,即消息摘要算法是不可逆的,理论上无法通过反向运算取得原数据内容,因此它通常只能被用来做数据完整性验证。
String testStr= "哇哈哈哈";
String md5Hex = DigestUtil.md5Hex(testStr);
//deb16ca91d86283c5e32a38540a50c44
System.out.println(md5Hex);
Hutool针对java.security.Signature做了简化包装,包装类为:Sign,用于生成签名和签名验证。
byte[] data = "我是一段测试字符串".getBytes();
Sign sign = SecureUtil.sign(SignAlgorithm.MD5withRSA);
//签名
byte[] signed = sign.sign(data);
//验证签名
boolean verify = sign.verify(data, signed);