mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
fix code
This commit is contained in:
parent
6fba25ad7d
commit
46febc3d05
@ -12,6 +12,10 @@
|
||||
|
||||
package org.dromara.hutool.crypto;
|
||||
|
||||
import org.bouncycastle.crypto.BufferedBlockCipher;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 密码接口,提供统一的API,用于兼容和统一JCE和BouncyCastle等库的操作
|
||||
*
|
||||
@ -30,7 +34,7 @@ public interface Cipher {
|
||||
/**
|
||||
* 获取块大小,当为Stream方式加密时返回0
|
||||
*
|
||||
* @return 块大小
|
||||
* @return 块大小,-1表示非块加密
|
||||
*/
|
||||
int getBlockSize();
|
||||
|
||||
@ -42,16 +46,59 @@ public interface Cipher {
|
||||
*/
|
||||
void init(CipherMode mode, Parameters parameters);
|
||||
|
||||
/**
|
||||
* 根据输入长度,获取输出长度,输出长度与算法相关<br>
|
||||
* 输出长度只针对本次输入关联,即len长度的数据对应输出长度加doFinal的长度
|
||||
*
|
||||
* @param len 输入长度
|
||||
* @return 输出长度,-1表示非块加密
|
||||
*/
|
||||
int getOutputSize(int len);
|
||||
|
||||
/**
|
||||
* 执行运算,可以是加密运算或解密运算
|
||||
*
|
||||
* @param data 被处理的数据
|
||||
* @return 运算结果
|
||||
* @param in 输入数据
|
||||
* @param inOff 输入数据开始位置
|
||||
* @param len 被处理数据长度
|
||||
* @param out 输出数据
|
||||
* @param outOff 输出数据开始位置
|
||||
* @return 处理长度
|
||||
*/
|
||||
byte[] process(byte[] data);
|
||||
int process(byte[] in, int inOff, int len, byte[] out, int outOff);
|
||||
|
||||
/**
|
||||
* 处理最后一块数据<br>
|
||||
* 当{@link #process(byte[], int, int, byte[], int)}处理完数据后非完整块数据,此方法用于处理块中剩余的bytes<br>
|
||||
* 如加密数据要求128bit,即16byes的整数,单数处理数据后为15bytes,此时根据padding方式不同,可填充剩余1byte为指定值(如填充0)<br>
|
||||
* 当对数据进行分段加密时,需要首先多次执行process方法,在最后一块数据处理完后执行此方法。
|
||||
*
|
||||
* @param out 经过process执行过运算的结果数据
|
||||
* @param outOff 数据处理开始位置
|
||||
* @return 处理长度
|
||||
*/
|
||||
int doFinal(byte[] out, int outOff);
|
||||
|
||||
/**
|
||||
* 处理数据,并返回最终结果
|
||||
*
|
||||
* @param in 输入数据
|
||||
* @return 结果数据
|
||||
*/
|
||||
default byte[] processFinal(final byte[] in) {
|
||||
final byte[] buf = new byte[getOutputSize(in.length)];
|
||||
int len = process(in, 0, in.length, buf, 0);
|
||||
len += doFinal(buf, len);
|
||||
|
||||
if (len == buf.length) {
|
||||
return buf;
|
||||
}
|
||||
return Arrays.copyOfRange(buf, 0, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cipher所需参数,包括Key、Random、IV等信息
|
||||
*/
|
||||
interface Parameters { }
|
||||
interface Parameters {
|
||||
}
|
||||
}
|
||||
|
@ -24,19 +24,19 @@ public enum CipherMode {
|
||||
/**
|
||||
* 加密模式
|
||||
*/
|
||||
encrypt(Cipher.ENCRYPT_MODE),
|
||||
ENCRYPT(Cipher.ENCRYPT_MODE),
|
||||
/**
|
||||
* 解密模式
|
||||
*/
|
||||
decrypt(Cipher.DECRYPT_MODE),
|
||||
DECRYPT(Cipher.DECRYPT_MODE),
|
||||
/**
|
||||
* 包装模式
|
||||
*/
|
||||
wrap(Cipher.WRAP_MODE),
|
||||
WRAP(Cipher.WRAP_MODE),
|
||||
/**
|
||||
* 拆包模式
|
||||
*/
|
||||
unwrap(Cipher.UNWRAP_MODE);
|
||||
UNWRAP(Cipher.UNWRAP_MODE);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -15,6 +15,7 @@ package org.dromara.hutool.crypto;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.lang.wrapper.Wrapper;
|
||||
|
||||
import javax.crypto.ShortBufferException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
@ -63,6 +64,11 @@ public class JceCipher implements Cipher, Wrapper<javax.crypto.Cipher> {
|
||||
return this.cipher.getBlockSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOutputSize(final int len) {
|
||||
return this.cipher.getOutputSize(len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(final CipherMode mode, final Parameters parameters) {
|
||||
Assert.isInstanceOf(JceParameters.class, parameters, "Only support JceParameters!");
|
||||
@ -100,8 +106,30 @@ public class JceCipher implements Cipher, Wrapper<javax.crypto.Cipher> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] process(final byte[] data) {
|
||||
return new byte[0];
|
||||
public int process(final byte[] in, final int inOff, final int len, final byte[] out, final int outOff) {
|
||||
try {
|
||||
return this.cipher.update(in, inOff, len, out, outOff);
|
||||
} catch (final ShortBufferException e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int doFinal(final byte[] out, final int outOff) {
|
||||
try {
|
||||
return this.cipher.doFinal(out, outOff);
|
||||
} catch (final Exception e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] processFinal(final byte[] data) {
|
||||
try {
|
||||
return this.cipher.doFinal(data);
|
||||
} catch (final Exception e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,8 +21,6 @@ import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
@ -149,8 +147,8 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
|
||||
*/
|
||||
public AsymmetricCrypto(final String algorithm, final byte[] privateKey, final byte[] publicKey) {
|
||||
this(algorithm, //
|
||||
KeyUtil.generatePrivateKey(algorithm, privateKey), //
|
||||
KeyUtil.generatePublicKey(algorithm, publicKey)//
|
||||
KeyUtil.generatePrivateKey(algorithm, privateKey), //
|
||||
KeyUtil.generatePublicKey(algorithm, publicKey)//
|
||||
);
|
||||
}
|
||||
|
||||
@ -255,7 +253,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
|
||||
final Key key = getKeyByType(keyType);
|
||||
lock.lock();
|
||||
try {
|
||||
final Cipher cipher = initMode(Cipher.ENCRYPT_MODE, key);
|
||||
final JceCipher cipher = initMode(CipherMode.ENCRYPT, key);
|
||||
|
||||
if (this.encryptBlockSize < 0) {
|
||||
// 在引入BC库情况下,自动获取块大小
|
||||
@ -280,7 +278,7 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
|
||||
final Key key = getKeyByType(keyType);
|
||||
lock.lock();
|
||||
try {
|
||||
final Cipher cipher = initMode(Cipher.DECRYPT_MODE, key);
|
||||
final JceCipher cipher = initMode(CipherMode.DECRYPT, key);
|
||||
|
||||
if (this.decryptBlockSize < 0) {
|
||||
// 在引入BC库情况下,自动获取块大小
|
||||
@ -352,9 +350,10 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
|
||||
* @throws BadPaddingException padding错误异常
|
||||
* @throws IOException IO异常,不会被触发
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
private byte[] doFinalWithBlock(final byte[] data, final int maxBlockSize) throws IllegalBlockSizeException, BadPaddingException, IOException {
|
||||
final int dataLength = data.length;
|
||||
@SuppressWarnings("resource") final FastByteArrayOutputStream out = new FastByteArrayOutputStream();
|
||||
final FastByteArrayOutputStream out = new FastByteArrayOutputStream();
|
||||
|
||||
int offSet = 0;
|
||||
// 剩余长度
|
||||
@ -373,18 +372,15 @@ public class AsymmetricCrypto extends AbstractAsymmetricCrypto<AsymmetricCrypto>
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化{@link Cipher}的模式,如加密模式或解密模式
|
||||
* 初始化{@link JceCipher}的模式,如加密模式或解密模式
|
||||
*
|
||||
* @param mode 模式,可选{@link Cipher#ENCRYPT_MODE}或者{@link Cipher#DECRYPT_MODE}
|
||||
* @param mode 模式,可选{@link CipherMode#ENCRYPT}或者{@link CipherMode#DECRYPT}
|
||||
* @param key 密钥
|
||||
* @return {@link Cipher}
|
||||
* @throws InvalidAlgorithmParameterException 异常算法错误
|
||||
* @throws InvalidKeyException 异常KEY错误
|
||||
* @return {@link JceCipher}
|
||||
*/
|
||||
private Cipher initMode(final int mode, final Key key) throws InvalidAlgorithmParameterException, InvalidKeyException {
|
||||
private JceCipher initMode(final CipherMode mode, final Key key) {
|
||||
final JceCipher cipher = this.cipher;
|
||||
cipher.init(mode,
|
||||
new JceCipher.JceParameters(key, this.algorithmParameterSpec, this.random));
|
||||
return cipher.getRaw();
|
||||
cipher.init(mode, new JceCipher.JceParameters(key, this.algorithmParameterSpec, this.random));
|
||||
return cipher;
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,9 @@ package org.dromara.hutool.crypto.bc;
|
||||
|
||||
import org.bouncycastle.crypto.BufferedBlockCipher;
|
||||
import org.bouncycastle.crypto.CipherParameters;
|
||||
import org.bouncycastle.crypto.InvalidCipherTextException;
|
||||
import org.bouncycastle.crypto.StreamCipher;
|
||||
import org.bouncycastle.crypto.modes.AEADBlockCipher;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.lang.wrapper.Wrapper;
|
||||
import org.dromara.hutool.crypto.Cipher;
|
||||
@ -21,16 +24,31 @@ import org.dromara.hutool.crypto.CipherMode;
|
||||
import org.dromara.hutool.crypto.CryptoException;
|
||||
|
||||
/**
|
||||
* 基于BouncyCastle库的{@link BufferedBlockCipher}封装的加密解密实现
|
||||
* 基于BouncyCastle库封装的加密解密实现,包装包括:
|
||||
* <ul>
|
||||
* <li>{@link BufferedBlockCipher}</li>
|
||||
* <li>{@link StreamCipher}</li>
|
||||
* <li>{@link AEADBlockCipher}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Looly, changhr2013
|
||||
*/
|
||||
public class BCCipher implements Cipher, Wrapper<BufferedBlockCipher> {
|
||||
public class BCCipher implements Cipher, Wrapper<Object> {
|
||||
|
||||
/**
|
||||
* {@link BufferedBlockCipher},包含engine、mode、padding
|
||||
* {@link BufferedBlockCipher},块加密,包含engine、mode、padding
|
||||
*/
|
||||
private final BufferedBlockCipher blockCipher;
|
||||
private BufferedBlockCipher blockCipher;
|
||||
/**
|
||||
* {@link AEADBlockCipher}, 关联数据的认证加密(Authenticated Encryption with Associated Data)
|
||||
*/
|
||||
private AEADBlockCipher aeadBlockCipher;
|
||||
/**
|
||||
* {@link StreamCipher}
|
||||
*/
|
||||
private StreamCipher streamCipher;
|
||||
|
||||
// region ----- 构造
|
||||
|
||||
/**
|
||||
* 构造
|
||||
@ -41,42 +59,112 @@ public class BCCipher implements Cipher, Wrapper<BufferedBlockCipher> {
|
||||
this.blockCipher = Assert.notNull(blockCipher);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param aeadBlockCipher {@link AEADBlockCipher}
|
||||
*/
|
||||
public BCCipher(final AEADBlockCipher aeadBlockCipher) {
|
||||
this.aeadBlockCipher = Assert.notNull(aeadBlockCipher);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param streamCipher {@link StreamCipher}
|
||||
*/
|
||||
public BCCipher(final StreamCipher streamCipher) {
|
||||
this.streamCipher = Assert.notNull(streamCipher);
|
||||
}
|
||||
// endregion
|
||||
|
||||
@Override
|
||||
public BufferedBlockCipher getRaw() {
|
||||
return this.blockCipher;
|
||||
public Object getRaw() {
|
||||
if (null != this.blockCipher) {
|
||||
return this.blockCipher;
|
||||
}
|
||||
if (null != this.aeadBlockCipher) {
|
||||
return this.aeadBlockCipher;
|
||||
}
|
||||
return this.streamCipher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAlgorithmName() {
|
||||
return this.blockCipher.getUnderlyingCipher().getAlgorithmName();
|
||||
if (null != this.blockCipher) {
|
||||
return this.blockCipher.getUnderlyingCipher().getAlgorithmName();
|
||||
}
|
||||
if (null != this.aeadBlockCipher) {
|
||||
return this.aeadBlockCipher.getUnderlyingCipher().getAlgorithmName();
|
||||
}
|
||||
return this.streamCipher.getAlgorithmName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockSize() {
|
||||
return this.blockCipher.getBlockSize();
|
||||
if (null != this.blockCipher) {
|
||||
return this.blockCipher.getBlockSize();
|
||||
}
|
||||
if (null != this.aeadBlockCipher) {
|
||||
return this.aeadBlockCipher.getUnderlyingCipher().getBlockSize();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
if (null != this.blockCipher) {
|
||||
this.blockCipher.init(mode == CipherMode.ENCRYPT, ((BCParameters) parameters).parameters);
|
||||
return;
|
||||
}
|
||||
if (null != this.aeadBlockCipher) {
|
||||
this.aeadBlockCipher.init(mode == CipherMode.ENCRYPT, ((BCParameters) parameters).parameters);
|
||||
return;
|
||||
}
|
||||
this.streamCipher.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);
|
||||
public int getOutputSize(final int len) {
|
||||
if (null != this.blockCipher) {
|
||||
return this.blockCipher.getOutputSize(len);
|
||||
}
|
||||
return out;
|
||||
if (null != this.aeadBlockCipher) {
|
||||
return this.aeadBlockCipher.getOutputSize(len);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int process(final byte[] in, final int inOff, final int len, final byte[] out, final int outOff) {
|
||||
if (null != this.blockCipher) {
|
||||
return this.blockCipher.processBytes(in, inOff, len, out, outOff);
|
||||
}
|
||||
if (null != this.aeadBlockCipher) {
|
||||
return this.aeadBlockCipher.processBytes(in, inOff, len, out, outOff);
|
||||
}
|
||||
return this.streamCipher.processBytes(in, inOff, len, out, outOff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int doFinal(final byte[] out, final int outOff) {
|
||||
if (null != this.blockCipher) {
|
||||
try {
|
||||
return this.blockCipher.doFinal(out, outOff);
|
||||
} catch (final InvalidCipherTextException e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
}
|
||||
if (null != this.aeadBlockCipher) {
|
||||
try {
|
||||
return this.aeadBlockCipher.doFinal(out, outOff);
|
||||
} catch (final InvalidCipherTextException e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -34,8 +34,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
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;
|
||||
@ -253,9 +251,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
|
||||
public SymmetricCrypto setMode(final CipherMode mode, final byte[] salt) {
|
||||
lock.lock();
|
||||
try {
|
||||
initMode(mode.getValue(), salt);
|
||||
} catch (final Exception e) {
|
||||
throw new CryptoException(e);
|
||||
initMode(mode, salt);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
@ -313,10 +309,8 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
|
||||
byte[] result;
|
||||
lock.lock();
|
||||
try {
|
||||
final Cipher cipher = initMode(Cipher.ENCRYPT_MODE, salt);
|
||||
result = cipher.doFinal(paddingDataWithZero(data, cipher.getBlockSize()));
|
||||
} catch (final Exception e) {
|
||||
throw new CryptoException(e);
|
||||
final JceCipher cipher = initMode(CipherMode.ENCRYPT, salt);
|
||||
result = cipher.processFinal(paddingDataWithZero(data, cipher.getBlockSize()));
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
@ -328,8 +322,8 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
|
||||
CipherOutputStream cipherOutputStream = null;
|
||||
lock.lock();
|
||||
try {
|
||||
final Cipher cipher = initMode(Cipher.ENCRYPT_MODE, null);
|
||||
cipherOutputStream = new CipherOutputStream(out, cipher);
|
||||
final JceCipher cipher = initMode(CipherMode.ENCRYPT, null);
|
||||
cipherOutputStream = new CipherOutputStream(out, cipher.getRaw());
|
||||
final long length = IoUtil.copy(data, cipherOutputStream);
|
||||
if (this.isZeroPadding) {
|
||||
final int blockSize = cipher.getBlockSize();
|
||||
@ -367,9 +361,9 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
|
||||
lock.lock();
|
||||
try {
|
||||
final byte[] salt = SaltMagic.getSalt(bytes);
|
||||
final Cipher cipher = initMode(Cipher.DECRYPT_MODE, salt);
|
||||
final JceCipher cipher = initMode(CipherMode.DECRYPT, salt);
|
||||
blockSize = cipher.getBlockSize();
|
||||
decryptData = cipher.doFinal(SaltMagic.getData(bytes));
|
||||
decryptData = cipher.processFinal(SaltMagic.getData(bytes));
|
||||
} catch (final Exception e) {
|
||||
throw new CryptoException(e);
|
||||
} finally {
|
||||
@ -384,8 +378,8 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
|
||||
CipherInputStream cipherInputStream = null;
|
||||
lock.lock();
|
||||
try {
|
||||
final Cipher cipher = initMode(Cipher.DECRYPT_MODE, null);
|
||||
cipherInputStream = new CipherInputStream(data, cipher);
|
||||
final JceCipher cipher = initMode(CipherMode.DECRYPT, null);
|
||||
cipherInputStream = new CipherInputStream(data, cipher.getRaw());
|
||||
if (this.isZeroPadding) {
|
||||
final int blockSize = cipher.getBlockSize();
|
||||
if (blockSize > 0) {
|
||||
@ -447,14 +441,12 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化{@link Cipher}为加密或者解密模式
|
||||
* 初始化{@link JceCipher}为加密或者解密模式
|
||||
*
|
||||
* @param mode 模式,见{@link Cipher#ENCRYPT_MODE} 或 {@link Cipher#DECRYPT_MODE}
|
||||
* @param mode 模式,见{@link CipherMode#ENCRYPT} 或 {@link CipherMode#DECRYPT}
|
||||
* @return {@link Cipher}
|
||||
* @throws InvalidKeyException 无效key
|
||||
* @throws InvalidAlgorithmParameterException 无效算法
|
||||
*/
|
||||
private Cipher initMode(final int mode, final byte[] salt) throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
private JceCipher initMode(final CipherMode mode, final byte[] salt) {
|
||||
SecretKey secretKey = this.secretKey;
|
||||
if (null != salt) {
|
||||
// /issues#I6YWWD,提供OpenSSL格式兼容支持
|
||||
@ -462,7 +454,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
|
||||
final byte[][] keyAndIV = OpenSSLSaltParser.ofMd5(32, algorithm)
|
||||
.getKeyAndIV(secretKey.getEncoded(), salt);
|
||||
secretKey = KeyUtil.generateKey(algorithm, keyAndIV[0]);
|
||||
if(ArrayUtil.isNotEmpty(keyAndIV[1])){
|
||||
if (ArrayUtil.isNotEmpty(keyAndIV[1])) {
|
||||
setAlgorithmParameterSpec(new IvParameterSpec(keyAndIV[1]));
|
||||
}
|
||||
}
|
||||
@ -470,7 +462,7 @@ public class SymmetricCrypto implements SymmetricEncryptor, SymmetricDecryptor,
|
||||
final JceCipher cipher = this.cipher;
|
||||
cipher.init(mode,
|
||||
new JceCipher.JceParameters(secretKey, this.algorithmParameterSpec, this.random));
|
||||
return cipher.getRaw();
|
||||
return cipher;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,28 @@
|
||||
package org.dromara.hutool.crypto.bc;
|
||||
|
||||
import org.bouncycastle.crypto.BufferedBlockCipher;
|
||||
import org.bouncycastle.crypto.DefaultBufferedBlockCipher;
|
||||
import org.bouncycastle.crypto.engines.SM4Engine;
|
||||
import org.bouncycastle.crypto.modes.CBCBlockCipher;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.dromara.hutool.core.util.ByteUtil;
|
||||
import org.dromara.hutool.crypto.CipherMode;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class BCCipherTest {
|
||||
@Test
|
||||
void sm4Test() {
|
||||
final byte[] data = ByteUtil.toUtf8Bytes("我是测试Hutool的字符串00");
|
||||
|
||||
final BufferedBlockCipher blockCipher = new DefaultBufferedBlockCipher(CBCBlockCipher.newInstance(new SM4Engine()));
|
||||
final BCCipher bcCipher = new BCCipher(blockCipher);
|
||||
bcCipher.init(CipherMode.ENCRYPT, new BCCipher.BCParameters(new KeyParameter(ByteUtil.toUtf8Bytes("1234567890000000"))));
|
||||
final byte[] encryptData = bcCipher.processFinal(data);
|
||||
|
||||
bcCipher.init(CipherMode.DECRYPT, new BCCipher.BCParameters(new KeyParameter(ByteUtil.toUtf8Bytes("1234567890000000"))));
|
||||
final byte[] decryptData = bcCipher.processFinal(encryptData);
|
||||
|
||||
Assertions.assertArrayEquals(data, decryptData);
|
||||
}
|
||||
}
|
@ -135,9 +135,9 @@ public class SymmetricTest {
|
||||
final AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, "0123456789ABHAEQ".getBytes(), "DYgjCEIMVrj2W9xN".getBytes());
|
||||
|
||||
// 加密为16进制表示
|
||||
aes.setMode(CipherMode.encrypt);
|
||||
aes.setMode(CipherMode.ENCRYPT);
|
||||
final String randomData = aes.updateHex(content.getBytes(StandardCharsets.UTF_8));
|
||||
aes.setMode(CipherMode.encrypt);
|
||||
aes.setMode(CipherMode.ENCRYPT);
|
||||
final String randomData2 = aes.updateHex(content.getBytes(StandardCharsets.UTF_8));
|
||||
Assertions.assertEquals(randomData2, randomData);
|
||||
Assertions.assertEquals(randomData, "cd0e3a249eaf0ed80c330338508898c4");
|
||||
|
Loading…
x
Reference in New Issue
Block a user