Base64
建议使用org.apache.commons.codec.binary.Base64
类库。
注意标准和url safe的base64。
DES
/**
* DES 加密
* @param password
* @param data
* @return
*/
@SneakyThrows
public static byte[] encrypt(String password, String data) {
if (password == null || password.length() < 8) {
throw new RuntimeException("加密失败,key不能小于8位");
}
if (data == null) {
return null;
}
// 生成一个可信任的随机数源
SecureRandom sr = new SecureRandom();
// 从原始密钥数据创建DESKeySpec对象
DESKeySpec dks = new DESKeySpec(password.getBytes(StandardCharsets.UTF_8));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(dks);
// Cipher对象实际完成解密操作
Cipher cipher = Cipher.getInstance("DES");
// 用密钥初始化Cipher对象
cipher.init(Cipher.ENCRYPT_MODE, secretKey, sr);
byte[] bytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
return bytes;
}
/**
* DES 解密
* @param password
* @param data
* @return
*/
@SneakyThrows
public static String decrypt(String password, byte[] data){
if (data == null) {
return null;
}
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(password.getBytes(StandardCharsets.UTF_8));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, secretKey, sr);
return new String(cipher.doFinal(data),StandardCharsets.UTF_8);
}
RAS
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.ArrayUtils;
import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class RSAUtils {
/**
* 生成密钥
* @param seed 种子
* @return 密钥对象
* @throws Exception
*/
public static void generateKey(String seed) throws Exception {
KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
SecureRandom secureRandom = new SecureRandom();
// 如果指定seed,那么secureRandom结果是一样的,所以生成的公私钥也永远不会变
// secureRandom.setSeed(seed.getBytes());
// Modulus size must range from 512 to 1024 and be a multiple of 64
keygen.initialize(2048, secureRandom);
KeyPair keys = keygen.genKeyPair();
PrivateKey privateKey = keys.getPrivate();
PublicKey publicKey = keys.getPublic();
}
/**
* 用私钥对信息进行数字签名
* @param data 加密数据
* @param privateKey 私钥 - base64加密后的
*/
@SneakyThrows
public static byte[] signByPrivateKey(byte[] data, String privateKey) {
// base64 解密私钥
byte[] keyBytes = Base64.decodeBase64(privateKey);
KeyFactory factory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
// 生成私钥
PrivateKey priKey = factory.generatePrivate(keySpec);
// 用私钥对信息进行数字签名
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(priKey);
signature.update(data);
return signature.sign();
}
/**
* 使用 公钥 校验签名
* @param data
* @param publicKey
* @param signByte
*/
@SneakyThrows
public static boolean verifyByPublicKey(byte[] data, String publicKey, byte[] signByte) {
byte[] keyBytes = Base64.decodeBase64(publicKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(pubKey);
signature.update(data);
// 验证签名
return signature.verify(signByte);
}
/**
* RSA公钥加密
* @param str 加密字符串
* @param publicKey 公钥
*/
@SneakyThrows
public static byte[] encodeWithPublicKey(String str, String publicKey) {
// base64解码的公钥
byte[] keyBytes = Base64.decodeBase64(publicKey);
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
.generatePublic(new X509EncodedKeySpec(keyBytes));
//该密钥能够加密的最大字节长度
int maxBitLength = pubKey.getModulus().bitLength() / 8 - 11;
// RSA加密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] data = str.getBytes(StandardCharsets.UTF_8);
byte[] encodeBytes = null;
for (int i = 0; i < data.length; i += maxBitLength) {
// 注意要使用2的倍数,否则会出现加密后的内容再解密时为乱码
byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i, i + maxBitLength));
encodeBytes = ArrayUtils.addAll(encodeBytes, doFinal);
}
return encodeBytes;
}
/**
* RSA私钥解密
* @param data
* @param privateKey
* @return
*/
@SneakyThrows
public static String decodeWithPrivateKey(byte[] data, String privateKey) {
// base64解码的私钥
byte[] decoded = Base64.decodeBase64(privateKey);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA")
.generatePrivate(new PKCS8EncodedKeySpec(decoded));
// 该密钥能够解密的最大字节长度
int maxBitLength = priKey.getModulus().bitLength() / 8;
// RSA解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.length; i += maxBitLength) {
byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i, i + maxBitLength));
sb.append(new String(doFinal, StandardCharsets.UTF_8));
}
return sb.toString();
}
/**
* RSA私钥加密
* @param str 加密字符串
* @param privateKey 私钥
*/
@SneakyThrows
public static byte[] encodeWithPrivateKey(String str, String privateKey) {
// base64编码的公钥
byte[] keyBytes = Base64.decodeBase64(privateKey);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA")
.generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
//该密钥能够加密的最大字节长度
int maxBitLength = priKey.getModulus().bitLength() / 8 - 11;
// RSA加密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, priKey);
byte[] data = str.getBytes(StandardCharsets.UTF_8);
byte[] encodeBytes = null;
for (int i = 0; i < data.length; i += maxBitLength) {
byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i, i + maxBitLength));
encodeBytes = ArrayUtils.addAll(encodeBytes, doFinal);
}
return encodeBytes;
}
@SneakyThrows
public static String decodeWithPublicKey(byte[] data, String publicKey){
// base64编码的私钥
byte[] decoded = Base64.decodeBase64(publicKey);
RSAPublicKey priKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
.generatePublic(new X509EncodedKeySpec(decoded));
// 该密钥能够解密的最大字节长度
int maxBitLength = priKey.getModulus().bitLength() / 8;
// RSA解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.length; i += maxBitLength) {
byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i, i + maxBitLength));
sb.append(new String(doFinal));
}
return sb.toString();
}
}