diff --git a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/Cipher.java b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/Cipher.java
new file mode 100644
index 000000000..a88795ac8
--- /dev/null
+++ b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/Cipher.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2024. looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * https://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.crypto;
+
+/**
+ * 密码接口,提供统一的API,用于兼容和统一JCE和BouncyCastle等库的操作
+ *
+ * @author Looly
+ * @since 6.0.0
+ */
+public interface Cipher {
+
+ /**
+ * 获取算法名称
+ *
+ * @return 算法名称
+ */
+ String getAlgorithmName();
+
+ /**
+ * 获取块大小,当为Stream方式加密时返回0
+ *
+ * @return 块大小
+ */
+ int getBlockSize();
+
+ /**
+ * 初始化模式和参数
+ *
+ * @param mode 模式,如加密模式或解密模式
+ * @param parameters Cipher所需参数,包括Key、Random、IV等信息
+ */
+ void init(CipherMode mode, Parameters parameters);
+
+ /**
+ * 执行运算,可以是加密运算或解密运算
+ *
+ * @param data 被处理的数据
+ * @return 运算结果
+ */
+ byte[] process(byte[] data);
+
+ /**
+ * Cipher所需参数,包括Key、Random、IV等信息
+ */
+ interface Parameters { }
+}
diff --git a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/CipherWrapper.java b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/CipherWrapper.java
deleted file mode 100644
index 7a4077932..000000000
--- a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/CipherWrapper.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2023 looly(loolly@aliyun.com)
- * Hutool is licensed under Mulan PSL v2.
- * You can use this software according to the terms and conditions of the Mulan PSL v2.
- * You may obtain a copy of Mulan PSL v2 at:
- * https://license.coscl.org.cn/MulanPSL2
- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
- * See the Mulan PSL v2 for more details.
- */
-
-package org.dromara.hutool.crypto;
-
-import org.dromara.hutool.core.lang.wrapper.Wrapper;
-
-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}包装类,提供初始化模式等额外方法
- * 包装之后可提供自定义或默认的:
- *
- * - {@link AlgorithmParameterSpec}
- * - {@link SecureRandom}
- *
- *
- * @author looly
- * @since 5.7.17
- */
-public class CipherWrapper implements Wrapper {
-
- private final Cipher cipher;
- /**
- * 算法参数
- */
- private AlgorithmParameterSpec params;
- /**
- * 随机数生成器,可自定义随机数种子
- */
- private SecureRandom random;
-
- /**
- * 构造
- *
- * @param algorithm 算法名称
- */
- public CipherWrapper(final String algorithm) {
- this(SecureUtil.createCipher(algorithm));
- }
-
- /**
- * 构造
- *
- * @param cipher {@link Cipher}
- */
- public CipherWrapper(final Cipher cipher) {
- this.cipher = cipher;
- }
-
- /**
- * 获取{@link AlgorithmParameterSpec}
- * 在某些算法中,需要特别的参数,例如在ECIES中,此处为IESParameterSpec
- *
- * @return {@link AlgorithmParameterSpec}
- */
- public AlgorithmParameterSpec getParams() {
- return this.params;
- }
-
- /**
- * 设置 {@link AlgorithmParameterSpec},通常用于加盐或偏移向量
- *
- * @param params {@link AlgorithmParameterSpec}
- * @return this
- */
- public CipherWrapper setParams(final AlgorithmParameterSpec params) {
- this.params = params;
- return this;
- }
-
- /**
- * 设置随机数生成器,可自定义随机数种子
- *
- * @param random 随机数生成器,可自定义随机数种子
- * @return this
- */
- public CipherWrapper setRandom(final SecureRandom random) {
- this.random = random;
- return this;
- }
-
- /**
- * 获取被包装的{@link Cipher}
- *
- * @return {@link Cipher}
- */
- @Override
- public Cipher getRaw() {
- 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(final int mode, final 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;
- }
-}
diff --git a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/JceCipher.java b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/JceCipher.java
new file mode 100644
index 000000000..ca92856e8
--- /dev/null
+++ b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/JceCipher.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2024. looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * https://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.crypto;
+
+import org.dromara.hutool.core.lang.Assert;
+import org.dromara.hutool.core.lang.wrapper.Wrapper;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * 提供{@link javax.crypto.Cipher}的方法包装
+ *
+ * @author Looly
+ */
+public class JceCipher implements Cipher, Wrapper {
+
+ private final javax.crypto.Cipher cipher;
+
+ /**
+ * 构造
+ *
+ * @param algorithm 算法名称
+ */
+ public JceCipher(final String algorithm) {
+ this(SecureUtil.createCipher(algorithm));
+ }
+
+ /**
+ * 构造
+ *
+ * @param cipher {@link javax.crypto.Cipher}
+ */
+ public JceCipher(final javax.crypto.Cipher cipher) {
+ this.cipher = cipher;
+ }
+
+ @Override
+ public javax.crypto.Cipher getRaw() {
+ return this.cipher;
+ }
+
+ @Override
+ public String getAlgorithmName() {
+ return this.cipher.getAlgorithm();
+ }
+
+ @Override
+ public int getBlockSize() {
+ return this.cipher.getBlockSize();
+ }
+
+ @Override
+ public void init(final CipherMode mode, final Parameters parameters) {
+ Assert.isInstanceOf(JceParameters.class, parameters, "Only support JceParameters!");
+
+ try {
+ init(mode.getValue(), (JceParameters) parameters);
+ } catch (final InvalidAlgorithmParameterException | InvalidKeyException e) {
+ throw new CryptoException(e);
+ }
+ }
+
+ /**
+ * 执行初始化参数操作
+ *
+ * @param mode 模式
+ * @param jceParameters {@link JceParameters}
+ * @throws InvalidAlgorithmParameterException 无效算法参数
+ * @throws InvalidKeyException 无效key
+ */
+ public void init(final int mode, final JceParameters jceParameters) throws InvalidAlgorithmParameterException, InvalidKeyException {
+ final javax.crypto.Cipher cipher = this.cipher;
+ if (null != jceParameters.parameterSpec) {
+ if (null != jceParameters.random) {
+ cipher.init(mode, jceParameters.key, jceParameters.parameterSpec, jceParameters.random);
+ } else {
+ cipher.init(mode, jceParameters.key, jceParameters.parameterSpec);
+ }
+ } else {
+ if (null != jceParameters.random) {
+ cipher.init(mode, jceParameters.key, jceParameters.random);
+ } else {
+ cipher.init(mode, jceParameters.key);
+ }
+ }
+ }
+
+ @Override
+ public byte[] process(final byte[] data) {
+ return new byte[0];
+ }
+
+ /**
+ * JCE的{@link AlgorithmParameterSpec} 参数包装
+ */
+ public static class JceParameters implements Parameters {
+ private final Key key;
+ /**
+ * 算法参数
+ */
+ private final AlgorithmParameterSpec parameterSpec;
+ /**
+ * 随机数生成器,可自定义随机数种子
+ */
+ private final SecureRandom random;
+
+ /**
+ * 构造
+ *
+ * @param key 密钥
+ * @param parameterSpec {@link AlgorithmParameterSpec}
+ * @param random 自定义随机数生成器
+ */
+ public JceParameters(final Key key, final AlgorithmParameterSpec parameterSpec, final SecureRandom random) {
+ this.key = key;
+ this.parameterSpec = parameterSpec;
+ this.random = random;
+ }
+ }
+}
diff --git a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/Mode.java b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/Mode.java
index 7ef557bae..87e592bfb 100644
--- a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/Mode.java
+++ b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/Mode.java
@@ -54,5 +54,10 @@ public enum Mode {
/**
* Propagating Cipher Block
*/
- PCBC
+ PCBC,
+ /**
+ * GCM 全称为 Galois/Counter Mode。G是指GMAC,C是指CTR。
+ * 它在 CTR 加密的基础上增加 GMAC 的特性,解决了 CTR 不能对加密消息进行完整性校验的问题。
+ */
+ GCM
}
diff --git a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/AsymmetricCrypto.java b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/AsymmetricCrypto.java
index b050f6bf8..1731a0b62 100644
--- a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/AsymmetricCrypto.java
+++ b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/asymmetric/AsymmetricCrypto.java
@@ -14,10 +14,7 @@ package org.dromara.hutool.crypto.asymmetric;
import org.dromara.hutool.core.codec.binary.Base64;
import org.dromara.hutool.core.io.stream.FastByteArrayOutputStream;
-import org.dromara.hutool.crypto.CipherWrapper;
-import org.dromara.hutool.crypto.CryptoException;
-import org.dromara.hutool.crypto.KeyUtil;
-import org.dromara.hutool.crypto.SecureUtil;
+import org.dromara.hutool.crypto.*;
import org.dromara.hutool.crypto.symmetric.SymmetricAlgorithm;
import javax.crypto.BadPaddingException;
@@ -51,8 +48,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
/**
* Cipher负责完成加密或解密工作
*/
- protected CipherWrapper cipherWrapper;
-
+ protected JceCipher cipher;
/**
* 加密的块大小
*/
@@ -61,6 +57,15 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
* 解密的块大小
*/
protected int decryptBlockSize = -1;
+
+ /**
+ * 算法参数
+ */
+ private AlgorithmParameterSpec algorithmParameterSpec;
+ /**
+ * 自定义随机数
+ */
+ private SecureRandom random;
// ------------------------------------------------------------------ Constructor start
/**
@@ -209,7 +214,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
* @since 5.4.3
*/
public AlgorithmParameterSpec getAlgorithmParameterSpec() {
- return this.cipherWrapper.getParams();
+ return this.algorithmParameterSpec;
}
/**
@@ -217,10 +222,11 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
* 在某些算法中,需要特别的参数,例如在ECIES中,此处为IESParameterSpec
*
* @param algorithmParameterSpec {@link AlgorithmParameterSpec}
- * @since 5.4.3
+ * @return this
*/
- public void setAlgorithmParameterSpec(final AlgorithmParameterSpec algorithmParameterSpec) {
- this.cipherWrapper.setParams(algorithmParameterSpec);
+ public AsymmetricCrypto setAlgorithmParameterSpec(final AlgorithmParameterSpec algorithmParameterSpec) {
+ this.algorithmParameterSpec = algorithmParameterSpec;
+ return this;
}
/**
@@ -231,7 +237,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
* @since 5.7.17
*/
public AsymmetricCrypto setRandom(final SecureRandom random) {
- this.cipherWrapper.setRandom(random);
+ this.random = random;
return this;
}
@@ -301,7 +307,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
* @since 5.4.3
*/
public Cipher getCipher() {
- return this.cipherWrapper.getRaw();
+ return this.cipher.getRaw();
}
/**
@@ -310,7 +316,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
* @since 4.5.2
*/
protected void initCipher() {
- this.cipherWrapper = new CipherWrapper(this.algorithm);
+ this.cipher = new JceCipher(this.algorithm);
}
/**
@@ -376,6 +382,9 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto
* @throws InvalidKeyException 异常KEY错误
*/
private Cipher initMode(final int mode, final Key key) throws InvalidAlgorithmParameterException, InvalidKeyException {
- return this.cipherWrapper.initMode(mode, key).getRaw();
+ final JceCipher cipher = this.cipher;
+ cipher.init(mode,
+ new JceCipher.JceParameters(key, this.algorithmParameterSpec, this.random));
+ return cipher.getRaw();
}
}
diff --git a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/bc/BCCipher.java b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/bc/BCCipher.java
new file mode 100644
index 000000000..ad51cd410
--- /dev/null
+++ b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/bc/BCCipher.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2024. looly(loolly@aliyun.com)
+ * Hutool is licensed under Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * https://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ */
+
+package org.dromara.hutool.crypto.bc;
+
+import org.bouncycastle.crypto.BufferedBlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.dromara.hutool.core.lang.Assert;
+import org.dromara.hutool.crypto.Cipher;
+import org.dromara.hutool.crypto.CipherMode;
+import org.dromara.hutool.crypto.CryptoException;
+
+/**
+ * 基于BouncyCastle库的{@link BufferedBlockCipher}封装的加密解密实现
+ *
+ * @author Looly, changhr2013
+ */
+public class BCCipher implements Cipher {
+
+ /**
+ * {@link BufferedBlockCipher},包含engine、mode、padding
+ */
+ private final BufferedBlockCipher blockCipher;
+
+ /**
+ * 构造
+ *
+ * @param blockCipher {@link BufferedBlockCipher}
+ */
+ public BCCipher(final BufferedBlockCipher blockCipher) {
+ this.blockCipher = blockCipher;
+ }
+
+ @Override
+ public String getAlgorithmName() {
+ return this.blockCipher.getUnderlyingCipher().getAlgorithmName();
+ }
+
+ @Override
+ public int getBlockSize() {
+ return this.blockCipher.getBlockSize();
+ }
+
+ @Override
+ public void init(final CipherMode mode, final Parameters parameters) {
+ Assert.isInstanceOf(BCParameters.class, parameters, "Only support BCParameters!");
+ this.blockCipher.init(mode == CipherMode.encrypt, ((BCParameters) parameters).parameters);
+ }
+
+ @Override
+ public byte[] process(final byte[] data) {
+ final byte[] out;
+ try {
+ final BufferedBlockCipher cipher = this.blockCipher;
+ final int updateOutputSize = cipher.getOutputSize(data.length);
+ final byte[] buf = new byte[updateOutputSize];
+ int len = cipher.processBytes(data, 0, data.length, buf, 0);
+ len += cipher.doFinal(buf, len);
+ out = new byte[len];
+ System.arraycopy(buf, 0, out, 0, len);
+ } catch (final Exception e) {
+ throw new CryptoException("encrypt/decrypt process exception.", e);
+ }
+ return out;
+ }
+
+ /**
+ * BouncyCastle库的{@link CipherParameters}封装
+ *
+ * @author Looly
+ */
+ public static class BCParameters implements Parameters {
+ /**
+ * 算法的参数
+ */
+ private final CipherParameters parameters;
+
+ /**
+ * 构造
+ *
+ * @param parameters {@link CipherParameters}
+ */
+ public BCParameters(final CipherParameters parameters) {
+ this.parameters = parameters;
+ }
+ }
+}
diff --git a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/bc/BCUtil.java b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/bc/BCUtil.java
index f392fe8fe..9455bbb26 100644
--- a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/bc/BCUtil.java
+++ b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/bc/BCUtil.java
@@ -15,10 +15,19 @@ package org.dromara.hutool.crypto.bc;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.BufferedBlockCipher;
+import org.bouncycastle.crypto.DefaultBufferedBlockCipher;
+import org.bouncycastle.crypto.modes.*;
+import org.bouncycastle.crypto.paddings.ISO10126d2Padding;
+import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
+import org.bouncycastle.crypto.paddings.ZeroBytePadding;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.dromara.hutool.core.io.IORuntimeException;
+import org.dromara.hutool.crypto.Mode;
+import org.dromara.hutool.crypto.Padding;
import java.io.IOException;
import java.security.PrivateKey;
@@ -41,10 +50,10 @@ public class BCUtil {
*/
public static ECDomainParameters toDomainParams(final ECParameterSpec parameterSpec) {
return new ECDomainParameters(
- parameterSpec.getCurve(),
- parameterSpec.getG(),
- parameterSpec.getN(),
- parameterSpec.getH());
+ parameterSpec.getCurve(),
+ parameterSpec.getG(),
+ parameterSpec.getN(),
+ parameterSpec.getH());
}
/**
@@ -67,10 +76,10 @@ public class BCUtil {
*/
public static ECDomainParameters toDomainParams(final X9ECParameters x9ECParameters) {
return new ECDomainParameters(
- x9ECParameters.getCurve(),
- x9ECParameters.getG(),
- x9ECParameters.getN(),
- x9ECParameters.getH()
+ x9ECParameters.getCurve(),
+ x9ECParameters.getG(),
+ x9ECParameters.getN(),
+ x9ECParameters.getH()
);
}
@@ -81,7 +90,7 @@ public class BCUtil {
* @return PKCS#1格式私钥
* @since 5.5.9
*/
- public static byte[] toPkcs1(final PrivateKey privateKey){
+ public static byte[] toPkcs1(final PrivateKey privateKey) {
final PrivateKeyInfo pkInfo = PrivateKeyInfo.getInstance(privateKey.getEncoded());
try {
return pkInfo.parsePrivateKey().toASN1Primitive().getEncoded();
@@ -97,13 +106,53 @@ public class BCUtil {
* @return PKCS#1格式公钥
* @since 5.5.9
*/
- public static byte[] toPkcs1(final PublicKey publicKey){
+ public static byte[] toPkcs1(final PublicKey publicKey) {
final SubjectPublicKeyInfo spkInfo = SubjectPublicKeyInfo
- .getInstance(publicKey.getEncoded());
+ .getInstance(publicKey.getEncoded());
try {
return spkInfo.parsePublicKey().getEncoded();
} catch (final IOException e) {
throw new IORuntimeException(e);
}
}
+
+ /**
+ * 将{@link BlockCipher}包装为指定mode和padding的{@link BufferedBlockCipher}
+ *
+ * @param cipher {@link BlockCipher}
+ * @param mode 模式
+ * @param padding 补码方式
+ * @return {@link BufferedBlockCipher},无对应Cipher返回{@code null}
+ * @since 6.0.0
+ */
+ public static BufferedBlockCipher wrap(BlockCipher cipher, final Mode mode, final Padding padding) {
+ switch (mode) {
+ case CBC:
+ cipher = CBCBlockCipher.newInstance(cipher);
+ break;
+ case CFB:
+ cipher = CFBBlockCipher.newInstance(cipher, cipher.getBlockSize() * 8);
+ break;
+ case CTR:
+ cipher = SICBlockCipher.newInstance(cipher);
+ break;
+ case OFB:
+ cipher = new OFBBlockCipher(cipher, cipher.getBlockSize() * 8);
+ case CTS:
+ return new CTSBlockCipher(cipher);
+ }
+
+ switch (padding) {
+ case NoPadding:
+ return new DefaultBufferedBlockCipher(cipher);
+ case PKCS5Padding:
+ return new PaddedBufferedBlockCipher(cipher);
+ case ZeroPadding:
+ return new PaddedBufferedBlockCipher(cipher, new ZeroBytePadding());
+ case ISO10126Padding:
+ return new PaddedBufferedBlockCipher(cipher, new ISO10126d2Padding());
+ }
+
+ return null;
+ }
}
diff --git a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/symmetric/SymmetricCrypto.java b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/symmetric/SymmetricCrypto.java
index 38cea58af..3de82962a 100644
--- a/hutool-crypto/src/main/java/org/dromara/hutool/crypto/symmetric/SymmetricCrypto.java
+++ b/hutool-crypto/src/main/java/org/dromara/hutool/crypto/symmetric/SymmetricCrypto.java
@@ -52,7 +52,15 @@ import java.util.concurrent.locks.ReentrantLock;
public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor, Serializable {
private static final long serialVersionUID = 1L;
- private CipherWrapper cipherWrapper;
+ private JceCipher cipher;
+ /**
+ * 算法参数
+ */
+ private AlgorithmParameterSpec algorithmParameterSpec;
+ /**
+ * 自定义随机数
+ */
+ private SecureRandom random;
/**
* SecretKey 负责保存对称密钥
*/
@@ -157,7 +165,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
this.isZeroPadding = true;
}
- this.cipherWrapper = new CipherWrapper(algorithm);
+ this.cipher = new JceCipher(algorithm);
return this;
}
@@ -176,17 +184,17 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
* @return 加密或解密
*/
public Cipher getCipher() {
- return cipherWrapper.getRaw();
+ return cipher.getRaw();
}
/**
- * 设置 {@link AlgorithmParameterSpec},通常用于加盐或偏移向量
+ * 设置{@link AlgorithmParameterSpec},通常用于加盐或偏移向量
*
- * @param params {@link AlgorithmParameterSpec}
- * @return 自身
+ * @param algorithmParameterSpec {@link AlgorithmParameterSpec}
+ * @return this
*/
- public SymmetricCrypto setParams(final AlgorithmParameterSpec params) {
- this.cipherWrapper.setParams(params);
+ public SymmetricCrypto setAlgorithmParameterSpec(final AlgorithmParameterSpec algorithmParameterSpec) {
+ this.algorithmParameterSpec = algorithmParameterSpec;
return this;
}
@@ -197,7 +205,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
* @return 自身
*/
public SymmetricCrypto setIv(final IvParameterSpec iv) {
- return setParams(iv);
+ return setAlgorithmParameterSpec(iv);
}
/**
@@ -218,7 +226,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
* @since 5.7.17
*/
public SymmetricCrypto setRandom(final SecureRandom random) {
- this.cipherWrapper.setRandom(random);
+ this.random = random;
return this;
}
@@ -263,7 +271,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
* @since 5.6.8
*/
public byte[] update(final byte[] data) {
- final Cipher cipher = cipherWrapper.getRaw();
+ final Cipher cipher = this.cipher.getRaw();
lock.lock();
try {
return cipher.update(paddingDataWithZero(data, cipher.getBlockSize()));
@@ -417,8 +425,8 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
*/
private SymmetricCrypto initParams(final String algorithm, AlgorithmParameterSpec paramsSpec) {
if (null == paramsSpec) {
- byte[] iv = Opt.ofNullable(cipherWrapper)
- .map(CipherWrapper::getRaw).map(Cipher::getIV).get();
+ byte[] iv = Opt.ofNullable(cipher)
+ .map(JceCipher::getRaw).map(Cipher::getIV).get();
// 随机IV
if (StrUtil.startWithIgnoreCase(algorithm, "PBE")) {
@@ -435,7 +443,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
}
}
- return setParams(paramsSpec);
+ return setAlgorithmParameterSpec(paramsSpec);
}
/**
@@ -455,10 +463,14 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
.getKeyAndIV(secretKey.getEncoded(), salt);
secretKey = KeyUtil.generateKey(algorithm, keyAndIV[0]);
if(ArrayUtil.isNotEmpty(keyAndIV[1])){
- this.cipherWrapper.setParams(new IvParameterSpec(keyAndIV[1]));
+ setAlgorithmParameterSpec(new IvParameterSpec(keyAndIV[1]));
}
}
- return this.cipherWrapper.initMode(mode, secretKey).getRaw();
+
+ final JceCipher cipher = this.cipher;
+ cipher.init(mode,
+ new JceCipher.JceParameters(secretKey, this.algorithmParameterSpec, this.random));
+ return cipher.getRaw();
}
/**