This commit is contained in:
Looly 2023-04-12 17:23:09 +08:00
parent a96a95c988
commit a7c18e81f6
38 changed files with 426 additions and 175 deletions

View File

@ -140,15 +140,35 @@ public class TextSimilarity {
/**
* 求公共子串采用动态规划算法 其不要求所求得的字符在所给的字符串中是连续的
* 2023-04-06 优化堆内存占用此处不需要matrix[m][n]的完整矩阵仅需右下角值
*
* @param strA 字符串1
* @param strB 字符串2
* @return 公共子串
*/
private static int longestCommonSubstringLength(final String strA, final String strB) {
public static int longestCommonSubstringLength(final String strA, final String strB) {
final int m = strA.length();
final int n = strB.length();
return generateMatrix(strA, strB)[m][n];
// 初始化矩阵数据,matrix[0][0]的值为0 如果字符数组chars_strA和chars_strB的对应位相同则matrix[i][j]的值为左上角的值加1
// 否则matrix[i][j]的值等于左上方最近两个位置的较大值 矩阵中其余各点的值为0.
int[] lastLine = new int[n + 1];
int[] currLine = new int[n + 1];
int[] temp;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (strA.charAt(i - 1) == strB.charAt(j - 1)) {
currLine[j] = lastLine[j-1] + 1;
} else {
currLine[j] = Math.max(currLine[j-1], lastLine[j]);
}
}
temp = lastLine;
lastLine = currLine;
currLine = temp;
}
return lastLine[n];
}
/**

View File

@ -1,12 +1,15 @@
package org.dromara.hutool.core.text;
import org.dromara.hutool.core.lang.Console;
import org.dromara.hutool.core.util.RandomUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
/**
* 文本相似度计算工具类单元测试
* @author looly
*
* @author looly
*/
public class TextSimilarityTest {
@ -35,8 +38,20 @@ public class TextSimilarityTest {
}
@Test
public void similarTest(){
public void similarTest() {
final double abd = TextSimilarity.similar("abd", "1111");
Assertions.assertEquals(0, abd, 1);
}
@Test
@Disabled
void longestCommonSubstringLengthTest() {
// https://github.com/dromara/hutool/issues/3045
final String strCommon = RandomUtil.randomString(1024 * 32);
final String strA = RandomUtil.randomString(1024 * 32) + strCommon;
final String strB = RandomUtil.randomString(1024 * 32) + strCommon;
final int i = TextSimilarity.longestCommonSubstringLength(strA, strB);
Console.log(i);
}
}

View File

@ -1,58 +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:
* http://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 java.security.Provider;
/**
* 全局单例的 org.bouncycastle.jce.provider.BouncyCastleProvider 对象
*
* @author looly
*/
public enum GlobalBouncyCastleProvider {
/**
* 单例对象
*/
INSTANCE;
private Provider provider;
private static boolean useBouncyCastle = true;
GlobalBouncyCastleProvider() {
try {
this.provider = ProviderFactory.createBouncyCastleProvider();
} catch (final NoClassDefFoundError | NoSuchMethodError e) {
// ignore
}
}
/**
* 获取{@link Provider}
*
* @return {@link Provider}
*/
public Provider getProvider() {
return useBouncyCastle ? this.provider : null;
}
/**
* 设置是否使用Bouncy Castle库<br>
* 如果设置为false表示强制关闭Bouncy Castle而使用JDK
*
* @param isUseBouncyCastle 是否使用BouncyCastle库
* @since 4.5.2
*/
public static void setUseBouncyCastle(final boolean isUseBouncyCastle) {
useBouncyCastle = isUseBouncyCastle;
}
}

View File

@ -21,6 +21,9 @@ import org.dromara.hutool.core.util.CharUtil;
import org.dromara.hutool.core.util.RandomUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.crypto.asymmetric.AsymmetricAlgorithm;
import org.dromara.hutool.crypto.bc.BCUtil;
import org.dromara.hutool.crypto.bc.SmUtil;
import org.dromara.hutool.crypto.provider.GlobalProviderFactory;
import org.dromara.hutool.crypto.symmetric.SymmetricAlgorithm;
import javax.crypto.KeyGenerator;
@ -553,7 +556,7 @@ public class KeyUtil {
* @since 4.4.3
*/
public static KeyPairGenerator getKeyPairGenerator(final String algorithm) {
final Provider provider = GlobalBouncyCastleProvider.INSTANCE.getProvider();
final Provider provider = GlobalProviderFactory.getProvider();
final KeyPairGenerator keyPairGen;
try {
@ -574,7 +577,7 @@ public class KeyUtil {
* @since 4.4.4
*/
public static KeyFactory getKeyFactory(final String algorithm) {
final Provider provider = GlobalBouncyCastleProvider.INSTANCE.getProvider();
final Provider provider = GlobalProviderFactory.getProvider();
final KeyFactory keyFactory;
try {
@ -595,7 +598,7 @@ public class KeyUtil {
* @since 4.5.2
*/
public static SecretKeyFactory getSecretKeyFactory(final String algorithm) {
final Provider provider = GlobalBouncyCastleProvider.INSTANCE.getProvider();
final Provider provider = GlobalProviderFactory.getProvider();
final SecretKeyFactory keyFactory;
try {
@ -616,7 +619,7 @@ public class KeyUtil {
* @since 4.5.2
*/
public static KeyGenerator getKeyGenerator(final String algorithm) {
final Provider provider = GlobalBouncyCastleProvider.INSTANCE.getProvider();
final Provider provider = GlobalProviderFactory.getProvider();
final KeyGenerator generator;
try {
@ -773,7 +776,7 @@ public class KeyUtil {
* @return {@link KeyStore}
*/
public static KeyStore getKeyStore(final String type) {
final Provider provider = GlobalBouncyCastleProvider.INSTANCE.getProvider();
final Provider provider = GlobalProviderFactory.getProvider();
try {
return null == provider ? KeyStore.getInstance(type) : KeyStore.getInstance(type, provider);
} catch (final KeyStoreException e) {
@ -923,7 +926,7 @@ public class KeyUtil {
* @since 4.5.0
*/
public static CertificateFactory getCertificateFactory(final String type) {
final Provider provider = GlobalBouncyCastleProvider.INSTANCE.getProvider();
final Provider provider = GlobalProviderFactory.getProvider();
final CertificateFactory factory;
try {

View File

@ -24,6 +24,7 @@ import org.dromara.hutool.crypto.digest.Digester;
import org.dromara.hutool.crypto.digest.HMac;
import org.dromara.hutool.crypto.digest.HmacAlgorithm;
import org.dromara.hutool.crypto.digest.MD5;
import org.dromara.hutool.crypto.provider.GlobalProviderFactory;
import org.dromara.hutool.crypto.symmetric.AES;
import org.dromara.hutool.crypto.symmetric.DES;
import org.dromara.hutool.crypto.symmetric.DESede;
@ -536,7 +537,7 @@ public class SecureUtil {
* @since 4.5.2
*/
public static Cipher createCipher(final String algorithm) {
final Provider provider = GlobalBouncyCastleProvider.INSTANCE.getProvider();
final Provider provider = GlobalProviderFactory.getProvider();
final Cipher cipher;
try {
@ -556,7 +557,7 @@ public class SecureUtil {
* @since 4.5.2
*/
public static MessageDigest createMessageDigest(final String algorithm) {
final Provider provider = GlobalBouncyCastleProvider.INSTANCE.getProvider();
final Provider provider = GlobalProviderFactory.getProvider();
final MessageDigest messageDigest;
try {
@ -576,7 +577,7 @@ public class SecureUtil {
* @since 4.5.13
*/
public static Mac createMac(final String algorithm) {
final Provider provider = GlobalBouncyCastleProvider.INSTANCE.getProvider();
final Provider provider = GlobalProviderFactory.getProvider();
final Mac mac;
try {
@ -604,7 +605,7 @@ public class SecureUtil {
* @since 4.5.2
*/
public static void disableBouncyCastle() {
GlobalBouncyCastleProvider.setUseBouncyCastle(false);
GlobalProviderFactory.setUseCustomProvider(false);
}
/**

View File

@ -19,6 +19,7 @@ import org.dromara.hutool.crypto.asymmetric.Sign;
import org.dromara.hutool.crypto.asymmetric.SignAlgorithm;
import org.dromara.hutool.crypto.digest.DigestAlgorithm;
import org.dromara.hutool.crypto.digest.Digester;
import org.dromara.hutool.crypto.provider.GlobalProviderFactory;
import org.dromara.hutool.crypto.symmetric.SymmetricCrypto;
import java.security.NoSuchAlgorithmException;
@ -59,7 +60,7 @@ public class SignUtil {
* @since 5.7.0
*/
public static Signature createSignature(final String algorithm) {
final Provider provider = GlobalBouncyCastleProvider.INSTANCE.getProvider();
final Provider provider = GlobalProviderFactory.getProvider();
final Signature signature;
try {

View File

@ -13,7 +13,7 @@
package org.dromara.hutool.crypto.asymmetric;
import org.dromara.hutool.crypto.CryptoException;
import org.dromara.hutool.crypto.GlobalBouncyCastleProvider;
import org.dromara.hutool.crypto.provider.GlobalProviderFactory;
import org.dromara.hutool.crypto.KeyUtil;
import java.math.BigInteger;
@ -169,7 +169,7 @@ public class RSA extends AsymmetricCrypto {
@Override
public byte[] encrypt(final byte[] data, final KeyType keyType) {
// 在非使用BC库情况下blockSize使用默认的算法
if (this.encryptBlockSize < 0 && null == GlobalBouncyCastleProvider.INSTANCE.getProvider()) {
if (this.encryptBlockSize < 0 && null == GlobalProviderFactory.getProvider()) {
// 加密数据长度 <= 模长-11
this.encryptBlockSize = ((RSAKey) getKeyByType(keyType)).getModulus().bitLength() / 8 - 11;
}
@ -179,7 +179,7 @@ public class RSA extends AsymmetricCrypto {
@Override
public byte[] decrypt(final byte[] bytes, final KeyType keyType) {
// 在非使用BC库情况下blockSize使用默认的算法
if (this.decryptBlockSize < 0 && null == GlobalBouncyCastleProvider.INSTANCE.getProvider()) {
if (this.decryptBlockSize < 0 && null == GlobalProviderFactory.getProvider()) {
// 加密数据长度 <= 模长-11
this.decryptBlockSize = ((RSAKey) getKeyByType(keyType)).getModulus().bitLength() / 8;
}

View File

@ -14,9 +14,9 @@ package org.dromara.hutool.crypto.asymmetric;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.codec.HexUtil;
import org.dromara.hutool.crypto.BCUtil;
import org.dromara.hutool.crypto.bc.BCUtil;
import org.dromara.hutool.crypto.CryptoException;
import org.dromara.hutool.crypto.ECKeyUtil;
import org.dromara.hutool.crypto.bc.ECKeyUtil;
import org.dromara.hutool.crypto.SecureUtil;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Digest;
@ -33,7 +33,7 @@ import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.crypto.signers.StandardDSAEncoding;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.util.encoders.Hex;
import org.dromara.hutool.crypto.SmUtil;
import org.dromara.hutool.crypto.bc.SmUtil;
import java.math.BigInteger;
import java.security.PrivateKey;

View File

@ -10,7 +10,7 @@
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.crypto;
package org.dromara.hutool.crypto.bc;
import org.dromara.hutool.core.io.stream.FastByteArrayOutputStream;
import org.dromara.hutool.core.io.IORuntimeException;
@ -23,6 +23,7 @@ import org.bouncycastle.asn1.BERSequence;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DLSequence;
import org.bouncycastle.asn1.util.ASN1Dump;
import org.dromara.hutool.crypto.CryptoException;
import java.io.IOException;
import java.io.InputStream;

View File

@ -10,7 +10,7 @@
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.crypto;
package org.dromara.hutool.crypto.bc;
import org.dromara.hutool.core.io.IORuntimeException;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
@ -27,6 +27,7 @@ import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.math.ec.ECCurve;
import org.dromara.hutool.crypto.*;
import java.io.IOException;
import java.io.InputStream;

View File

@ -10,7 +10,7 @@
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.crypto;
package org.dromara.hutool.crypto.bc;
import org.dromara.hutool.core.io.IORuntimeException;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
@ -28,6 +28,9 @@ import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.FixedPointCombMultiplier;
import org.bouncycastle.util.BigIntegers;
import org.dromara.hutool.crypto.CryptoException;
import org.dromara.hutool.crypto.KeyUtil;
import org.dromara.hutool.crypto.SecureUtil;
import java.io.IOException;
import java.math.BigInteger;

View File

@ -10,7 +10,7 @@
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.crypto;
package org.dromara.hutool.crypto.bc;
import org.dromara.hutool.core.io.IORuntimeException;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
@ -30,6 +30,8 @@ import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
import org.bouncycastle.pkcs.PKCSException;
import org.dromara.hutool.crypto.CryptoException;
import org.dromara.hutool.crypto.provider.GlobalProviderFactory;
import java.io.IOException;
import java.io.InputStream;
@ -48,7 +50,8 @@ import java.security.PublicKey;
*/
public class OpensslKeyUtil {
private static final JcaPEMKeyConverter pemKeyConverter = new JcaPEMKeyConverter().setProvider(GlobalBouncyCastleProvider.INSTANCE.getProvider());
private static final JcaPEMKeyConverter pemKeyConverter =
new JcaPEMKeyConverter().setProvider(GlobalProviderFactory.getProvider());
/**
* 转换{@link PrivateKeyInfo}{@link PrivateKey}
@ -106,7 +109,8 @@ public class OpensslKeyUtil {
public static PrivateKeyInfo decrypt(final PKCS8EncryptedPrivateKeyInfo pkcs8Info, final char[] password) throws CryptoException {
final InputDecryptorProvider decryptProvider;
try {
decryptProvider = new JceOpenSSLPKCS8DecryptorProviderBuilder().setProvider(GlobalBouncyCastleProvider.INSTANCE.getProvider()).build(password);
decryptProvider = new JceOpenSSLPKCS8DecryptorProviderBuilder()
.setProvider(GlobalProviderFactory.getProvider()).build(password);
return pkcs8Info.decryptPrivateKeyInfo(decryptProvider);
} catch (final OperatorCreationException | PKCSException e) {
throw new CryptoException(e);
@ -124,7 +128,8 @@ public class OpensslKeyUtil {
public static PEMKeyPair decrypt(final PEMEncryptedKeyPair pemEncryptedKeyPair, final char[] password) throws IORuntimeException {
final PEMDecryptorProvider decryptProvider;
try {
decryptProvider = new JcePEMDecryptorProviderBuilder().setProvider(GlobalBouncyCastleProvider.INSTANCE.getProvider()).build(password);
decryptProvider = new JcePEMDecryptorProviderBuilder()
.setProvider(GlobalProviderFactory.getProvider()).build(password);
return pemEncryptedKeyPair.decryptKeyPair(decryptProvider);
} catch (final IOException e) {
throw new IORuntimeException(e);

View File

@ -10,22 +10,18 @@
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.crypto;
package org.dromara.hutool.crypto.bc;
import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemObjectGenerator;
import org.bouncycastle.util.io.pem.PemReader;
import org.bouncycastle.util.io.pem.PemWriter;
import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.crypto.KeyUtil;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.io.*;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
@ -96,7 +92,7 @@ public class PemUtil {
try {
// 尝试DER
return KeyUtil.generatePublicKey("EC", object.getContent());
} catch (Exception e) {
} catch (final Exception ignore) {
// 尝试PKCS#1
return KeyUtil.generatePublicKey("EC", ECKeyUtil.createOpenSSHPublicKeySpec(object.getContent()));
}

View File

@ -10,18 +10,8 @@
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.crypto;
package org.dromara.hutool.crypto.bc;
import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.crypto.asymmetric.SM2;
import org.dromara.hutool.crypto.digest.HMac;
import org.dromara.hutool.crypto.digest.HmacAlgorithm;
import org.dromara.hutool.crypto.digest.SM3;
import org.dromara.hutool.crypto.digest.mac.BCHMacEngine;
import org.dromara.hutool.crypto.digest.mac.MacEngine;
import org.dromara.hutool.crypto.symmetric.SM4;
import org.dromara.hutool.crypto.symmetric.SymmetricCrypto;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.crypto.digests.SM3Digest;
@ -31,6 +21,17 @@ import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.signers.StandardDSAEncoding;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Hex;
import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.crypto.CryptoException;
import org.dromara.hutool.crypto.asymmetric.SM2;
import org.dromara.hutool.crypto.digest.HMac;
import org.dromara.hutool.crypto.digest.HmacAlgorithm;
import org.dromara.hutool.crypto.digest.SM3;
import org.dromara.hutool.crypto.digest.mac.BCHMacEngine;
import org.dromara.hutool.crypto.digest.mac.MacEngine;
import org.dromara.hutool.crypto.symmetric.SM4;
import org.dromara.hutool.crypto.symmetric.SymmetricCrypto;
import java.io.File;
import java.io.IOException;

View File

@ -0,0 +1,19 @@
/*
* 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:
* http://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.
*/
/**
* BouncyCastle库相关工具封装
*
* @author looly
* @since 6.0.0
*/
package org.dromara.hutool.crypto.bc;

View File

@ -12,7 +12,7 @@
package org.dromara.hutool.crypto.digest.mac;
import org.dromara.hutool.crypto.SmUtil;
import org.dromara.hutool.crypto.bc.SmUtil;
import org.dromara.hutool.crypto.digest.HmacAlgorithm;
import java.security.Key;

View File

@ -0,0 +1,30 @@
/*
* 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:
* http://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.provider;
import java.security.Provider;
/**
* {@link org.bouncycastle.jce.provider.BouncyCastleProvider} 工厂类
*
* @author looly
* @since 6.0.0
*/
public class BouncyCastleProviderFactory implements ProviderFactory {
@Override
public Provider create() {
return new org.bouncycastle.jce.provider.BouncyCastleProvider();
}
}

View File

@ -0,0 +1,67 @@
/*
* 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:
* http://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.provider;
import org.dromara.hutool.core.util.ServiceLoaderUtil;
import org.dromara.hutool.crypto.SecureUtil;
import java.security.Provider;
/**
* 全局单例的{@link Provider}对象<br>
* 在此类加载时通过SPI方式查找用户引入的加密库查找对应的{@link Provider}实现然后全局创建唯一的{@link Provider}对象<br>
* 用户依旧可以通过{@link #setUseCustomProvider(boolean)} 方法选择是否使用自定义的Provider
*
* @author looly
*/
public class GlobalProviderFactory {
private static boolean useCustomProvider = true;
private static final Provider provider = _createProvider();
/**
* 获取{@link Provider}
*
* @return {@link Provider}
*/
public static Provider getProvider() {
return useCustomProvider ? provider : null;
}
/**
* 设置是否使用自定义的{@link Provider}<br>
* 如果设置为false表示使用JDK默认的Provider
*
* @param isUseCustomProvider 是否使用自定义{@link Provider}
*/
public static void setUseCustomProvider(final boolean isUseCustomProvider) {
useCustomProvider = isUseCustomProvider;
}
/**
* 通过SPI方式创建{@link Provider}无提供的返回{@code null}
*
* @return {@link Provider} or {@code null}
*/
private static Provider _createProvider() {
final ProviderFactory factory = ServiceLoaderUtil.loadFirstAvailable(ProviderFactory.class);
if (null == factory) {
return null;
}
final Provider provider = factory.create();
// issue#2631@Github
SecureUtil.addProvider(provider);
return provider;
}
}

View File

@ -10,32 +10,24 @@
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.crypto;
package org.dromara.hutool.crypto.provider;
import java.security.Provider;
/**
* Provider对象生产工厂类
*
* <pre>
* 1. 调用{@link #createBouncyCastleProvider()} 用于新建一个org.bouncycastle.jce.provider.BouncyCastleProvider对象
* </pre>
* Provider对象生产工厂类<br>
* 通过SPI方式加载可用的{@link ProviderFactory}并创建对应的{@link Provider}<br>
* spi定义在META-INF/services/org.dromara.hutool.crypto.provider.ProviderFactory
*
* @author looly
* @since 4.2.1
* @since 6.0.0
*/
public class ProviderFactory {
public interface ProviderFactory {
/**
* 创建Bouncy Castle 提供者<br>
* 如果用户未引入bouncycastle库则此方法抛出{@link NoClassDefFoundError} 异常
* 创建{@link Provider}
*
* @return {@link Provider}
*/
public static Provider createBouncyCastleProvider() {
final org.bouncycastle.jce.provider.BouncyCastleProvider provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
// issue#2631@Github
SecureUtil.addProvider(provider);
return provider;
}
Provider create();
}

View File

@ -0,0 +1,29 @@
/*
* 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:
* http://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.
*/
/**
* {@link java.security.Provider}相关封装通过SPI机制提供灵活的Provider注入<br>
* spi定义在META-INF/services/org.dromara.hutool.crypto.provider.ProviderFactory
*
* <pre>
* GlobalProviderFactory单例持有Provider
* ^
* create
* ProviderFactory
* |
* BouncyCastleProviderFactory
* </pre>
*
* @author looly
* @since 6.0.0
*/
package org.dromara.hutool.crypto.provider;

View File

@ -27,6 +27,9 @@ import javax.crypto.spec.IvParameterSpec;
public class ChaCha20 extends SymmetricCrypto {
private static final long serialVersionUID = 1L;
/**
* 算法名称ChaCha20
*/
public static final String ALGORITHM_NAME = "ChaCha20";
/**

View File

@ -31,7 +31,7 @@ import javax.crypto.spec.IvParameterSpec;
public class DES extends SymmetricCrypto {
private static final long serialVersionUID = 1L;
// ------------------------------------------------------------------------- Constrctor start
// region ----- Constructor
/**
* 构造默认DES/ECB/PKCS5Padding使用随机密钥
*/
@ -162,5 +162,5 @@ public class DES extends SymmetricCrypto {
public DES(final String mode, final String padding, final SecretKey key, final IvParameterSpec iv) {
super(StrUtil.format("DES/{}/{}", mode, padding), key, iv);
}
// ------------------------------------------------------------------------- Constrctor end
// endregion
}

View File

@ -35,12 +35,16 @@ import javax.crypto.spec.IvParameterSpec;
* @author Looly
* @since 4.6.8
*/
public class SM4 extends SymmetricCrypto{
public class SM4 extends SymmetricCrypto {
private static final long serialVersionUID = 1L;
/**
* 算法名称SM4
*/
public static final String ALGORITHM_NAME = "SM4";
//------------------------------------------------------------------------- Constrctor start
// region ----- Constructor
/**
* 构造使用随机密钥
*/
@ -182,5 +186,5 @@ public class SM4 extends SymmetricCrypto{
public SM4(final String mode, final String padding, final SecretKey key, final IvParameterSpec iv) {
super(StrUtil.format("SM4/{}/{}", mode, padding), key, iv);
}
//------------------------------------------------------------------------- Constrctor end
// endregion
}

View File

@ -17,27 +17,50 @@ package org.dromara.hutool.crypto.symmetric;
* see: https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#KeyGenerator
*
* @author Looly
*
*/
public enum SymmetricAlgorithm {
/** 默认的AES加密方式AES/ECB/PKCS5Padding */
/**
* 默认的AES加密方式AES/ECB/PKCS5Padding
*/
AES("AES"),
/**
* ARCFOUR
*/
ARCFOUR("ARCFOUR"),
/**
* Blowfish
*/
Blowfish("Blowfish"),
/** 默认的DES加密方式DES/ECB/PKCS5Padding */
/**
* 默认的DES加密方式DES/ECB/PKCS5Padding
*/
DES("DES"),
/** 3DES算法默认实现为DESede/ECB/PKCS5Padding */
/**
* 3DES算法默认实现为DESede/ECB/PKCS5Padding
*/
DESede("DESede"),
/**
* RC2
*/
RC2("RC2"),
/**
*PBEWithMD5AndDES
*/
PBEWithMD5AndDES("PBEWithMD5AndDES"),
/**
* PBEWithSHA1AndDESede
*/
PBEWithSHA1AndDESede("PBEWithSHA1AndDESede"),
/**
* PBEWithSHA1AndRC2_40
*/
PBEWithSHA1AndRC2_40("PBEWithSHA1AndRC2_40");
private final String value;
/**
* 构造
*
* @param value 算法的字符串表示区分大小写
*/
SymmetricAlgorithm(final String value) {
@ -46,6 +69,7 @@ public enum SymmetricAlgorithm {
/**
* 获得算法的字符串表示形式
*
* @return 算法字符串
*/
public String getValue() {

View File

@ -57,7 +57,13 @@ public class ZUC extends SymmetricCrypto {
* @author looly
*/
public enum ZUCAlgorithm {
/**
* ZUC-128
*/
ZUC_128("ZUC-128"),
/**
* ZUC-256
*/
ZUC_256("ZUC-256");
private final String value;

View File

@ -0,0 +1 @@
org.dromara.hutool.crypto.provider.BouncyCastleProviderFactory

View File

@ -1,5 +1,6 @@
package org.dromara.hutool.crypto;
import org.dromara.hutool.crypto.provider.GlobalProviderFactory;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@ -17,7 +18,7 @@ public class KeyUtilTest {
@Disabled
public void generateKeyPairTest() {
Assertions.assertThrows(CryptoException.class, ()->{
GlobalBouncyCastleProvider.setUseBouncyCastle(false);
GlobalProviderFactory.setUseCustomProvider(false);
final KeyPair pair = KeyUtil.generateKeyPair("SM2");
Assertions.assertNotNull(pair);
});

View File

@ -5,6 +5,7 @@ import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.crypto.asymmetric.Sign;
import org.dromara.hutool.crypto.asymmetric.SignAlgorithm;
import org.dromara.hutool.crypto.bc.PemUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

View File

@ -5,10 +5,10 @@ import org.dromara.hutool.core.codec.binary.Base64;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ByteUtil;
import org.dromara.hutool.core.util.CharsetUtil;
import org.dromara.hutool.crypto.ECKeyUtil;
import org.dromara.hutool.crypto.bc.ECKeyUtil;
import org.dromara.hutool.crypto.KeyUtil;
import org.dromara.hutool.crypto.SecureUtil;
import org.dromara.hutool.crypto.SmUtil;
import org.dromara.hutool.crypto.bc.SmUtil;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.jcajce.spec.OpenSSHPrivateKeySpec;

View File

@ -1,4 +1,16 @@
package org.dromara.hutool.crypto;
/*
* 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:
* http://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.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;

View File

@ -1,4 +1,16 @@
package org.dromara.hutool.crypto;
/*
* 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:
* http://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.dromara.hutool.core.io.resource.ResourceUtil;
import org.dromara.hutool.core.util.ByteUtil;

View File

@ -1,4 +1,16 @@
package org.dromara.hutool.crypto;
/*
* 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:
* http://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.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.io.resource.ResourceUtil;

View File

@ -1,6 +1,22 @@
package org.dromara.hutool.crypto;
/*
* 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:
* http://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.dromara.hutool.core.util.CharsetUtil;
import org.dromara.hutool.crypto.KeyUtil;
import org.dromara.hutool.crypto.Mode;
import org.dromara.hutool.crypto.Padding;
import org.dromara.hutool.crypto.bc.SmUtil;
import org.dromara.hutool.crypto.digest.HMac;
import org.dromara.hutool.crypto.symmetric.SM4;
import org.junit.jupiter.api.Assertions;

View File

@ -0,0 +1,34 @@
/*
* 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:
* http://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.provider;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.security.Provider;
/**
* 单元测试只针对bouncycastle引入有效
*/
public class GlobalProviderFactoryTest {
@Test
void getProviderTest() {
final Provider provider = GlobalProviderFactory.getProvider();
Assertions.assertNotNull(provider);
Assertions.assertEquals(
"org.bouncycastle.jce.provider.BouncyCastleProvider",
provider.getClass().getName());
}
}

View File

@ -21,7 +21,7 @@ import net.sf.cglib.proxy.Enhancer;
*
* @author looly
*/
public class CglibProxyFactory extends ProxyFactory {
public class CglibProxyFactory implements ProxyFactory {
private static final long serialVersionUID = 1L;
@Override

View File

@ -21,7 +21,7 @@ import org.dromara.hutool.extra.aop.interceptor.JdkInterceptor;
*
* @author looly
*/
public class JdkProxyFactory extends ProxyFactory {
public class JdkProxyFactory implements ProxyFactory {
private static final long serialVersionUID = 1L;
@Override

View File

@ -24,31 +24,7 @@ import java.io.Serializable;
*
* @author looly
*/
public abstract class ProxyFactory implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 创建代理
*
* @param <T> 代理对象类型
* @param target 被代理对象
* @param aspectClass 切面实现类自动实例化
* @return 代理对象
* @since 5.3.1
*/
public <T> T proxy(final T target, final Class<? extends Aspect> aspectClass) {
return proxy(target, ConstructorUtil.newInstanceIfPossible(aspectClass));
}
/**
* 创建代理
*
* @param <T> 代理对象类型
* @param target 被代理对象
* @param aspect 切面实现
* @return 代理对象
*/
public abstract <T> T proxy(T target, Aspect aspect);
public interface ProxyFactory extends Serializable {
/**
* 根据用户引入Cglib与否自动创建代理对象
@ -58,7 +34,7 @@ public abstract class ProxyFactory implements Serializable {
* @param aspectClass 切面对象类
* @return 代理对象
*/
public static <T> T createProxy(final T target, final Class<? extends Aspect> aspectClass) {
static <T> T createProxy(final T target, final Class<? extends Aspect> aspectClass) {
return createProxy(target, ConstructorUtil.newInstance(aspectClass));
}
@ -70,7 +46,7 @@ public abstract class ProxyFactory implements Serializable {
* @param aspect 切面实现
* @return 代理对象
*/
public static <T> T createProxy(final T target, final Aspect aspect) {
static <T> T createProxy(final T target, final Aspect aspect) {
return of().proxy(target, aspect);
}
@ -79,7 +55,30 @@ public abstract class ProxyFactory implements Serializable {
*
* @return 代理工厂
*/
public static ProxyFactory of() {
static ProxyFactory of() {
return ServiceLoaderUtil.loadFirstAvailable(ProxyFactory.class);
}
/**
* 创建代理
*
* @param <T> 代理对象类型
* @param target 被代理对象
* @param aspectClass 切面实现类自动实例化
* @return 代理对象
* @since 5.3.1
*/
default <T> T proxy(final T target, final Class<? extends Aspect> aspectClass) {
return proxy(target, ConstructorUtil.newInstanceIfPossible(aspectClass));
}
/**
* 创建代理
*
* @param <T> 代理对象类型
* @param target 被代理对象
* @param aspect 切面实现
* @return 代理对象
*/
<T> T proxy(T target, Aspect aspect);
}

View File

@ -22,7 +22,7 @@ import org.springframework.cglib.proxy.Enhancer;
* @author looly
*
*/
public class SpringCglibProxyFactory extends ProxyFactory{
public class SpringCglibProxyFactory implements ProxyFactory{
private static final long serialVersionUID = 1L;
@Override