add test and change AES costructor

This commit is contained in:
Looly 2021-09-07 23:54:57 +08:00
parent c50a63a196
commit 4c237ba95e
6 changed files with 119 additions and 13 deletions

View File

@ -15,6 +15,7 @@
* 【crypto 】 SymmetricCrypto增加setMode方法update采用累加模式pr#1642@Github
* 【core 】 ZipReader支持Filter
* 【all 】 Sftp、Ftp、HttpDownloader增加download重载支持避免传输文件损坏pr#407@Gitee
* 【crypto 】 AES修改构造的IvParameterSpec为AlgorithmParameterSpecissue#1814@Gitee
### 🐞Bug修复
* 【core 】 修复ListUtil.split方法越界问题issue#I48Q0P@Gitee

View File

@ -125,6 +125,21 @@ public class RandomUtil {
return random;
}
/**
* 获取algorithms/providers中提供的强安全随机生成器<br>
* 注意此方法可能造成阻塞或性能问题
*
* @return {@link SecureRandom}
* @since 5.7.12
*/
public static SecureRandom getSecureRandomStrong() {
try {
return SecureRandom.getInstanceStrong();
} catch (NoSuchAlgorithmException e) {
throw new UtilException(e);
}
}
/**
* 获取随机数产生器
*

View File

@ -96,7 +96,7 @@ public class ReUtil {
}
/**
* 获得匹配的字符串获得正则中分组1的内容
* 获得匹配的字符串获得正则中分组1的内容
*
* @param pattern 编译后的正则模式
* @param content 被匹配的内容

View File

@ -8,6 +8,7 @@ import cn.hutool.crypto.Padding;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.security.spec.AlgorithmParameterSpec;
/**
* AES加密算法实现<br>
@ -121,14 +122,14 @@ public class AES extends SymmetricCrypto {
/**
* 构造
*
* @param mode 模式{@link Mode}
* @param padding {@link Padding}补码方式
* @param key 密钥支持三种密钥长度128192256位
* @param iv 偏移向量加盐
* @param mode 模式{@link Mode}
* @param padding {@link Padding}补码方式
* @param key 密钥支持三种密钥长度128192256位
* @param paramsSpec 算法参数例如加盐等
* @since 3.3.0
*/
public AES(Mode mode, Padding padding, SecretKey key, IvParameterSpec iv) {
this(mode.name(), padding.name(), key, iv);
public AES(Mode mode, Padding padding, SecretKey key, AlgorithmParameterSpec paramsSpec) {
this(mode.name(), padding.name(), key, paramsSpec);
}
/**
@ -180,13 +181,13 @@ public class AES extends SymmetricCrypto {
/**
* 构造
*
* @param mode 模式
* @param padding 补码方式
* @param key 密钥支持三种密钥长度128192256位
* @param iv 加盐
* @param mode 模式
* @param padding 补码方式
* @param key 密钥支持三种密钥长度128192256位
* @param paramsSpec 算法参数例如加盐等
*/
public AES(String mode, String padding, SecretKey key, IvParameterSpec iv) {
super(StrUtil.format("AES/{}/{}", mode, padding), key, iv);
public AES(String mode, String padding, SecretKey key, AlgorithmParameterSpec paramsSpec) {
super(StrUtil.format("AES/{}/{}", mode, padding), key, paramsSpec);
}
//------------------------------------------------------------------------- Constrctor end
}

View File

@ -7,10 +7,14 @@ import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.AES;
import org.bouncycastle.crypto.util.BasicAlphabetMapper;
import org.bouncycastle.jcajce.spec.FPEParameterSpec;
import org.junit.Assert;
import org.junit.Test;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
public class AESTest {
@ -112,4 +116,51 @@ public class AESTest {
final String decryptStr = aes.decryptStr(result1);
Assert.assertEquals(content, decryptStr);
}
/**
* https://github.com/dromara/hutool/issues/1814
*/
@Test
public void fpeTest() {
// 映射字符表规定了明文和密文的字符范围
BasicAlphabetMapper numberMapper = new BasicAlphabetMapper("0123456789");
// 初始化 aes 密钥
byte[] keyBytes = RandomUtil.randomBytes(16);
AES aes = new AES("FF1", "NoPadding",
new SecretKeySpec(keyBytes, "FF1"),
new FPEParameterSpec(numberMapper.getRadix(), new byte[]{}));
// 原始数据
String phone = "13534534567";
// 加密
byte[] inputDataByte = numberMapper.convertToIndexes(phone.toCharArray());
byte[] encrypt = aes.encrypt(inputDataByte);
// 通过 mapper 将密文输出处理为原始格式
char[] encryptChars = numberMapper.convertToChars(encrypt);
// 手机号码加密: 13534534567 -> 49725950626
Assert.assertEquals(phone.length(), encryptChars.length);
}
/**
* https://blog.csdn.net/weixin_42468911/article/details/114358682
*/
@Test
public void gcmTest() {
final SecretKey key = KeyUtil.generateKey("AES");
byte[] iv = RandomUtil.randomBytes(12);
AES aes = new AES("GCM", "NoPadding",
key,
new GCMParameterSpec(128, iv));
// 原始数据
String phone = "13534534567";
// 加密
byte[] encrypt = aes.encrypt(phone);
final String decryptStr = aes.decryptStr(encrypt);
Assert.assertEquals(phone, decryptStr);
}
}

View File

@ -0,0 +1,38 @@
package cn.hutool.crypto.test.symmetric;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import org.junit.Assert;
import org.junit.Test;
import javax.crypto.spec.IvParameterSpec;
/**
* https://stackoverflow.com/questions/32672241/using-bouncycastles-chacha-for-file-encryption
*/
public class ChaCha20Test {
@Test
public void encryptAndDecryptTest() {
String content = "test中文";
// 32 for 256 bit key or 16 for 128 bit
byte[] key = RandomUtil.randomBytes(32);
// 64 bit IV required by ChaCha20
byte[] iv = RandomUtil.randomBytes(12);
final SymmetricCrypto chacha = new SymmetricCrypto("ChaCha20",
KeyUtil.generateKey("ChaCha", key),
new IvParameterSpec(iv)
);
// 加密为16进制表示
String encryptHex = chacha.encryptHex(content);
// 解密为字符串
String decryptStr = chacha.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);
Assert.assertEquals(content, decryptStr);
}
}