Merge branch 'v5-dev' of gitee.com:dromara/hutool into v5-dev

This commit is contained in:
looly 2021-11-20 16:38:57 +08:00
commit 60a8fd48f5
9 changed files with 453 additions and 76 deletions

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------------------------------------------------
# 5.7.17 (2021-11-16)
# 5.7.17 (2021-11-19)
### 🐣新特性
* 【core 】 增加AsyncUtilpr#457@Gitee
@ -17,9 +17,13 @@
* 【core 】 改进TextFinder支持限制结束位置及反向查找模式
* 【core 】 Opt增加部分方法pr#459@Gitee
* 【core 】 增加DefaultCloneablepr#459@Gitee
* 【core 】 CollStreamUtil增加是否并行的重载pr#467@Gitee
* 【core 】 ResourceClassLoader增加缓存pr#1959@Github
* 【crypto 】 增加CipherWrapper增加setRandomissue#1958@Github
*
### 🐞Bug修复
* 【core 】 修复FileResource构造fileName参数无效问题issue#1942@Github
* 【cache 】 修复WeakCache键值强关联导致的无法回收问题issue#1953@Github
-------------------------------------------------------------------------------------------------------------

View File

@ -17,11 +17,11 @@ public class CacheObj<K, V> implements Serializable{
protected final V obj;
/** 上次访问时间 */
private volatile long lastAccess;
protected volatile long lastAccess;
/** 访问次数 */
protected AtomicLong accessCount = new AtomicLong();
/** 对象存活时长0表示永久存活*/
private final long ttl;
protected final long ttl;
/**
* 构造

View File

@ -1,5 +1,10 @@
package cn.hutool.cache.impl;
import cn.hutool.cache.Cache;
import cn.hutool.core.lang.func.Func0;
import cn.hutool.core.lang.mutable.MutableObj;
import java.util.Iterator;
import java.util.WeakHashMap;
/**
@ -7,18 +12,112 @@ import java.util.WeakHashMap;
* 对于一个给定的键其映射的存在并不阻止垃圾回收器对该键的丢弃这就使该键成为可终止的被终止然后被回收<br>
* 丢弃某个键时其条目从映射中有效地移除<br>
*
* @param <K> 键类型
* @param <V> 值类型
* @author Looly
*
* @param <K>
* @param <V>
* @author looly
* @since 3.0.7
*/
public class WeakCache<K, V> extends TimedCache<K, V>{
public class WeakCache<K, V> implements Cache<K, V> {
private static final long serialVersionUID = 1L;
TimedCache<MutableObj<K>, V> timedCache;
/**
* 构造
*
* @param timeout 超时
*/
public WeakCache(long timeout) {
super(timeout, new WeakHashMap<>());
this.timedCache = new TimedCache<>(timeout, new WeakHashMap<>());
}
@Override
public int capacity() {
return timedCache.capacity();
}
@Override
public long timeout() {
return timedCache.timeout();
}
@Override
public void put(K key, V object) {
timedCache.put(new MutableObj<>(key), object);
}
@Override
public void put(K key, V object, long timeout) {
timedCache.put(new MutableObj<>(key), object, timeout);
}
@Override
public V get(K key, boolean isUpdateLastAccess, Func0<V> supplier) {
return timedCache.get(new MutableObj<>(key), isUpdateLastAccess, supplier);
}
@Override
public V get(K key, boolean isUpdateLastAccess) {
return timedCache.get(new MutableObj<>(key), isUpdateLastAccess);
}
@Override
public Iterator<CacheObj<K, V>> cacheObjIterator() {
final Iterator<CacheObj<MutableObj<K>, V>> timedIter = timedCache.cacheObjIterator();
return new Iterator<CacheObj<K, V>>() {
@Override
public boolean hasNext() {
return timedIter.hasNext();
}
@Override
public CacheObj<K, V> next() {
final CacheObj<MutableObj<K>, V> next = timedIter.next();
final CacheObj<K, V> nextNew = new CacheObj<>(next.key.get(), next.obj, next.ttl);
nextNew.lastAccess = next.lastAccess;
nextNew.accessCount = next.accessCount;
return nextNew;
}
};
}
@Override
public int prune() {
return timedCache.prune();
}
@Override
public boolean isFull() {
return timedCache.isFull();
}
@Override
public void remove(K key) {
timedCache.remove(new MutableObj<>(key));
}
@Override
public void clear() {
timedCache.clear();
}
@Override
public int size() {
return timedCache.size();
}
@Override
public boolean isEmpty() {
return timedCache.isEmpty();
}
@Override
public boolean containsKey(K key) {
return timedCache.containsKey(new MutableObj<>(key));
}
@Override
public Iterator<V> iterator() {
return timedCache.iterator();
}
}

View File

@ -0,0 +1,21 @@
package cn.hutool.cache;
import cn.hutool.cache.impl.WeakCache;
import org.junit.Assert;
import org.junit.Test;
public class WeakCacheTest {
@Test
public void removeTest(){
final WeakCache<String, String> cache = new WeakCache<>(-1);
cache.put("abc", "123");
cache.put("def", "456");
Assert.assertEquals(2, cache.size());
cache.remove("abc");
Assert.assertEquals(1, cache.size());
}
}

View File

@ -2,6 +2,7 @@ package cn.hutool.core.collection;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.stream.StreamUtil;
import java.util.*;
import java.util.function.BiFunction;
@ -27,10 +28,27 @@ public class CollStreamUtil {
* @return 转化后的map
*/
public static <V, K> Map<K, V> toIdentityMap(Collection<V> collection, Function<V, K> key) {
return toIdentityMap(collection, key, false);
}
/**
* 将collection转化为类型不变的map<br>
* <B>{@code Collection<V> ----> Map<K,V>}</B>
*
* @param collection 需要转化的集合
* @param key V类型转化为K类型的lambda方法
* @param isParallel 是否并行流
* @param <V> collection中的泛型
* @param <K> map中的key类型
* @return 转化后的map
*/
public static <V, K> Map<K, V> toIdentityMap(Collection<V> collection, Function<V, K> key, boolean isParallel) {
if (CollUtil.isEmpty(collection)) {
return Collections.emptyMap();
}
return collection.stream().collect(Collectors.toMap(key, Function.identity(), (l, r) -> l));
return StreamUtil.of(collection, isParallel)
.collect(Collectors.toMap(key, Function.identity(), (l, r) -> l));
}
/**
@ -46,12 +64,27 @@ public class CollStreamUtil {
* @return 转化后的map
*/
public static <E, K, V> Map<K, V> toMap(Collection<E> collection, Function<E, K> key, Function<E, V> value) {
return toMap(collection, key, value, false);
}
/**
* @param collection 需要转化的集合
* @param key E类型转化为K类型的lambda方法
* @param value E类型转化为V类型的lambda方法
* @param isParallel 是否并行流
* @param <E> collection中的泛型
* @param <K> map中的key类型
* @param <V> map中的value类型
* @return 转化后的map
*/
public static <E, K, V> Map<K, V> toMap(Collection<E> collection, Function<E, K> key, Function<E, V> value, boolean isParallel) {
if (CollUtil.isEmpty(collection)) {
return Collections.emptyMap();
}
return collection.stream().collect(Collectors.toMap(key, value, (l, r) -> l));
return StreamUtil.of(collection, isParallel).collect(Collectors.toMap(key, value, (l, r) -> l));
}
/**
* 将collection按照规则(比如有相同的班级id)分类成map<br>
* <B>{@code Collection<E> -------> Map<K,List<E>> } </B>
@ -63,12 +96,25 @@ public class CollStreamUtil {
* @return 分类后的map
*/
public static <E, K> Map<K, List<E>> groupByKey(Collection<E> collection, Function<E, K> key) {
return groupByKey(collection, key, false);
}
/**
* 将collection按照规则(比如有相同的班级id)分类成map<br>
* <B>{@code Collection<E> -------> Map<K,List<E>> } </B>
*
* @param collection 需要分类的集合
* @param key 分类的规则
* @param isParallel 是否并行流
* @param <E> collection中的泛型
* @param <K> map中的key类型
* @return 分类后的map
*/
public static <E, K> Map<K, List<E>> groupByKey(Collection<E> collection, Function<E, K> key, boolean isParallel) {
if (CollUtil.isEmpty(collection)) {
return Collections.emptyMap();
}
return collection
.stream()
.collect(Collectors.groupingBy(key, Collectors.toList()));
return StreamUtil.of(collection, isParallel).collect(Collectors.groupingBy(key, Collectors.toList()));
}
/**
@ -84,11 +130,29 @@ public class CollStreamUtil {
* @return 分类后的map
*/
public static <E, K, U> Map<K, Map<U, List<E>>> groupBy2Key(Collection<E> collection, Function<E, K> key1, Function<E, U> key2) {
return groupBy2Key(collection, key1, key2, false);
}
/**
* 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map<br>
* <B>{@code Collection<E> ---> Map<T,Map<U,List<E>>> } </B>
*
* @param collection 需要分类的集合
* @param key1 第一个分类的规则
* @param key2 第二个分类的规则
* @param isParallel 是否并行流
* @param <E> 集合元素类型
* @param <K> 第一个map中的key类型
* @param <U> 第二个map中的key类型
* @return 分类后的map
*/
public static <E, K, U> Map<K, Map<U, List<E>>> groupBy2Key(Collection<E> collection, Function<E, K> key1,
Function<E, U> key2, boolean isParallel) {
if (CollUtil.isEmpty(collection)) {
return Collections.emptyMap();
}
return collection
.stream()
return StreamUtil.of(collection, isParallel)
.collect(Collectors.groupingBy(key1, Collectors.groupingBy(key2, Collectors.toList())));
}
@ -105,11 +169,28 @@ public class CollStreamUtil {
* @return 分类后的map
*/
public static <E, T, U> Map<T, Map<U, E>> group2Map(Collection<E> collection, Function<E, T> key1, Function<E, U> key2) {
return group2Map(collection, key1, key2, false);
}
/**
* 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map<br>
* <B>{@code Collection<E> ---> Map<T,Map<U,E>> } </B>
*
* @param collection 需要分类的集合
* @param key1 第一个分类的规则
* @param key2 第二个分类的规则
* @param isParallel 是否并行流
* @param <T> 第一个map中的key类型
* @param <U> 第二个map中的key类型
* @param <E> collection中的泛型
* @return 分类后的map
*/
public static <E, T, U> Map<T, Map<U, E>> group2Map(Collection<E> collection,
Function<E, T> key1, Function<E, U> key2, boolean isParallel) {
if (CollUtil.isEmpty(collection) || key1 == null || key2 == null) {
return Collections.emptyMap();
}
return collection
.stream()
return StreamUtil.of(collection, isParallel)
.collect(Collectors.groupingBy(key1, Collectors.toMap(key2, Function.identity(), (l, r) -> l)));
}
@ -124,11 +205,25 @@ public class CollStreamUtil {
* @return 转化后的list
*/
public static <E, T> List<T> toList(Collection<E> collection, Function<E, T> function) {
return toList(collection, function, false);
}
/**
* 将collection转化为List集合但是两者的泛型不同<br>
* <B>{@code Collection<E> ------> List<T> } </B>
*
* @param collection 需要转化的集合
* @param function collection中的泛型转化为list泛型的lambda表达式
* @param isParallel 是否并行流
* @param <E> collection中的泛型
* @param <T> List中的泛型
* @return 转化后的list
*/
public static <E, T> List<T> toList(Collection<E> collection, Function<E, T> function, boolean isParallel) {
if (CollUtil.isEmpty(collection)) {
return Collections.emptyList();
}
return collection
.stream()
return StreamUtil.of(collection, isParallel)
.map(function)
.filter(Objects::nonNull)
.collect(Collectors.toList());
@ -145,11 +240,25 @@ public class CollStreamUtil {
* @return 转化后的Set
*/
public static <E, T> Set<T> toSet(Collection<E> collection, Function<E, T> function) {
if (CollUtil.isEmpty(collection) || function == null) {
return toSet(collection, function, false);
}
/**
* 将collection转化为Set集合但是两者的泛型不同<br>
* <B>{@code Collection<E> ------> Set<T> } </B>
*
* @param collection 需要转化的集合
* @param function collection中的泛型转化为set泛型的lambda表达式
* @param isParallel 是否并行流
* @param <E> collection中的泛型
* @param <T> Set中的泛型
* @return 转化后的Set
*/
public static <E, T> Set<T> toSet(Collection<E> collection, Function<E, T> function, boolean isParallel) {
if (CollUtil.isEmpty(collection)) {
return Collections.emptySet();
}
return collection
.stream()
return StreamUtil.of(collection, isParallel)
.map(function)
.filter(Objects::nonNull)
.collect(Collectors.toSet());

View File

@ -12,12 +12,16 @@ import java.util.Map;
* 资源类加载器可以加载任意类型的资源类
*
* @param <T> {@link Resource}接口实现类
* @author looly
* @author looly, lzpeng
* @since 5.5.2
*/
public class ResourceClassLoader<T extends Resource> extends SecureClassLoader {
private final Map<String, T> resourceMap;
/**
* 缓存已经加载的类
*/
private final Map<String, Class<?>> cacheClassMap;
/**
* 构造
@ -28,25 +32,42 @@ public class ResourceClassLoader<T extends Resource> extends SecureClassLoader {
public ResourceClassLoader(ClassLoader parentClassLoader, Map<String, T> resourceMap) {
super(ObjectUtil.defaultIfNull(parentClassLoader, ClassLoaderUtil.getClassLoader()));
this.resourceMap = ObjectUtil.defaultIfNull(resourceMap, new HashMap<>());
this.cacheClassMap = new HashMap<>();
}
/**
* 增加需要加载的类资源
*
* @param resource 资源可以是文件流或者字符串
* @return this
*/
public ResourceClassLoader<T> addResource(T resource){
public ResourceClassLoader<T> addResource(T resource) {
this.resourceMap.put(resource.getName(), resource);
return this;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
final Class<?> clazz = cacheClassMap.computeIfAbsent(name, this::defineByName);
if (clazz == null) {
return super.findClass(name);
}
return clazz;
}
/**
* 从给定资源中读取class的二进制流然后生成类<br>
* 如果这个类资源不存在返回{@code null}
*
* @param name 类名
* @return 定义的类
*/
private Class<?> defineByName(String name) {
final Resource resource = resourceMap.get(name);
if (null != resource) {
final byte[] bytes = resource.readBytes();
return defineClass(name, bytes, 0, bytes.length);
}
return super.findClass(name);
return null;
}
}

View File

@ -0,0 +1,121 @@
package cn.hutool.crypto;
import javax.crypto.Cipher;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
/**
* {@link Cipher}包装类提供初始化模式等额外方法<br>
* 包装之后可提供自定义或默认的
* <ul>
* <li>{@link AlgorithmParameterSpec}</li>
* <li>{@link SecureRandom}</li>
* </ul>
*
* @author looly
* @since 5.7.17
*/
public class CipherWrapper {
private final Cipher cipher;
/**
* 算法参数
*/
private AlgorithmParameterSpec params;
/**
* 随机数生成器可自定义随机数种子
*/
private SecureRandom random;
/**
* 构造
*
* @param algorithm 算法名称
*/
public CipherWrapper(String algorithm) {
this(SecureUtil.createCipher(algorithm));
}
/**
* 构造
*
* @param cipher {@link Cipher}
*/
public CipherWrapper(Cipher cipher) {
this.cipher = cipher;
}
/**
* 获取{@link AlgorithmParameterSpec}<br>
* 在某些算法中需要特别的参数例如在ECIES中此处为IESParameterSpec
*
* @return {@link AlgorithmParameterSpec}
*/
public AlgorithmParameterSpec getParams() {
return this.params;
}
/**
* 设置 {@link AlgorithmParameterSpec}通常用于加盐或偏移向量
*
* @param params {@link AlgorithmParameterSpec}
* @return this
*/
public CipherWrapper setParams(AlgorithmParameterSpec params) {
this.params = params;
return this;
}
/**
* 设置随机数生成器可自定义随机数种子
*
* @param random 随机数生成器可自定义随机数种子
* @return this
*/
public CipherWrapper setRandom(SecureRandom random) {
this.random = random;
return this;
}
/**
* 获取被包装的{@link Cipher}
*
* @return {@link Cipher}
*/
public Cipher getCipher() {
return this.cipher;
}
/**
* 初始化{@link Cipher}为加密或者解密模式
*
* @param mode 模式{@link Cipher#ENCRYPT_MODE} {@link Cipher#DECRYPT_MODE}
* @param key 密钥
* @return this
* @throws InvalidKeyException 无效key
* @throws InvalidAlgorithmParameterException 无效算法
*/
public CipherWrapper initMode(int mode, Key key)
throws InvalidKeyException, InvalidAlgorithmParameterException {
final Cipher cipher = this.cipher;
final AlgorithmParameterSpec params = this.params;
final SecureRandom random = this.random;
if (null != params) {
if (null != random) {
cipher.init(mode, key, params, random);
} else {
cipher.init(mode, key, params);
}
} else {
if (null != random) {
cipher.init(mode, key, random);
} else {
cipher.init(mode, key);
}
}
return this;
}
}

View File

@ -2,6 +2,7 @@ package cn.hutool.crypto.asymmetric;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FastByteArrayOutputStream;
import cn.hutool.crypto.CipherWrapper;
import cn.hutool.crypto.CryptoException;
import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.SecureUtil;
@ -16,6 +17,7 @@ import java.security.InvalidKeyException;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
/**
@ -37,7 +39,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
/**
* Cipher负责完成加密或解密工作
*/
protected Cipher cipher;
protected CipherWrapper cipherWrapper;
/**
* 加密的块大小
@ -47,12 +49,6 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
* 解密的块大小
*/
protected int decryptBlockSize = -1;
/**
* 算法参数
*/
private AlgorithmParameterSpec algorithmParameterSpec;
// ------------------------------------------------------------------ Constructor start
/**
@ -201,7 +197,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
* @since 5.4.3
*/
public AlgorithmParameterSpec getAlgorithmParameterSpec() {
return algorithmParameterSpec;
return this.cipherWrapper.getParams();
}
/**
@ -212,7 +208,19 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
* @since 5.4.3
*/
public void setAlgorithmParameterSpec(AlgorithmParameterSpec algorithmParameterSpec) {
this.algorithmParameterSpec = algorithmParameterSpec;
this.cipherWrapper.setParams(algorithmParameterSpec);
}
/**
* 设置随机数生成器可自定义随机数种子
*
* @param random 随机数生成器可自定义随机数种子
* @return this
* @since 5.7.17
*/
public AsymmetricCrypto setRandom(SecureRandom random) {
this.cipherWrapper.setRandom(random);
return this;
}
@Override
@ -229,11 +237,11 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
final Key key = getKeyByType(keyType);
lock.lock();
try {
initMode(Cipher.ENCRYPT_MODE, key);
final Cipher cipher = initMode(Cipher.ENCRYPT_MODE, key);
if (this.encryptBlockSize < 0) {
// 在引入BC库情况下自动获取块大小
final int blockSize = this.cipher.getBlockSize();
final int blockSize = cipher.getBlockSize();
if (blockSize > 0) {
this.encryptBlockSize = blockSize;
}
@ -254,11 +262,11 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
final Key key = getKeyByType(keyType);
lock.lock();
try {
initMode(Cipher.DECRYPT_MODE, key);
final Cipher cipher = initMode(Cipher.DECRYPT_MODE, key);
if (this.decryptBlockSize < 0) {
// 在引入BC库情况下自动获取块大小
final int blockSize = this.cipher.getBlockSize();
final int blockSize = cipher.getBlockSize();
if (blockSize > 0) {
this.decryptBlockSize = blockSize;
}
@ -281,7 +289,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
* @since 5.4.3
*/
public Cipher getCipher() {
return cipher;
return this.cipherWrapper.getCipher();
}
/**
@ -290,7 +298,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
* @since 4.5.2
*/
protected void initCipher() {
this.cipher = SecureUtil.createCipher(algorithm);
this.cipherWrapper = new CipherWrapper(this.algorithm);
}
/**
@ -309,7 +317,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
// 不足分段
if (dataLength <= maxBlockSize) {
return this.cipher.doFinal(data, 0, dataLength);
return getCipher().doFinal(data, 0, dataLength);
}
// 分段解密
@ -337,7 +345,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
// 对数据分段处理
while (remainLength > 0) {
blockSize = Math.min(remainLength, maxBlockSize);
out.write(cipher.doFinal(data, offSet, blockSize));
out.write(getCipher().doFinal(data, offSet, blockSize));
offSet += blockSize;
remainLength = dataLength - offSet;
@ -351,14 +359,11 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
*
* @param mode 模式可选{@link Cipher#ENCRYPT_MODE}或者{@link Cipher#DECRYPT_MODE}
* @param key 密钥
* @return {@link Cipher}
* @throws InvalidAlgorithmParameterException 异常算法错误
* @throws InvalidKeyException 异常KEY错误
*/
private void initMode(int mode, Key key) throws InvalidAlgorithmParameterException, InvalidKeyException {
if (null != this.algorithmParameterSpec) {
cipher.init(mode, key, this.algorithmParameterSpec);
} else {
cipher.init(mode, key);
}
private Cipher initMode(int mode, Key key) throws InvalidAlgorithmParameterException, InvalidKeyException {
return this.cipherWrapper.initMode(mode, key).getCipher();
}
}

View File

@ -3,15 +3,16 @@ package cn.hutool.crypto.symmetric;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.CipherMode;
import cn.hutool.crypto.CipherWrapper;
import cn.hutool.crypto.CryptoException;
import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.SecureUtil;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
@ -25,6 +26,7 @@ import java.io.OutputStream;
import java.io.Serializable;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@ -40,18 +42,11 @@ import java.util.concurrent.locks.ReentrantLock;
public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor, Serializable {
private static final long serialVersionUID = 1L;
private CipherWrapper cipherWrapper;
/**
* SecretKey 负责保存对称密钥
*/
private SecretKey secretKey;
/**
* Cipher负责完成加密或解密工作
*/
private Cipher cipher;
/**
* 加密解密参数
*/
private AlgorithmParameterSpec params;
/**
* 是否0填充
*/
@ -152,7 +147,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
this.isZeroPadding = true;
}
this.cipher = SecureUtil.createCipher(algorithm);
this.cipherWrapper = new CipherWrapper(algorithm);
return this;
}
@ -171,7 +166,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
* @return 加密或解密
*/
public Cipher getCipher() {
return cipher;
return cipherWrapper.getCipher();
}
/**
@ -181,7 +176,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
* @return 自身
*/
public SymmetricCrypto setParams(AlgorithmParameterSpec params) {
this.params = params;
this.cipherWrapper.setParams(params);
return this;
}
@ -192,8 +187,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
* @return 自身
*/
public SymmetricCrypto setIv(IvParameterSpec iv) {
setParams(iv);
return this;
return setParams(iv);
}
/**
@ -203,7 +197,18 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
* @return 自身
*/
public SymmetricCrypto setIv(byte[] iv) {
setIv(new IvParameterSpec(iv));
return setIv(new IvParameterSpec(iv));
}
/**
* 设置随机数生成器可自定义随机数种子
*
* @param random 随机数生成器可自定义随机数种子
* @return this
* @since 5.7.17
*/
public SymmetricCrypto setRandom(SecureRandom random){
this.cipherWrapper.setRandom(random);
return this;
}
@ -237,6 +242,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
* @since 5.6.8
*/
public byte[] update(byte[] data) {
final Cipher cipher = cipherWrapper.getCipher();
lock.lock();
try {
return cipher.update(paddingDataWithZero(data, cipher.getBlockSize()));
@ -376,11 +382,8 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
*/
private SymmetricCrypto initParams(String algorithm, AlgorithmParameterSpec paramsSpec) {
if (null == paramsSpec) {
byte[] iv = null;
final Cipher cipher = this.cipher;
if (null != cipher) {
iv = cipher.getIV();
}
byte[] iv = Opt.ofNullable(cipherWrapper)
.map(CipherWrapper::getCipher).map(Cipher::getIV).get();
// 随机IV
if (StrUtil.startWithIgnoreCase(algorithm, "PBE")) {
@ -409,13 +412,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
* @throws InvalidAlgorithmParameterException 无效算法
*/
private Cipher initMode(int mode) throws InvalidKeyException, InvalidAlgorithmParameterException {
final Cipher cipher = this.cipher;
if (null == this.params) {
cipher.init(mode, secretKey);
} else {
cipher.init(mode, secretKey, params);
}
return cipher;
return this.cipherWrapper.initMode(mode, this.secretKey).getCipher();
}
/**