This commit is contained in:
Looly 2024-01-08 23:41:58 +08:00
parent 46febc3d05
commit fb608eac61
13 changed files with 195 additions and 203 deletions

View File

@ -13,7 +13,7 @@
package org.dromara.hutool.crypto;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.lang.wrapper.Wrapper;
import org.dromara.hutool.core.lang.wrapper.SimpleWrapper;
import javax.crypto.ShortBufferException;
import java.security.InvalidAlgorithmParameterException;
@ -27,9 +27,7 @@ import java.security.spec.AlgorithmParameterSpec;
*
* @author Looly
*/
public class JceCipher implements Cipher, Wrapper<javax.crypto.Cipher> {
private final javax.crypto.Cipher cipher;
public class JceCipher extends SimpleWrapper<javax.crypto.Cipher> implements Cipher {
/**
* 构造
@ -43,30 +41,25 @@ public class JceCipher implements Cipher, Wrapper<javax.crypto.Cipher> {
/**
* 构造
*
* @param cipher {@link javax.crypto.Cipher}
* @param cipher {@link javax.crypto.Cipher}可以通过{@link javax.crypto.Cipher#getInstance(String)}创建
*/
public JceCipher(final javax.crypto.Cipher cipher) {
this.cipher = Assert.notNull(cipher);
}
@Override
public javax.crypto.Cipher getRaw() {
return this.cipher;
super(Assert.notNull(cipher));
}
@Override
public String getAlgorithmName() {
return this.cipher.getAlgorithm();
return getRaw().getAlgorithm();
}
@Override
public int getBlockSize() {
return this.cipher.getBlockSize();
return getRaw().getBlockSize();
}
@Override
public int getOutputSize(final int len) {
return this.cipher.getOutputSize(len);
return getRaw().getOutputSize(len);
}
@Override
@ -89,7 +82,7 @@ public class JceCipher implements Cipher, Wrapper<javax.crypto.Cipher> {
* @throws InvalidKeyException 无效key
*/
public void init(final int mode, final JceParameters jceParameters) throws InvalidAlgorithmParameterException, InvalidKeyException {
final javax.crypto.Cipher cipher = this.cipher;
final javax.crypto.Cipher cipher = getRaw();
if (null != jceParameters.parameterSpec) {
if (null != jceParameters.random) {
cipher.init(mode, jceParameters.key, jceParameters.parameterSpec, jceParameters.random);
@ -108,7 +101,7 @@ public class JceCipher implements Cipher, Wrapper<javax.crypto.Cipher> {
@Override
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);
return getRaw().update(in, inOff, len, out, outOff);
} catch (final ShortBufferException e) {
throw new CryptoException(e);
}
@ -117,7 +110,7 @@ public class JceCipher implements Cipher, Wrapper<javax.crypto.Cipher> {
@Override
public int doFinal(final byte[] out, final int outOff) {
try {
return this.cipher.doFinal(out, outOff);
return getRaw().doFinal(out, outOff);
} catch (final Exception e) {
throw new CryptoException(e);
}
@ -126,7 +119,7 @@ public class JceCipher implements Cipher, Wrapper<javax.crypto.Cipher> {
@Override
public byte[] processFinal(final byte[] data) {
try {
return this.cipher.doFinal(data);
return getRaw().doFinal(data);
} catch (final Exception e) {
throw new CryptoException(e);
}

View File

@ -12,10 +12,7 @@
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.*;
import org.bouncycastle.crypto.modes.AEADBlockCipher;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.lang.wrapper.Wrapper;
@ -23,10 +20,13 @@ import org.dromara.hutool.crypto.Cipher;
import org.dromara.hutool.crypto.CipherMode;
import org.dromara.hutool.crypto.CryptoException;
import java.util.Arrays;
/**
* 基于BouncyCastle库封装的加密解密实现包装包括
* <ul>
* <li>{@link BufferedBlockCipher}</li>
* <li>{@link BlockCipher}</li>
* <li>{@link StreamCipher}</li>
* <li>{@link AEADBlockCipher}</li>
* </ul>
@ -38,7 +38,11 @@ public class BCCipher implements Cipher, Wrapper<Object> {
/**
* {@link BufferedBlockCipher}块加密包含enginemodepadding
*/
private BufferedBlockCipher blockCipher;
private BufferedBlockCipher bufferedBlockCipher;
/**
* {@link BlockCipher} 块加密一般用于AES等对称加密
*/
private BlockCipher blockCipher;
/**
* {@link AEADBlockCipher}, 关联数据的认证加密(Authenticated Encryption with Associated Data)
*/
@ -53,9 +57,18 @@ public class BCCipher implements Cipher, Wrapper<Object> {
/**
* 构造
*
* @param blockCipher {@link BufferedBlockCipher}
* @param bufferedBlockCipher {@link BufferedBlockCipher}
*/
public BCCipher(final BufferedBlockCipher blockCipher) {
public BCCipher(final BufferedBlockCipher bufferedBlockCipher) {
this.bufferedBlockCipher = Assert.notNull(bufferedBlockCipher);
}
/**
* 构造
*
* @param blockCipher {@link BlockCipher}
*/
public BCCipher(final BlockCipher blockCipher) {
this.blockCipher = Assert.notNull(blockCipher);
}
@ -80,6 +93,9 @@ public class BCCipher implements Cipher, Wrapper<Object> {
@Override
public Object getRaw() {
if (null != this.bufferedBlockCipher) {
return this.bufferedBlockCipher;
}
if (null != this.blockCipher) {
return this.blockCipher;
}
@ -91,8 +107,11 @@ public class BCCipher implements Cipher, Wrapper<Object> {
@Override
public String getAlgorithmName() {
if (null != this.bufferedBlockCipher) {
return this.bufferedBlockCipher.getUnderlyingCipher().getAlgorithmName();
}
if (null != this.blockCipher) {
return this.blockCipher.getUnderlyingCipher().getAlgorithmName();
return this.blockCipher.getAlgorithmName();
}
if (null != this.aeadBlockCipher) {
return this.aeadBlockCipher.getUnderlyingCipher().getAlgorithmName();
@ -102,6 +121,9 @@ public class BCCipher implements Cipher, Wrapper<Object> {
@Override
public int getBlockSize() {
if (null != this.bufferedBlockCipher) {
return this.bufferedBlockCipher.getBlockSize();
}
if (null != this.blockCipher) {
return this.blockCipher.getBlockSize();
}
@ -115,21 +137,34 @@ public class BCCipher implements Cipher, Wrapper<Object> {
public void init(final CipherMode mode, final Parameters parameters) {
Assert.isInstanceOf(BCParameters.class, parameters, "Only support BCParameters!");
if (null != this.blockCipher) {
this.blockCipher.init(mode == CipherMode.ENCRYPT, ((BCParameters) parameters).parameters);
final boolean forEncryption;
if (mode == CipherMode.ENCRYPT) {
forEncryption = true;
} else if (mode == CipherMode.DECRYPT) {
forEncryption = false;
} else {
throw new IllegalArgumentException("Invalid mode: " + mode.name());
}
final CipherParameters cipherParameters = ((BCParameters) parameters).parameters;
if (null != this.bufferedBlockCipher) {
this.bufferedBlockCipher.init(forEncryption, cipherParameters);
return;
}
if (null != this.blockCipher) {
this.blockCipher.init(forEncryption, cipherParameters);
}
if (null != this.aeadBlockCipher) {
this.aeadBlockCipher.init(mode == CipherMode.ENCRYPT, ((BCParameters) parameters).parameters);
this.aeadBlockCipher.init(forEncryption, cipherParameters);
return;
}
this.streamCipher.init(mode == CipherMode.ENCRYPT, ((BCParameters) parameters).parameters);
this.streamCipher.init(forEncryption, cipherParameters);
}
@Override
public int getOutputSize(final int len) {
if (null != this.blockCipher) {
return this.blockCipher.getOutputSize(len);
if (null != this.bufferedBlockCipher) {
return this.bufferedBlockCipher.getOutputSize(len);
}
if (null != this.aeadBlockCipher) {
return this.aeadBlockCipher.getOutputSize(len);
@ -139,8 +174,17 @@ public class BCCipher implements Cipher, Wrapper<Object> {
@Override
public int process(final byte[] in, final int inOff, final int len, final byte[] out, final int outOff) {
if (null != this.bufferedBlockCipher) {
return this.bufferedBlockCipher.processBytes(in, inOff, len, out, outOff);
}
if (null != this.blockCipher) {
return this.blockCipher.processBytes(in, inOff, len, out, outOff);
final byte[] subBytes;
if (inOff + len < in.length) {
subBytes = Arrays.copyOf(in, inOff + len);
} else {
subBytes = in;
}
return this.blockCipher.processBlock(subBytes, inOff, out, outOff);
}
if (null != this.aeadBlockCipher) {
return this.aeadBlockCipher.processBytes(in, inOff, len, out, outOff);
@ -150,9 +194,9 @@ public class BCCipher implements Cipher, Wrapper<Object> {
@Override
public int doFinal(final byte[] out, final int outOff) {
if (null != this.blockCipher) {
if (null != this.bufferedBlockCipher) {
try {
return this.blockCipher.doFinal(out, outOff);
return this.bufferedBlockCipher.doFinal(out, outOff);
} catch (final InvalidCipherTextException e) {
throw new CryptoException(e);
}

View File

@ -545,7 +545,7 @@ public class BCrypt {
if (hashed_bytes.length != try_bytes.length) {
return false;
}
byte ret = 0;
int ret = 0;
for (int i = 0; i < try_bytes.length; i++)
ret |= hashed_bytes[i] ^ try_bytes[i];
return ret == 0;

View File

@ -19,11 +19,29 @@ package org.dromara.hutool.crypto.digest;
* @author Looly
*/
public enum DigestAlgorithm {
/**
* MD2
*/
MD2("MD2"),
/**
* MD5
*/
MD5("MD5"),
/**
* SHA-1
*/
SHA1("SHA-1"),
/**
* SHA-256
*/
SHA256("SHA-256"),
/**
* SHA-384
*/
SHA384("SHA-384"),
/**
* SHA-512
*/
SHA512("SHA-512");
private final String value;

View File

@ -27,7 +27,7 @@ import java.security.Provider;
public class DigesterFactory {
/**
* 创建工厂
* 创建工厂只使用JDK提供的算法
*
* @param algorithm 算法
* @return DigesterFactory

View File

@ -75,16 +75,4 @@ public class BCHMacEngine extends BCMacEngine {
super(mac, params);
}
// ------------------------------------------------------------------------------------------- Constructor end
/**
* 初始化
*
* @param digest 摘要算法
* @param params 参数例如密钥可以用{@link KeyParameter}
* @return this
* @see #init(Mac, CipherParameters)
*/
public BCHMacEngine init(final Digest digest, final CipherParameters params) {
return (BCHMacEngine) init(new HMac(digest), params);
}
}

View File

@ -15,6 +15,7 @@ package org.dromara.hutool.crypto.digest.mac;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.dromara.hutool.core.lang.wrapper.SimpleWrapper;
/**
* BouncyCastle的MAC算法实现引擎使用{@link Mac} 实现摘要<br>
@ -23,9 +24,7 @@ import org.bouncycastle.crypto.params.KeyParameter;
* @author Looly
* @since 5.8.0
*/
public class BCMacEngine implements MacEngine {
private Mac mac;
public class BCMacEngine extends SimpleWrapper<Mac> implements MacEngine {
// ------------------------------------------------------------------------------------------- Constructor start
/**
@ -36,57 +35,46 @@ public class BCMacEngine implements MacEngine {
* @since 5.8.0
*/
public BCMacEngine(final Mac mac, final CipherParameters params) {
init(mac, params);
super(initMac(mac, params));
}
// ------------------------------------------------------------------------------------------- Constructor end
@Override
public void update(final byte[] in, final int inOff, final int len) {
getRaw().update(in, inOff, len);
}
@Override
public byte[] doFinal() {
final byte[] result = new byte[getMacLength()];
getRaw().doFinal(result, 0);
return result;
}
@Override
public void reset() {
getRaw().reset();
}
@Override
public int getMacLength() {
return getRaw().getMacSize();
}
@Override
public String getAlgorithm() {
return getRaw().getAlgorithmName();
}
/**
* 初始化
*
* @param mac 摘要算法
* @param params 参数例如密钥可以用{@link KeyParameter}
* @return this
* @since 5.8.0
*/
public BCMacEngine init(final Mac mac, final CipherParameters params) {
private static Mac initMac(final Mac mac, final CipherParameters params) {
mac.init(params);
this.mac = mac;
return this;
}
/**
* 获得 {@link Mac}
*
* @return {@link Mac}
*/
public Mac ipgetMac() {
return mac;
}
@Override
public void update(final byte[] in, final int inOff, final int len) {
this.mac.update(in, inOff, len);
}
@Override
public byte[] doFinal() {
final byte[] result = new byte[getMacLength()];
this.mac.doFinal(result, 0);
return result;
}
@Override
public void reset() {
this.mac.reset();
}
@Override
public int getMacLength() {
return mac.getMacSize();
}
@Override
public String getAlgorithm() {
return this.mac.getAlgorithmName();
}
}

View File

@ -15,7 +15,6 @@ package org.dromara.hutool.crypto.digest.mac;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.macs.CBCBlockCipherMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
@ -97,16 +96,4 @@ public class CBCBlockCipherMacEngine extends BCMacEngine {
public CBCBlockCipherMacEngine(final CBCBlockCipherMac mac, final CipherParameters params) {
super(mac, params);
}
/**
* 初始化
*
* @param cipher {@link BlockCipher}
* @param params 参数例如密钥可以用{@link KeyParameter}
* @return this
* @see #init(Mac, CipherParameters)
*/
public CBCBlockCipherMacEngine init(final BlockCipher cipher, final CipherParameters params) {
return (CBCBlockCipherMacEngine) init(new CBCBlockCipherMac(cipher), params);
}
}

View File

@ -12,6 +12,7 @@
package org.dromara.hutool.crypto.digest.mac;
import org.dromara.hutool.core.lang.wrapper.SimpleWrapper;
import org.dromara.hutool.crypto.CryptoException;
import org.dromara.hutool.crypto.KeyUtil;
import org.dromara.hutool.crypto.SecureUtil;
@ -23,18 +24,15 @@ import java.security.Key;
import java.security.spec.AlgorithmParameterSpec;
/**
* 默认的HMAC算法实现引擎使用{@link Mac} 实现摘要<br>
* JDK提供的的MAC算法实现引擎使用{@link Mac} 实现摘要<br>
* 当引入BouncyCastle库时自动使用其作为Provider
*
* @author Looly
* @since 4.5.13
*/
public class DefaultHMacEngine implements MacEngine {
private Mac mac;
public class JCEMacEngine extends SimpleWrapper<Mac> implements MacEngine {
// region ----- Constructor
/**
* 构造
*
@ -42,7 +40,7 @@ public class DefaultHMacEngine implements MacEngine {
* @param key 密钥
* @since 4.5.13
*/
public DefaultHMacEngine(final String algorithm, final byte[] key) {
public JCEMacEngine(final String algorithm, final byte[] key) {
this(algorithm, (null == key) ? null : new SecretKeySpec(key, algorithm));
}
@ -53,7 +51,7 @@ public class DefaultHMacEngine implements MacEngine {
* @param key 密钥
* @since 4.5.13
*/
public DefaultHMacEngine(final String algorithm, final Key key) {
public JCEMacEngine(final String algorithm, final Key key) {
this(algorithm, key, null);
}
@ -65,34 +63,39 @@ public class DefaultHMacEngine implements MacEngine {
* @param spec {@link AlgorithmParameterSpec}
* @since 5.7.12
*/
public DefaultHMacEngine(final String algorithm, final Key key, final AlgorithmParameterSpec spec) {
init(algorithm, key, spec);
public JCEMacEngine(final String algorithm, final Key key, final AlgorithmParameterSpec spec) {
super(initMac(algorithm, key, spec));
}
// endregion
// region ----- init
/**
* 初始化
*
* @param algorithm 算法
* @param key 密钥
* @return this
*/
public DefaultHMacEngine init(final String algorithm, final byte[] key) {
return init(algorithm, (null == key) ? null : new SecretKeySpec(key, algorithm));
@Override
public void update(final byte[] in) {
getRaw().update(in);
}
/**
* 初始化
*
* @param algorithm 算法
* @param key 密钥 {@link SecretKey}
* @return this
* @throws CryptoException Cause by IOException
*/
public DefaultHMacEngine init(final String algorithm, final Key key) {
return init(algorithm, key, null);
@Override
public void update(final byte[] in, final int inOff, final int len) {
getRaw().update(in, inOff, len);
}
@Override
public byte[] doFinal() {
return getRaw().doFinal();
}
@Override
public void reset() {
getRaw().reset();
}
@Override
public int getMacLength() {
return getRaw().getMacLength();
}
@Override
public String getAlgorithm() {
return getRaw().getAlgorithm();
}
/**
@ -103,9 +106,9 @@ public class DefaultHMacEngine implements MacEngine {
* @param spec {@link AlgorithmParameterSpec}
* @return this
* @throws CryptoException Cause by IOException
* @since 5.7.12
*/
public DefaultHMacEngine init(final String algorithm, Key key, final AlgorithmParameterSpec spec) {
private static Mac initMac(final String algorithm, Key key, final AlgorithmParameterSpec spec) {
final Mac mac;
try {
mac = SecureUtil.createMac(algorithm);
if (null == key) {
@ -119,46 +122,6 @@ public class DefaultHMacEngine implements MacEngine {
} catch (final Exception e) {
throw new CryptoException(e);
}
return this;
}
// endregion
/**
* 获得 {@link Mac}
*
* @return {@link Mac}
*/
public Mac getMac() {
return mac;
}
@Override
public void update(final byte[] in) {
this.mac.update(in);
}
@Override
public void update(final byte[] in, final int inOff, final int len) {
this.mac.update(in, inOff, len);
}
@Override
public byte[] doFinal() {
return this.mac.doFinal();
}
@Override
public void reset() {
this.mac.reset();
}
@Override
public int getMacLength() {
return mac.getMacLength();
}
@Override
public String getAlgorithm() {
return this.mac.getAlgorithm();
}
}

View File

@ -50,6 +50,6 @@ public class MacEngineFactory {
// HmacSM3算法是BC库实现的忽略加盐
return SmUtil.createHmacSm3Engine(key.getEncoded());
}
return new DefaultHMacEngine(algorithm, key, spec);
return new JCEMacEngine(algorithm, key, spec);
}
}

View File

@ -22,6 +22,21 @@
* HMAC 可以与任何迭代散列函数捆绑使用MD5 SHA-1 就是这种散列函数HMAC 还可以使用一个用于计算和确认消息鉴别值的密钥
* </p>
*
* <pre>
* MacEngineFactory
* ||(创建)
* MacEngine----------------包装-----------------> Mac
* _____|_______________ |
* / \ HMac
* JCEMacEngine BCMacEngine
* / \
* BCHMacEngine CBCBlockCipherMacEngine
* |
* SM4MacEngine
* </pre>
*
* 通过MacEngine封装支持了BouncyCastle和JCE实现的一些MAC算法通过MacEngineFactory自动根据算法名称创建对应对象
*
* @author Looly
* @since 4.5.13
*/

View File

@ -21,6 +21,12 @@
* Truncate是一个函数就是怎么截取加密后的串并取加密后串的哪些字段组成一个数字
* </pre>
*
* 实现包括
* <ul>
* <li>HMAC-based one-time passwords (HOTP) 基于HMAC算法一次性密码生成器</li>
* <li>time-based one-time passwords (TOTP) 基于时间戳算法的一次性密码生成器</li>
* </ul>
*
* @author looly
*/
package org.dromara.hutool.crypto.digest.otp;

View File

@ -14,7 +14,7 @@ package org.dromara.hutool.db.ds;
import org.dromara.hutool.core.exception.CloneException;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.lang.wrapper.Wrapper;
import org.dromara.hutool.core.lang.wrapper.SimpleWrapper;
import javax.sql.DataSource;
import java.io.Closeable;
@ -34,9 +34,8 @@ import java.util.logging.Logger;
* @author looly
* @since 4.3.2
*/
public class DSWrapper implements Wrapper<DataSource>, DataSource, Closeable, Cloneable {
public class DSWrapper extends SimpleWrapper<DataSource> implements DataSource, Closeable, Cloneable {
private final DataSource ds;
private final String driver;
/**
@ -57,7 +56,7 @@ public class DSWrapper implements Wrapper<DataSource>, DataSource, Closeable, Cl
* @param driver 数据库驱动类名
*/
public DSWrapper(final DataSource ds, final String driver) {
this.ds = ds;
super(ds);
this.driver = driver;
}
@ -70,65 +69,56 @@ public class DSWrapper implements Wrapper<DataSource>, DataSource, Closeable, Cl
return this.driver;
}
/**
* 获取原始的数据源
*
* @return 原始数据源
*/
@Override
public DataSource getRaw() {
return this.ds;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return ds.getLogWriter();
return getRaw().getLogWriter();
}
@Override
public void setLogWriter(final PrintWriter out) throws SQLException {
ds.setLogWriter(out);
getRaw().setLogWriter(out);
}
@Override
public void setLoginTimeout(final int seconds) throws SQLException {
ds.setLoginTimeout(seconds);
getRaw().setLoginTimeout(seconds);
}
@Override
public int getLoginTimeout() throws SQLException {
return ds.getLoginTimeout();
return getRaw().getLoginTimeout();
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return ds.getParentLogger();
return getRaw().getParentLogger();
}
@Override
public <T> T unwrap(final Class<T> iface) throws SQLException {
return ds.unwrap(iface);
return getRaw().unwrap(iface);
}
@Override
public boolean isWrapperFor(final Class<?> iface) throws SQLException {
return ds.isWrapperFor(iface);
return getRaw().isWrapperFor(iface);
}
@Override
public Connection getConnection() throws SQLException {
return ds.getConnection();
return getRaw().getConnection();
}
@Override
public Connection getConnection(final String username, final String password) throws SQLException {
return ds.getConnection(username, password);
return getRaw().getConnection(username, password);
}
@Override
public void close() {
if (this.ds instanceof AutoCloseable) {
IoUtil.closeQuietly((AutoCloseable) this.ds);
final DataSource ds = getRaw();
if (ds instanceof AutoCloseable) {
IoUtil.closeQuietly((AutoCloseable) ds);
}
}