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}包装类,提供初始化模式等额外方法
- * 包装之后可提供自定义或默认的: - * - * - * @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(); } /**