新增 encrypt.defaultKey 参数,适用于 Aes、M3 加密的默认秘钥;新增 encrypt.storeBase64 参数,是否将 Hex 编码改为 Base64 编码存储

This commit is contained in:
thinkgem
2024-07-23 19:39:19 +08:00
parent 09b1505120
commit 89d785f04c
2 changed files with 135 additions and 122 deletions

View File

@@ -4,176 +4,175 @@
*/
package com.jeesite.common.codec;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import com.jeesite.common.io.PropertiesUtils;
import com.jeesite.common.lang.ExceptionUtils;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import com.jeesite.common.lang.ExceptionUtils;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
/**
* AES加密解密工具类
* AES 加密解密工具类
* @author ThinkGem
*/
public class AesUtils {
private static final String AES = "AES";
private static final String AES_CBC = "AES/CBC/PKCS5Padding";
private static final int DEFAULT_AES_KEYSIZE = 128; // 生成AES密钥, 默认长度为128位(16字节).
private static final int DEFAULT_IVSIZE = 16; // 生成随机向量, 默认大小为cipher.getBlockSize(), 16字节
private static final int DEFAULT_KEY_SIZE = 128; // 生成AES密钥, 默认长度为128位(16字节).
private static final int DEFAULT_IV_SIZE = 16; // 生成随机向量, 默认大小为cipher.getBlockSize(), 16字节
private static final SecureRandom RANDOM = new SecureRandom(); // 用于 生成 generateIV随机数对象
private static final byte[] DEFAULT_KEY = new byte[]{-97,88,-94,9,70,-76,126,25,0,3,-20,113,108,28,69,125};
private static final byte[] DEFAULT_KEY = EncodeUtils.decodeHex(PropertiesUtils.getInstance()
.getProperty("encrypt.defaultKey", "9f58a20946b47e190003ec716c1c457d"));
private static final boolean STORE_BASE64 = PropertiesUtils.getInstance()
.getPropertyToBoolean("encrypt.storeBase64", "false");
/**
* 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
*/
public static String genKeyString() {
return EncodeUtils.encodeHex(genKey(DEFAULT_AES_KEYSIZE));
}
/**
* 使用AES加密原始字符串.
*
* @param input 原始输入字符数组
*/
public static String encode(String input) {
try {
return EncodeUtils.encodeHex(encode(input.getBytes(EncodeUtils.UTF_8), DEFAULT_KEY));
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* 使用AES加密原始字符串.
*
* @param input 原始输入字符数组
* @param key 符合AES要求的密钥
*/
public static String encode(String input, String key) {
try {
return EncodeUtils.encodeHex(encode(input.getBytes(EncodeUtils.UTF_8), EncodeUtils.decodeHex(key)));
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* 使用AES解密字符串, 返回原始字符串.
*
* @param input Hex编码的加密字符串
*/
public static String decode(String input) {
try {
return new String(decode(EncodeUtils.decodeHex(input), DEFAULT_KEY), EncodeUtils.UTF_8);
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* 使用AES解密字符串, 返回原始字符串.
*
* @param input Hex编码的加密字符串
* @param key 符合AES要求的密钥
*/
public static String decode(String input, String key) {
try {
return new String(decode(EncodeUtils.decodeHex(input), EncodeUtils.decodeHex(key)), EncodeUtils.UTF_8);
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
* 生成 AES 密钥,返回字节数组, 默认长度为128位(16字节)
*/
public static byte[] genKey() {
return genKey(DEFAULT_AES_KEYSIZE);
return genKey(DEFAULT_KEY_SIZE);
}
/**
* 生成AES密钥,可选长度为128,192,256位.
* 生成 AES 密钥, 返回字节数组, 默认长度为128位(16字节)
*/
public static byte[] genKey(int keysize) {
public static String genKeyString() {
return EncodeUtils.encodeHex(genKey());
}
/**
* 生成 AES 密钥, 可选长度为128,192,256位
*/
public static byte[] genKey(int keySize) {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
keyGenerator.init(keysize);
keyGenerator.init(keySize);
SecretKey secretKey = keyGenerator.generateKey();
return secretKey.getEncoded();
} catch (GeneralSecurityException e) {
throw ExceptionUtils.unchecked(e);
}
}
/**
* 生成随机向量,默认大小为cipher.getBlockSize(), 16字节.
* 生成随机向量, 默认大小为cipher.getBlockSize(), 16字节
*/
public static byte[] genIV() {
byte[] bytes = new byte[DEFAULT_IVSIZE];
byte[] bytes = new byte[DEFAULT_IV_SIZE];
RANDOM.nextBytes(bytes);
return bytes;
}
/**
* 使用 AES 加密原始字符串
* @param input 原始输入字符串
* @author ThinkGem
*/
public static String encode(String input) {
if (STORE_BASE64) {
return EncodeUtils.encodeBase64(encode(input.getBytes(StandardCharsets.UTF_8), DEFAULT_KEY));
}
return EncodeUtils.encodeHex(encode(input.getBytes(StandardCharsets.UTF_8), DEFAULT_KEY));
}
/**
* 使用AES加密原始字符串.
*
* 使用 AES 加密原始字符串
* @param input 原始输入字符数组
* @param key 符合AES要求的密钥
* @param key 符合要求的密钥
* @author ThinkGem
*/
public static byte[] encode(byte[] input, byte[] key) {
return aes(input, key, Cipher.ENCRYPT_MODE);
}
/**
* 使用AES加密原始字符串.
*
* 使用 AES 加密原始字符串
* @param input 原始输入字符串
* @param key 符合要求的密钥
* @author ThinkGem
*/
public static String encode(String input, String key) {
if (STORE_BASE64) {
return EncodeUtils.encodeBase64(encode(input.getBytes(StandardCharsets.UTF_8), EncodeUtils.decodeHex(key)));
}
return EncodeUtils.encodeHex(encode(input.getBytes(StandardCharsets.UTF_8), EncodeUtils.decodeHex(key)));
}
/**
* 使用 AES 加密原始字符串
* @param input 原始输入字符数组
* @param key 符合AES要求的密钥
* @param key 符合要求的密钥
* @param iv 初始向量
* @author ThinkGem
*/
public static byte[] encode(byte[] input, byte[] key, byte[] iv) {
return aes(input, key, iv, Cipher.ENCRYPT_MODE);
}
/**
* 使用 AES 解密数据, 返回原始字符串
* @param input Hex 或 Base64 编码的加密字符串
* @author ThinkGem
*/
public static String decode(String input) {
if (STORE_BASE64) {
return new String(decode(EncodeUtils.decodeBase64(input), DEFAULT_KEY), StandardCharsets.UTF_8);
}
return new String(decode(EncodeUtils.decodeHex(input), DEFAULT_KEY), StandardCharsets.UTF_8);
}
/**
* 使用AES解密字符串, 返回原始字符串.
*
* @param input Hex编码的加密字符串
* @param key 符合AES要求的密钥
* 使用 AES 解密数据, 返回原始字符串
* @param input 加密输入字符数组
* @param key 符合要求的密钥
* @author ThinkGem
*/
public static byte[] decode(byte[] input, byte[] key) {
return aes(input, key, Cipher.DECRYPT_MODE);
}
/**
* 使用AES解密字符串, 返回原始字符串.
*
* 使用 AES 解密数据, 返回原始字符串
* @param input Hex 或 Base64 编码的加密字符串
* @param key 符合要求的密钥
* @author ThinkGem
*/
public static String decode(String input, String key) {
if (STORE_BASE64) {
return new String(decode(EncodeUtils.decodeBase64(input), EncodeUtils.decodeHex(key)), StandardCharsets.UTF_8);
}
return new String(decode(EncodeUtils.decodeHex(input), EncodeUtils.decodeHex(key)), StandardCharsets.UTF_8);
}
/**
* 使用 AES 解密数据, 返回原始字符串
* @param input Hex编码的加密字符串
* @param key 符合AES要求的密钥
* @param iv 初始向量
* @author ThinkGem
*/
public static byte[] decode(byte[] input, byte[] key, byte[] iv) {
return aes(input, key, iv, Cipher.DECRYPT_MODE);
}
/**
* 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
*
* 使用 AES 加密或解密无编码的原始字节数组, 返回无编码的字节数组结果
* @param input 原始字节数组
* @param key 符合AES要求的密钥
* @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
* @author ThinkGem
*/
private static byte[] aes(byte[] input, byte[] key, int mode) {
try {
SecretKey secretKey = new SecretKeySpec(key, AES);
Cipher cipher = Cipher.getInstance(AES);
SecretKey secretKey = new SecretKeySpec(key, AES);
cipher.init(mode, secretKey);
return cipher.doFinal(input);
} catch (GeneralSecurityException e) {
@@ -182,18 +181,18 @@ public class AesUtils {
}
/**
* 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
*
* 使用 AES 加密或解密无编码的原始字节数组, 返回无编码的字节数组结果
* @param input 原始字节数组
* @param key 符合AES要求的密钥
* @param iv 初始向量
* @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
* @author ThinkGem
*/
private static byte[] aes(byte[] input, byte[] key, byte[] iv, int mode) {
try {
Cipher cipher = Cipher.getInstance(AES_CBC);
SecretKey secretKey = new SecretKeySpec(key, AES);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance(AES_CBC);
cipher.init(mode, secretKey, ivSpec);
return cipher.doFinal(input);
} catch (GeneralSecurityException e) {
@@ -201,18 +200,4 @@ public class AesUtils {
}
}
// public static void main(String[] args) {
//
// String s = "hello word!";
// System.out.println(s);
//
// String k = genKeyString();
// System.out.println(k);
// String ss = encode(s, k);
// System.out.println(ss);
// String sss = decode(ss, k);
// System.out.println(sss);
//
// }
}

View File

@@ -6,17 +6,16 @@ package com.jeesite.common.codec;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
/**
* SHA-1不可逆加密工具类
* SHA-1 加密工具类,散列加密,不可逆加密
* @author ThinkGem
*/
public class Sha1Utils {
private static final String SHA1 = "SHA-1";
/**
* 生成随机的Byte[]作为salt密钥.
* 生成随机的 Byte[] 作为 salt 密钥.
* @param numBytes byte数组的大小
*/
public static byte[] genSalt(int numBytes) {
@@ -24,31 +23,60 @@ public class Sha1Utils {
}
/**
* 对输入字符串进行sha1散列.
* 生成随机的 Byte[] 作为 salt 密钥,返回 HEX 值
* @param numBytes byte 数组的大小
*/
public static String genSaltString(int numBytes) {
return DigestUtils.genSaltString(numBytes);
}
/**
* 对输入字符串进行 SHA-1 散列.
*/
public static byte[] sha1(byte[] input) {
return DigestUtils.digest(input, SHA1, null, 1);
return DigestUtils.digest(input, DigestUtils.SHA1, null, 1);
}
/**
* 对输入字符串进行sha1散列.
* 对输入字符串进行 SHA-1 散列.
*/
public static String sha1(String input) {
return EncodeUtils.encodeHex(sha1(input.getBytes(StandardCharsets.UTF_8)));
}
/**
* 对输入字符串进行 SHA-1 散列.
*/
public static byte[] sha1(byte[] input, byte[] salt) {
return DigestUtils.digest(input, SHA1, salt, 1);
return DigestUtils.digest(input, DigestUtils.SHA1, salt, 1);
}
/**
* 对输入字符串进行sha1散列.
* 对输入字符串进行 SHA-1 散列.
*/
public static String sha1(String data, String salt) {
return EncodeUtils.encodeHex(sha1(data.getBytes(StandardCharsets.UTF_8), EncodeUtils.decodeHex(salt)));
}
/**
* 对输入字符串进行 SHA-1 散列.
*/
public static byte[] sha1(byte[] input, byte[] salt, int iterations) {
return DigestUtils.digest(input, SHA1, salt, iterations);
return DigestUtils.digest(input, DigestUtils.SHA1, salt, iterations);
}
/**
* 对文件进行sha1散列.
* 对输入字符串进行 SHA-1 散列.
*/
public static String sha1(String input, String salt, int iterations) {
return EncodeUtils.encodeHex(sha1(input.getBytes(StandardCharsets.UTF_8), EncodeUtils.decodeHex(salt), iterations));
}
/**
* 对文件进行 SHA-1 散列.
*/
public static byte[] sha1(InputStream input) throws IOException {
return DigestUtils.digest(input, SHA1);
return DigestUtils.digest(input, DigestUtils.SHA1);
}
}