mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add Cipher
This commit is contained in:
parent
30fafaa5de
commit
9992d776da
@ -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 { }
|
||||
}
|
@ -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}包装类,提供初始化模式等额外方法<br>
|
||||
* 包装之后可提供自定义或默认的:
|
||||
* <ul>
|
||||
* <li>{@link AlgorithmParameterSpec}</li>
|
||||
* <li>{@link SecureRandom}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.7.17
|
||||
*/
|
||||
public class CipherWrapper implements Wrapper<Cipher> {
|
||||
|
||||
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}<br>
|
||||
* 在某些算法中,需要特别的参数,例如在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;
|
||||
}
|
||||
}
|
@ -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<javax.crypto.Cipher> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -54,5 +54,10 @@ public enum Mode {
|
||||
/**
|
||||
* Propagating Cipher Block
|
||||
*/
|
||||
PCBC
|
||||
PCBC,
|
||||
/**
|
||||
* GCM 全称为 Galois/Counter Mode。G是指GMAC,C是指CTR。
|
||||
* 它在 CTR 加密的基础上增加 GMAC 的特性,解决了 CTR 不能对加密消息进行完整性校验的问题。
|
||||
*/
|
||||
GCM
|
||||
}
|
||||
|
@ -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<AsymmetricCrypto>
|
||||
/**
|
||||
* Cipher负责完成加密或解密工作
|
||||
*/
|
||||
protected CipherWrapper cipherWrapper;
|
||||
|
||||
protected JceCipher cipher;
|
||||
/**
|
||||
* 加密的块大小
|
||||
*/
|
||||
@ -61,6 +57,15 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
|
||||
* 解密的块大小
|
||||
*/
|
||||
protected int decryptBlockSize = -1;
|
||||
|
||||
/**
|
||||
* 算法参数
|
||||
*/
|
||||
private AlgorithmParameterSpec algorithmParameterSpec;
|
||||
/**
|
||||
* 自定义随机数
|
||||
*/
|
||||
private SecureRandom random;
|
||||
// ------------------------------------------------------------------ Constructor start
|
||||
|
||||
/**
|
||||
@ -209,7 +214,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
|
||||
* @since 5.4.3
|
||||
*/
|
||||
public AlgorithmParameterSpec getAlgorithmParameterSpec() {
|
||||
return this.cipherWrapper.getParams();
|
||||
return this.algorithmParameterSpec;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -217,10 +222,11 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
|
||||
* 在某些算法中,需要特别的参数,例如在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<AsymmetricCrypto>
|
||||
* @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<AsymmetricCrypto>
|
||||
* @since 5.4.3
|
||||
*/
|
||||
public Cipher getCipher() {
|
||||
return this.cipherWrapper.getRaw();
|
||||
return this.cipher.getRaw();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -310,7 +316,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
|
||||
* @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<AsymmetricCrypto>
|
||||
* @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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user