mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add CipherWrapper
This commit is contained in:
parent
6ed8588c83
commit
851a10d3b0
@ -19,6 +19,7 @@
|
||||
* 【core 】 增加DefaultCloneable(pr#459@Gitee)
|
||||
* 【core 】 CollStreamUtil增加是否并行的重载(pr#467@Gitee)
|
||||
* 【core 】 ResourceClassLoader增加缓存(pr#1959@Github)
|
||||
* 【crypto 】 增加CipherWrapper,增加setRandom(pr#1959@Github)
|
||||
*
|
||||
### 🐞Bug修复
|
||||
* 【core 】 修复FileResource构造fileName参数无效问题(issue#1942@Github)
|
||||
|
121
hutool-crypto/src/main/java/cn/hutool/crypto/CipherWrapper.java
Normal file
121
hutool-crypto/src/main/java/cn/hutool/crypto/CipherWrapper.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user