分类
加密分为三种:
- 对称加密(symmetric),例如:AES、DES(已经被AES取代)等
- 非对称加密(asymmetric),例如:RSA、DSA等
- 摘要加密(digest),例如:MD5、SHA-1、SHA-256、HMAC等
以下的演示,一种是使用hutool封装好的方法,一种是使用自己封装的方法
如果是hutool封装的方法,则需要导入依赖
hutool简介:Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.22</version>
</dependency>
RSA
RSA公开密钥密码体制是一种使用不同的加密密钥与解密密钥,“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制
是非对称加密算法,所以需要公钥和私钥,而且公钥和私钥是有一定规则的,不能随意使用
然后就是使用公钥加密的话,就得用私钥加密
使用私钥加密,公钥解密
- hutool
//生成密钥方式
KeyPair rsa = SecureUtil.generateKeyPair("RSA");
String privateKey = Base64.encode(rsa.getPrivate().getEncoded());
String publicKey = Base64.encode(rsa.getPublic().getEncoded());
System.out.println("私钥:"+privateKey);
System.out.println("公钥:"+publicKey);
下面是以私钥加密,然后公钥解密的情况进行
模拟场景:
用户端持有私钥,将请求进行rsa加密,然后将byte[]数组再加密为base64
然后被请求端持有公钥,先将base64进行解密,然后使用公钥进行rsa解密
//公钥和私钥是需要成对生成的
String publicKey="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkBbLK/MPqwZ2ZAcUmPJ88tltwYdfzTEK+/1lYfBnKczD5ZC4p5aigPkXxNCqnp/FI9g6EfDI1zKO2+yXhkuEpZqgqWuoTkWbL7oWxcDs02RH8dYtbDAogwZqpfyoC/LbzQGBdnWs+ZhEz7Gpzzo6Ou2s56U6WZmo1N9uL6sFfUUpPEUUWNCkUPuATh6YBSgllN74IJvfK5CxzmSWCea9H5l4DS+AH8fdiiSnJKKQyLSePo88iWgS5Ck0oMATbE0Q5wXvB8jTtHxUxGCPrA/nW5gxbeWR4sp8QADgU+gOuaW+TOaFblowJWHEgS/9wrc+Ds6Wk1OkFOhs36EAMBaZywIDAQAB";
String privatekey="MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCQFssr8w+rBnZkBxSY8nzy2W3Bh1/NMQr7/WVh8GcpzMPlkLinlqKA+RfE0Kqen8Uj2DoR8MjXMo7b7JeGS4SlmqCpa6hORZsvuhbFwOzTZEfx1i1sMCiDBmql/KgL8tvNAYF2daz5mETPsanPOjo67aznpTpZmajU324vqwV9RSk8RRRY0KRQ+4BOHpgFKCWU3vggm98rkLHOZJYJ5r0fmXgNL4Afx92KJKckopDItJ4+jzyJaBLkKTSgwBNsTRDnBe8HyNO0fFTEYI+sD+dbmDFt5ZHiynxAAOBT6A65pb5M5oVuWjAlYcSBL/3Ctz4OzpaTU6QU6GzfoQAwFpnLAgMBAAECggEAETyo0XkiRrNfNlgifqmDiQm5t40aSNG1HrARkMXRkY6NYMkPTf0XM5aY4VKVFqTGUKNtTvgfDp9dt7F17vrZw3XcAmh+md550hvQ3ZdWvXMhqCyXAnpAXmxGFdVDxSooYT3s3t708mbk1HPMfJ3amXIVXSDG+jEHoW+ZHtq2rWWKs5/Vqvxk4BU0+vdnkXYuCxPsR9Ym+HxABVywquJt3+kj8UktuDEmk1NvxaQIEuIkx0VI83UOy07r8771s4p6THTKf+A2n+K6tk+aXiRSUXBneIOy+IT2E3XL8IRdji5B0xV1hIqUD+hQjM95KHU8YdHfO5RNSr8QWcBGhGttAQKBgQDDqfuHynNNEjpwX/GlnYjd+rb07i83aN7xPAbKyJXRGOXsbIU94EfeEevb8VFJjItSc42Bchw5EGbKYi4faI2aqNmQ8QFf7c542XjbExTYZ7mVHUBiUqHYoMxf1VcfnRYmIM2CzhJRs87fpkkn9fEwEOhDKvpODnCwzK646tAk1wKBgQC8hWeMM+niVOPmprfV5yxbagbboRqrdk/Gydp2Xv6ciZtjDv7tkQn29tmbXHd93clwDpi2Gn76NQJwbTv2i5QrTmYh2t7ADOeBPR1+2+Wfe54O9mtXZIlWjAJdzn2qlm2ik9PEIMzP/sDawt5H9Q3+nEI+EgeLWJx3WGljVFzgLQKBgGC/Kv0QsIRaUAUCm8SNKYDBGDfxke0u8JWNXbplBhcW3ZFSc2uN+1slt17QaqYYVUdWlZB88NGSd5D4jN/A3cusU6+kS064klAVD/oa7EK4vv2pMg2r2BT6JTP5lBOwo6QEsjlMVaiKZO8XFLMqm7Btm7qihJOV9kilXHtYt8SPAoGAKxuuQ+cTEkgrHPD+lJEaGYUzMEG0oYSaVXCO3gZ23kCxIYOqU5SY3LoxpE8Om999Unxj+zAv3PMGLcMstQHRzd1NiWxNB0lsHqdk+T87UK6pw+4hOYipxvqZB+5R2hIv279F61E8xEsSunNY9MdafeApXZwt0XVfwgKbhrUhz7kCgYBlmuj3s/ZJuz94gV7NpyONpj9kGEEzTAfrNEI2oND+SA8i2EBQjFWQb9LdfMOpVclPsXCOTPQ113i3KveTLicy0ZWQ4jVY1sc9U5EtN/9ZWTktoahIgpQ0YzUeH+7GDrM7LNQCOI55LkbV0OSK3wlGiemUYW2Aa2Cr08z7s6Y9Rg==";
//私钥加密
RSA rsa1 = new RSA(privatekey, null);
byte[] encrypt1 = rsa1.encrypt("HELLO".getBytes(StandardCharsets.UTF_8), KeyType.PrivateKey);
String base64Str = Base64.encode(encrypt1);
System.out.println("加密后结果:"+base64Str);
//公钥解密
RSA dRsa = new RSA(null, publicKey);
byte[] decrypt1 = dRsa.decrypt(Base64.decode(base64Str), KeyType.PublicKey);
System.out.println(new String(decrypt1));
- 自己封装
参考连接:https://blog.csdn.net/piaoranyuji/article/details/126140261
package com.walker.encrypt.util;
import lombok.extern.slf4j.Slf4j;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class RSAUtil {
public static final String KEY_ALGORITHM = "RSA";
private static final String PUBLIC_KEY = "RSAPublicKey";
private static final String PRIVATE_KEY = "RSAPrivateKey";
// 1024 bits 的 RSA 密钥对,最大加密明文大小
private static final int MAX_ENCRYPT_BLOCK = 117;
// 1024 bits 的 RSA 密钥对,最大解密密文大小
private static final int MAX_DECRYPT_BLOCK = 128;
// 生成密钥对
public static Map<String, Object> initKey(int keysize) throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
// 设置密钥对的 bit 数,越大越安全
keyPairGen.initialize(keysize);
KeyPair keyPair = keyPairGen.generateKeyPair();
// 获取公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 获取私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap = new HashMap<>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
// 获取公钥字符串
public static String getPublicKeyStr(Map<String, Object> keyMap) {
// 获得 map 中的公钥对象,转为 key 对象
Key key = (Key) keyMap.get(PUBLIC_KEY);
// 编码返回字符串
return encryptBASE64(key.getEncoded());
}
// 获取私钥字符串
public static String getPrivateKeyStr(Map<String, Object> keyMap) {
// 获得 map 中的私钥对象,转为 key 对象
Key key = (Key) keyMap.get(PRIVATE_KEY);
// 编码返回字符串
return encryptBASE64(key.getEncoded());
}
// 获取公钥
public static PublicKey getPublicKey(String publicKeyString) throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] publicKeyByte = Base64.getDecoder().decode(publicKeyString);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyByte);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
return keyFactory.generatePublic(keySpec);
}
// 获取私钥
public static PrivateKey getPrivateKey(String privateKeyString) throws Exception {
byte[] privateKeyByte = Base64.getDecoder().decode(privateKeyString);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyByte);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
return keyFactory.generatePrivate(keySpec);
}
/**
* BASE64 编码返回加密字符串
*
* @param key 需要编码的字节数组
* @return 编码后的字符串
*/
public static String encryptBASE64(byte[] key) {
return new String(Base64.getEncoder().encode(key));
}
/**
* BASE64 解码,返回字节数组
*
* @param key 待解码的字符串
* @return 解码后的字节数组
*/
public static byte[] decryptBASE64(String key) {
return Base64.getDecoder().decode(key);
}
/**
* 公钥加密
*
* @param text 待加密的明文字符串
* @param publicKeyStr 公钥
* @return 加密后的密文
*/
public static String encrypt1(String text, String publicKeyStr) {
try {
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKeyStr));
byte[] tempBytes = cipher.doFinal(text.getBytes("UTF-8"));
return Base64.getEncoder().encodeToString(tempBytes);
} catch (Exception e) {
throw new RuntimeException("加密字符串[" + text + "]时遇到异常", e);
}
}
/**
* 私钥解密
*
* @param secretText 待解密的密文字符串
* @param privateKeyStr 私钥
* @return 解密后的明文
*/
public static String decrypt1(String secretText, String privateKeyStr) {
try {
// 生成私钥
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKeyStr));
// 密文解码
byte[] secretTextDecoded = Base64.getDecoder().decode(secretText.getBytes("UTF-8"));
byte[] tempBytes = cipher.doFinal(secretTextDecoded);
return new String(tempBytes);
} catch (Exception e) {
throw new RuntimeException("解密字符串[" + secretText + "]时遇到异常", e);
}
}
public static void main(String[] args) throws Exception {
Map<String, Object> keyMap;
String cipherText;
// 原始明文
String content = "你好你好";
// 生成密钥对
keyMap = initKey(1024);
String publicKey = getPublicKeyStr(keyMap);
System.out.println("公钥:"+publicKey);
String privateKey = getPrivateKeyStr(keyMap);
System.out.println("私钥:"+privateKey);
// 加密
cipherText = encrypt1(content, publicKey);
System.out.println("加密后的密文:"+cipherText);
// 解密
String plainText = decrypt1(cipherText, privateKey);
System.out.println("解密后明文:"+plainText);
}
}
AES
密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。
- hutool
//随机生成密钥
byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();
AES aes = SecureUtil.aes(key);
//加密
byte[] encrypt = aes.encrypt("hello");
System.out.println(new String(encrypt));
//解密
System.out.println(aes.decryptStr(encrypt));
- 封装
package com.walker.encrypt.util;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class AESUtil {
private final static String AES = "AES";
private static final String AES_ALGORITHM = "AES/ECB/PKCS5Padding";
/**
* 获取cipher
*/
private static Cipher getCipher(byte[] key, int model) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException {
SecretKeySpec aes = new SecretKeySpec(key, AES);
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
cipher.init(model, aes);
return cipher;
}
/**
* 加密
*/
public static String encrypt(byte[] data, byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = getCipher(key, Cipher.ENCRYPT_MODE);
return Base64.getEncoder().encodeToString(cipher.doFinal(data));
}
/**
* 解密
*/
public static byte[] decrypt(byte[] data, byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = getCipher(key, Cipher.DECRYPT_MODE);
return cipher.doFinal(Base64.getDecoder().decode(data));
}
}
MD5
MD5的全称是Message-Digest Algorithm 5(信息-摘要算法),是不可逆的
作用:
是让大容量信息在用数字签名软件签署私人密匙前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的大整数)。它需要获得一个随机长度的信息并产生一个128位的信息摘要。
虽然md5是哈希加密,属于不可逆的,但是其他还是可以逆的,只是稍微复杂一下,所以密码加密还是不推荐使用md5,可以用使用security的BCryptPasswordEncoder
使用:
方式一: hutool
- 使用
String HELLO="hello";
SecureUtil.md5(HELLO)
方式二:自己封装
package com.walker.encrypt.util;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Util {
public static final String KEY_MD5 = "MD5";
/***
* MD5加密(生成唯一的MD5值)
*/
public static String encrypt(String str) {
byte[] digest = null;
try {
MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
digest = md5.digest(str.getBytes(StandardCharsets.UTF_8));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
//16是表示转换为16进制数
String md5Str = new BigInteger(1, digest).toString(16);
return md5Str;
}
}
base64
- hutool
String encode = Base64.encode(HELLO);
System.out.println("加密后"+encode);
byte[] decode = Base64.decode(encode);
System.out.println("解密后:"+new String(decode));
- 封装
package com.walker.encrypt.util;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.nio.charset.StandardCharsets;
public class Base64Util {
/***
* BASE64解密
* @param key
* @return
* @throws Exception
*/
public static String decryBASE64(String key) throws Exception{
byte[] bytes = (new BASE64Decoder()).decodeBuffer(key);
return new String(bytes);
}
/***
* BASE64加密
* @param key
* @return
* @throws Exception
*/
public static String encryptBASE64(String key) throws Exception{
return (new BASE64Encoder()).encode(key.getBytes(StandardCharsets.UTF_8));
}
}