From 82f982f80929f2bbdb3b70ee5e29d5745a9fd404 Mon Sep 17 00:00:00 2001
From: Looly
Date: Mon, 2 Mar 2020 23:34:45 +0800
Subject: [PATCH] 5.2.0
---
CHANGELOG.md | 4 +-
README.md | 10 +-
bin/version.txt | 2 +-
docs/js/version.js | 2 +-
hutool-all/pom.xml | 2 +-
hutool-aop/pom.xml | 2 +-
hutool-bloomFilter/pom.xml | 2 +-
hutool-bom/pom.xml | 2 +-
hutool-cache/pom.xml | 2 +-
hutool-captcha/pom.xml | 2 +-
hutool-core/pom.xml | 2 +-
hutool-cron/pom.xml | 2 +-
hutool-crypto/pom.xml | 2 +-
.../main/java/cn/hutool/crypto/BCUtil.java | 176 ++-------
.../main/java/cn/hutool/crypto/PemUtil.java | 154 ++++++++
.../java/cn/hutool/crypto/asymmetric/SM2.java | 145 ++++---
.../hutool/crypto/asymmetric/SM2Engine.java | 356 ------------------
.../{BCUtilTest.java => PemUtilTest.java} | 27 +-
.../java/cn/hutool/crypto/test/SM2Test.java | 19 +-
hutool-db/pom.xml | 2 +-
hutool-dfa/pom.xml | 2 +-
hutool-extra/pom.xml | 2 +-
hutool-http/pom.xml | 2 +-
hutool-json/pom.xml | 2 +-
hutool-log/pom.xml | 2 +-
hutool-poi/pom.xml | 2 +-
hutool-script/pom.xml | 2 +-
hutool-setting/pom.xml | 2 +-
hutool-socket/pom.xml | 2 +-
hutool-system/pom.xml | 2 +-
pom.xml | 2 +-
31 files changed, 327 insertions(+), 610 deletions(-)
create mode 100644 hutool-crypto/src/main/java/cn/hutool/crypto/PemUtil.java
delete mode 100644 hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2Engine.java
rename hutool-crypto/src/test/java/cn/hutool/crypto/test/{BCUtilTest.java => PemUtilTest.java} (58%)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c0934450c..b990978c1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,7 @@
-------------------------------------------------------------------------------------------------------------
-## 5.1.6
+## 5.2.0
### 新特性
* 【core 】 NumberUtil.decimalFormat增加Object对象参数支持
@@ -18,6 +18,8 @@
* 【all 】 log、template、tokenizer使用SPI机制代替硬编码
* 【poi 】 Word07Writer增加addPicture
* 【crypto】 RSA算法中,BlockSize长度策略调整(issue#721@Github)
+* 【crypto】 删除SM2Engine,使用BC库中的对象替代
+* 【crypto】 增加PemUtil工具类
### Bug修复
diff --git a/README.md b/README.md
index 8398ffdb7..986ef43dc 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@
-- 主页:https://hutool.cn/ | https://www.hutool.club/ --
- -- QQ群③:555368316 --
+ -- QQ群③:555368316 --
-- QQ群④:718802356 --
@@ -116,21 +116,21 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不
cn.hutool
hutool-all
- 5.1.6
+ 5.2.0
```
### Gradle
```
-compile 'cn.hutool:hutool-all:5.1.6'
+compile 'cn.hutool:hutool-all:5.2.0'
```
### 非Maven项目
点击以下任一链接,下载`hutool-all-X.X.X.jar`即可:
-- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.1.6/)
-- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.1.6/)
+- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.2.0/)
+- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.2.0/)
> 注意
> Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类获工具方法可用。
diff --git a/bin/version.txt b/bin/version.txt
index 8710cfdff..91ff57278 100755
--- a/bin/version.txt
+++ b/bin/version.txt
@@ -1 +1 @@
-5.1.6
+5.2.0
diff --git a/docs/js/version.js b/docs/js/version.js
index b2c323153..6edc874ca 100644
--- a/docs/js/version.js
+++ b/docs/js/version.js
@@ -1 +1 @@
-var version = '5.1.6'
\ No newline at end of file
+var version = '5.2.0'
\ No newline at end of file
diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml
index dec55c769..5d8370582 100644
--- a/hutool-all/pom.xml
+++ b/hutool-all/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-all
diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml
index ac1cbb5b2..e6a967516 100644
--- a/hutool-aop/pom.xml
+++ b/hutool-aop/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-aop
diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml
index a8cd0979f..50db780b5 100644
--- a/hutool-bloomFilter/pom.xml
+++ b/hutool-bloomFilter/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-bloomFilter
diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml
index 0fbd0f039..af290867b 100644
--- a/hutool-bom/pom.xml
+++ b/hutool-bom/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-bom
diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml
index 9ec5cd7e2..f79791807 100644
--- a/hutool-cache/pom.xml
+++ b/hutool-cache/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-cache
diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml
index d5155d798..6869b9e6a 100644
--- a/hutool-captcha/pom.xml
+++ b/hutool-captcha/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-captcha
diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml
index e7def7b3c..afccd19fe 100644
--- a/hutool-core/pom.xml
+++ b/hutool-core/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-core
diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml
index e76776af0..c95813918 100644
--- a/hutool-cron/pom.xml
+++ b/hutool-cron/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-cron
diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml
index 59360a4c3..17291e026 100644
--- a/hutool-crypto/pom.xml
+++ b/hutool-crypto/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-crypto
diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/BCUtil.java b/hutool-crypto/src/main/java/cn/hutool/crypto/BCUtil.java
index 0b423c2ff..91150151e 100644
--- a/hutool-crypto/src/main/java/cn/hutool/crypto/BCUtil.java
+++ b/hutool-crypto/src/main/java/cn/hutool/crypto/BCUtil.java
@@ -1,30 +1,25 @@
package cn.hutool.crypto;
-import cn.hutool.core.io.IORuntimeException;
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.StrUtil;
+import org.bouncycastle.crypto.params.ECDomainParameters;
+import org.bouncycastle.crypto.params.ECKeyParameters;
+import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.ECPointUtil;
+import org.bouncycastle.jce.interfaces.ECKey;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
+import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.math.ec.ECCurve;
-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 java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
import java.security.GeneralSecurityException;
-import java.security.Key;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.ECFieldFp;
-import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.EllipticCurve;
@@ -81,7 +76,7 @@ public class BCUtil {
final ECPoint point = ECPointUtil.decodePoint(ecCurve, encodeByte);
// 根据曲线恢复公钥格式
- ECParameterSpec ecSpec = new ECNamedCurveSpec(curveName, curve, namedSpec.getG(), namedSpec.getN());
+ ECNamedCurveSpec ecSpec = new ECNamedCurveSpec(curveName, curve, namedSpec.getG(), namedSpec.getN());
final KeyFactory PubKeyGen = KeyUtil.getKeyFactory("EC");
try {
@@ -92,152 +87,37 @@ public class BCUtil {
}
/**
- * 读取PEM格式的私钥
+ * ECKey转换为ECKeyParameters
*
- * @param pemStream pem流
- * @return {@link PrivateKey}
- * @since 4.5.2
- */
- public static PrivateKey readPrivateKey(InputStream pemStream) {
- return (PrivateKey) readPemKey(pemStream);
- }
-
- /**
- * 读取PEM格式的公钥
- *
- * @param pemStream pem流
- * @return {@link PublicKey}
- * @since 4.5.2
- */
- public static PublicKey readPublicKey(InputStream pemStream) {
- return (PublicKey) readPemKey(pemStream);
- }
-
- /**
- * 从pem文件中读取公钥或私钥
- * 根据类型返回{@link PublicKey} 或者 {@link PrivateKey}
- *
- * @param pemKeyStream pem流
- * @return {@link Key}
- * @since 4.5.2
- * @deprecated 请使用{@link #readPemKey(InputStream)}
- */
- @Deprecated
- public static Key readKey(InputStream pemKeyStream) {
- return readPemKey(pemKeyStream);
- }
-
- /**
- * 从pem文件中读取公钥或私钥
- * 根据类型返回{@link PublicKey} 或者 {@link PrivateKey}
- *
- * @param keyStream pem流
- * @return {@link Key},null表示无法识别的密钥类型
+ * @param ecKey BCECPrivateKey或者BCECPublicKey
+ * @return ECPrivateKeyParameters或者ECPublicKeyParameters
* @since 5.1.6
*/
- public static Key readPemKey(InputStream keyStream) {
- final PemObject object = readPemObject(keyStream);
- final String type = object.getType();
- if (StrUtil.isNotBlank(type)) {
- if (type.endsWith("PRIVATE KEY")) {
- return KeyUtil.generateRSAPrivateKey(object.getContent());
- } else if (type.endsWith("PUBLIC KEY")) {
- return KeyUtil.generateRSAPublicKey(object.getContent());
- } else if (type.endsWith("CERTIFICATE")) {
- return KeyUtil.readPublicKeyFromCert(IoUtil.toStream(object.getContent()));
- }
+ public static ECKeyParameters toParams(ECKey ecKey) {
+ final ECParameterSpec parameterSpec = ecKey.getParameters();
+ final ECDomainParameters ecDomainParameters = buildECDomainParameters(parameterSpec);
+
+ if (ecKey instanceof BCECPrivateKey) {
+ return new ECPrivateKeyParameters(((BCECPrivateKey) ecKey).getD(), ecDomainParameters);
+ } else if (ecKey instanceof BCECPublicKey) {
+ return new ECPublicKeyParameters(((BCECPublicKey) ecKey).getQ(), ecDomainParameters);
}
- //表示无法识别的密钥类型
return null;
}
/**
- * 从pem文件中读取公钥或私钥
+ * 构建ECDomainParameters对象
*
- * @param keyStream pem流
- * @return 密钥bytes
- * @since 4.5.2
- * @deprecated 使用{@link #readPem(InputStream)}
- */
- @Deprecated
- public static byte[] readKeyBytes(InputStream keyStream) {
- return readPem(keyStream);
- }
-
- /**
- * 从pem流中读取公钥或私钥
- *
- * @param keyStream pem流
- * @return 密钥bytes
+ * @param parameterSpec ECParameterSpec
+ * @return ECDomainParameters
* @since 5.1.6
*/
- public static byte[] readPem(InputStream keyStream) {
- PemObject pemObject = readPemObject(keyStream);
- if (null != pemObject) {
- return pemObject.getContent();
- }
- return null;
- }
-
- /**
- * 读取pem文件中的信息,包括类型、头信息和密钥内容
- *
- * @param keyStream pem流
- * @return {@link PemObject}
- * @since 4.5.2
- */
- public static PemObject readPemObject(InputStream keyStream) {
- return readPemObject(IoUtil.getUtf8Reader(keyStream));
- }
-
- /**
- * 读取pem文件中的信息,包括类型、头信息和密钥内容
- *
- * @param reader pem Reader
- * @return {@link PemObject}
- * @since 5.1.6
- */
- public static PemObject readPemObject(Reader reader) {
- PemReader pemReader = null;
- try {
- pemReader = new PemReader(reader);
- return pemReader.readPemObject();
- } catch (IOException e) {
- throw new IORuntimeException(e);
- } finally {
- IoUtil.close(pemReader);
- }
- }
-
- /**
- * 写出pem密钥(私钥、公钥、证书)
- *
- * @param type 密钥类型(私钥、公钥、证书)
- * @param content 密钥内容
- * @param keyStream pem流
- * @since 5.1.6
- */
- public static void writePemObject(String type, byte[] content, OutputStream keyStream) {
- writePemObject(new PemObject(type, content), keyStream);
- }
-
- /**
- * 写出pem密钥(私钥、公钥、证书)
- *
- * @param pemObject pem对象,包括密钥和密钥类型等信息
- * @param keyStream pem流
- * @since 5.1.6
- */
- public static void writePemObject(PemObjectGenerator pemObject, OutputStream keyStream) {
- PemWriter writer = null;
- try {
- writer = new PemWriter(IoUtil.getUtf8Writer(keyStream));
- writer.writeObject(pemObject);
- } catch (IOException e) {
- throw new IORuntimeException(e);
- } finally {
- IoUtil.close(writer);
- }
+ public static ECDomainParameters buildECDomainParameters(ECParameterSpec parameterSpec) {
+ return new ECDomainParameters(
+ parameterSpec.getCurve(),
+ parameterSpec.getG(),
+ parameterSpec.getN(),
+ parameterSpec.getH());
}
}
diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/PemUtil.java b/hutool-crypto/src/main/java/cn/hutool/crypto/PemUtil.java
new file mode 100644
index 000000000..d2b8930ed
--- /dev/null
+++ b/hutool-crypto/src/main/java/cn/hutool/crypto/PemUtil.java
@@ -0,0 +1,154 @@
+package cn.hutool.crypto;
+
+import cn.hutool.core.io.IORuntimeException;
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.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 java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+/**
+ * PEM(Privacy Enhanced Mail)格式相关工具类。
+ *
+ *
+ * PEM一般为文本格式,以 -----BEGIN... 开头,以 -----END... 结尾,中间的内容是 BASE64 编码。
+ *
+ * 这种格式可以保存证书和私钥,有时我们也把PEM格式的私钥的后缀改为 .key 以区别证书与私钥。
+ *
+ * @author looly
+ * @since 5.1.6
+ */
+public class PemUtil {
+
+ /**
+ * 读取PEM格式的私钥
+ *
+ * @param pemStream pem流
+ * @return {@link PrivateKey}
+ * @since 4.5.2
+ */
+ public static PrivateKey readPemPrivateKey(InputStream pemStream) {
+ return (PrivateKey) PemUtil.readPemKey(pemStream);
+ }
+
+ /**
+ * 读取PEM格式的公钥
+ *
+ * @param pemStream pem流
+ * @return {@link PublicKey}
+ * @since 4.5.2
+ */
+ public static PublicKey readPemPublicKey(InputStream pemStream) {
+ return (PublicKey) PemUtil.readPemKey(pemStream);
+ }
+
+ /**
+ * 从pem文件中读取公钥或私钥
+ * 根据类型返回 {@link PublicKey} 或者 {@link PrivateKey}
+ *
+ * @param keyStream pem流
+ * @return {@link Key},null表示无法识别的密钥类型
+ * @since 5.1.6
+ */
+ public static Key readPemKey(InputStream keyStream) {
+ final PemObject object = readPemObject(keyStream);
+ final String type = object.getType();
+ if (StrUtil.isNotBlank(type)) {
+ if (type.endsWith("PRIVATE KEY")) {
+ return KeyUtil.generateRSAPrivateKey(object.getContent());
+ } else if (type.endsWith("PUBLIC KEY")) {
+ return KeyUtil.generateRSAPublicKey(object.getContent());
+ } else if (type.endsWith("CERTIFICATE")) {
+ return KeyUtil.readPublicKeyFromCert(IoUtil.toStream(object.getContent()));
+ }
+ }
+
+ //表示无法识别的密钥类型
+ return null;
+ }
+
+ /**
+ * 从pem流中读取公钥或私钥
+ *
+ * @param keyStream pem流
+ * @return 密钥bytes
+ * @since 5.1.6
+ */
+ public static byte[] readPem(InputStream keyStream) {
+ PemObject pemObject = readPemObject(keyStream);
+ if (null != pemObject) {
+ return pemObject.getContent();
+ }
+ return null;
+ }
+
+ /**
+ * 读取pem文件中的信息,包括类型、头信息和密钥内容
+ *
+ * @param keyStream pem流
+ * @return {@link PemObject}
+ * @since 4.5.2
+ */
+ public static PemObject readPemObject(InputStream keyStream) {
+ return readPemObject(IoUtil.getUtf8Reader(keyStream));
+ }
+
+ /**
+ * 读取pem文件中的信息,包括类型、头信息和密钥内容
+ *
+ * @param reader pem Reader
+ * @return {@link PemObject}
+ * @since 5.1.6
+ */
+ public static PemObject readPemObject(Reader reader) {
+ PemReader pemReader = null;
+ try {
+ pemReader = new PemReader(reader);
+ return pemReader.readPemObject();
+ } catch (IOException e) {
+ throw new IORuntimeException(e);
+ } finally {
+ IoUtil.close(pemReader);
+ }
+ }
+
+ /**
+ * 写出pem密钥(私钥、公钥、证书)
+ *
+ * @param type 密钥类型(私钥、公钥、证书)
+ * @param content 密钥内容
+ * @param keyStream pem流
+ * @since 5.1.6
+ */
+ public static void writePemObject(String type, byte[] content, OutputStream keyStream) {
+ writePemObject(new PemObject(type, content), keyStream);
+ }
+
+ /**
+ * 写出pem密钥(私钥、公钥、证书)
+ *
+ * @param pemObject pem对象,包括密钥和密钥类型等信息
+ * @param keyStream pem流
+ * @since 5.1.6
+ */
+ public static void writePemObject(PemObjectGenerator pemObject, OutputStream keyStream) {
+ PemWriter writer = null;
+ try {
+ writer = new PemWriter(IoUtil.getUtf8Writer(keyStream));
+ writer.writeObject(pemObject);
+ } catch (IOException e) {
+ throw new IORuntimeException(e);
+ } finally {
+ IoUtil.close(writer);
+ }
+ }
+}
diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java
index 3dc10d01c..da3a1b213 100644
--- a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java
+++ b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2.java
@@ -2,8 +2,9 @@ package cn.hutool.crypto.asymmetric;
import cn.hutool.crypto.CryptoException;
import cn.hutool.crypto.SecureUtil;
-import cn.hutool.crypto.asymmetric.SM2Engine.SM2Mode;
import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithID;
@@ -19,23 +20,26 @@ import java.security.PublicKey;
* 国密SM2算法实现,基于BC库
* SM2算法只支持公钥加密,私钥解密
* 参考:https://blog.csdn.net/pridas/article/details/86118774
- *
+ *
* @author looly
* @since 4.3.2
*/
public class SM2 extends AbstractAsymmetricCrypto {
- /** 算法EC */
+ /**
+ * 算法EC
+ */
private static final String ALGORITHM_SM2 = "SM2";
protected SM2Engine engine;
protected SM2Signer signer;
- private SM2Mode mode;
+ private SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2;
private ECPublicKeyParameters publicKeyParams;
private ECPrivateKeyParameters privateKeyParams;
// ------------------------------------------------------------------ Constructor start
+
/**
* 构造,生成新的私钥公钥对
*/
@@ -47,9 +51,9 @@ public class SM2 extends AbstractAsymmetricCrypto {
* 构造
* 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
- *
+ *
* @param privateKeyStr 私钥Hex或Base64表示
- * @param publicKeyStr 公钥Hex或Base64表示
+ * @param publicKeyStr 公钥Hex或Base64表示
*/
public SM2(String privateKeyStr, String publicKeyStr) {
this(SecureUtil.decode(privateKeyStr), SecureUtil.decode(publicKeyStr));
@@ -59,9 +63,9 @@ public class SM2 extends AbstractAsymmetricCrypto {
* 构造
* 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
- *
+ *
* @param privateKey 私钥
- * @param publicKey 公钥
+ * @param publicKey 公钥
*/
public SM2(byte[] privateKey, byte[] publicKey) {
this(//
@@ -74,9 +78,9 @@ public class SM2 extends AbstractAsymmetricCrypto {
* 构造
* 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
- *
+ *
* @param privateKey 私钥
- * @param publicKey 公钥
+ * @param publicKey 公钥
*/
public SM2(PrivateKey privateKey, PublicKey publicKey) {
super(ALGORITHM_SM2, privateKey, publicKey);
@@ -87,9 +91,9 @@ public class SM2 extends AbstractAsymmetricCrypto {
* 初始化
* 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密(签名)或者解密(校验)
- *
+ *
* @param privateKey 私钥
- * @param publicKey 公钥
+ * @param publicKey 公钥
* @return this
*/
public SM2 init(PrivateKey privateKey, PublicKey publicKey) {
@@ -103,16 +107,17 @@ public class SM2 extends AbstractAsymmetricCrypto {
}
// --------------------------------------------------------------------------------- Encrypt
+
/**
* 加密,SM2非对称加密的结果由C1,C2,C3三部分组成,其中:
- *
+ *
*
* C1 生成随机数的计算出的椭圆曲线点
* C2 密文数据
* C3 SM3的摘要值
*
- *
- * @param data 被加密的bytes
+ *
+ * @param data 被加密的bytes
* @param keyType 私钥或公钥 {@link KeyType}
* @return 加密后的bytes
* @throws CryptoException 包括InvalidKeyException和InvalidCipherTextException的包装异常
@@ -123,22 +128,43 @@ public class SM2 extends AbstractAsymmetricCrypto {
throw new IllegalArgumentException("Encrypt is only support by public key");
}
checkKey(keyType);
+ return encrypt(data, new ParametersWithRandom(getCipherParameters(keyType)));
+ }
+ /**
+ * 加密,SM2非对称加密的结果由C1,C2,C3三部分组成,其中:
+ *
+ *
+ * C1 生成随机数的计算出的椭圆曲线点
+ * C2 密文数据
+ * C3 SM3的摘要值
+ *
+ *
+ * @param data 被加密的bytes
+ * @param pubKeyParameters 公钥参数
+ * @return 加密后的bytes
+ * @throws CryptoException 包括InvalidKeyException和InvalidCipherTextException的包装异常
+ * @since 5.1.6
+ */
+ public byte[] encrypt(byte[] data, CipherParameters pubKeyParameters) throws CryptoException {
lock.lock();
final SM2Engine engine = getEngine();
try {
- engine.init(true, new ParametersWithRandom(getCipherParameters(keyType)));
+ engine.init(true, pubKeyParameters);
return engine.processBlock(data, 0, data.length);
+ } catch (InvalidCipherTextException e) {
+ throw new CryptoException(e);
} finally {
lock.unlock();
}
}
// --------------------------------------------------------------------------------- Decrypt
+
/**
* 解密
- *
- * @param data SM2密文,实际包含三部分:ECC公钥、真正的密文、公钥和原文的SM3-HASH值
+ *
+ * @param data SM2密文,实际包含三部分:ECC公钥、真正的密文、公钥和原文的SM3-HASH值
* @param keyType 私钥或公钥 {@link KeyType}
* @return 加密后的bytes
* @throws CryptoException 包括InvalidKeyException和InvalidCipherTextException的包装异常
@@ -149,21 +175,35 @@ public class SM2 extends AbstractAsymmetricCrypto {
throw new IllegalArgumentException("Decrypt is only support by private key");
}
checkKey(keyType);
+ return decrypt(data, getCipherParameters(keyType));
+ }
+ /**
+ * 解密
+ *
+ * @param data SM2密文,实际包含三部分:ECC公钥、真正的密文、公钥和原文的SM3-HASH值
+ * @param privateKeyParameters 私钥参数
+ * @return 加密后的bytes
+ * @throws CryptoException 包括InvalidKeyException和InvalidCipherTextException的包装异常
+ * @since 5.1.6
+ */
+ public byte[] decrypt(byte[] data, CipherParameters privateKeyParameters) throws CryptoException {
lock.lock();
final SM2Engine engine = getEngine();
try {
- engine.init(false, getCipherParameters(keyType));
+ engine.init(false, privateKeyParameters);
return engine.processBlock(data, 0, data.length);
+ } catch (InvalidCipherTextException e) {
+ throw new CryptoException(e);
} finally {
lock.unlock();
}
}
-
// --------------------------------------------------------------------------------- Sign and Verify
+
/**
* 用私钥对信息生成数字签名
- *
+ *
* @param data 加密数据
* @return 签名
*/
@@ -173,9 +213,9 @@ public class SM2 extends AbstractAsymmetricCrypto {
/**
* 用私钥对信息生成数字签名
- *
+ *
* @param data 加密数据
- * @param id 可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes()
+ * @param id 可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes()
* @return 签名
*/
public byte[] sign(byte[] data, byte[] id) {
@@ -198,7 +238,7 @@ public class SM2 extends AbstractAsymmetricCrypto {
/**
* 用公钥检验数字签名的合法性
- *
+ *
* @param data 数据
* @param sign 签名
* @return 是否验证通过
@@ -209,10 +249,10 @@ public class SM2 extends AbstractAsymmetricCrypto {
/**
* 用公钥检验数字签名的合法性
- *
+ *
* @param data 数据
* @param sign 签名
- * @param id 可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes()
+ * @param id 可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes()
* @return 是否验证通过
*/
public boolean verify(byte[] data, byte[] sign, byte[] id) {
@@ -257,22 +297,23 @@ public class SM2 extends AbstractAsymmetricCrypto {
/**
* 设置加密类型
- *
- * @param mode {@link SM2Mode}
+ *
+ * @param mode {@link SM2Engine.Mode}
* @return this
*/
- public SM2 setMode(SM2Mode mode) {
+ public SM2 setMode(SM2Engine.Mode mode) {
this.mode = mode;
if (null != this.engine) {
- this.engine.setMode(mode);
+ this.engine = null;
}
return this;
}
// ------------------------------------------------------------------------------------------------------------------------- Private method start
+
/**
* 初始化加密解密参数(包括私钥和公钥参数)
- *
+ *
* @return this
*/
private SM2 initCipherParams() {
@@ -292,16 +333,16 @@ public class SM2 extends AbstractAsymmetricCrypto {
/**
* 获取密钥类型对应的加密参数对象{@link CipherParameters}
- *
+ *
* @param keyType Key类型枚举,包括私钥或公钥
* @return {@link CipherParameters}
*/
private CipherParameters getCipherParameters(KeyType keyType) {
switch (keyType) {
- case PublicKey:
- return this.publicKeyParams;
- case PrivateKey:
- return this.privateKeyParams;
+ case PublicKey:
+ return this.publicKeyParams;
+ case PrivateKey:
+ return this.privateKeyParams;
}
return null;
@@ -309,27 +350,27 @@ public class SM2 extends AbstractAsymmetricCrypto {
/**
* 检查对应类型的Key是否存在
- *
+ *
* @param keyType key类型
*/
private void checkKey(KeyType keyType) {
switch (keyType) {
- case PublicKey:
- if (null == this.publicKey) {
- throw new NullPointerException("No public key provided");
- }
- break;
- case PrivateKey:
- if (null == this.privateKey) {
- throw new NullPointerException("No private key provided");
- }
- break;
+ case PublicKey:
+ if (null == this.publicKey) {
+ throw new NullPointerException("No public key provided");
+ }
+ break;
+ case PrivateKey:
+ if (null == this.privateKey) {
+ throw new NullPointerException("No private key provided");
+ }
+ break;
}
}
/**
- * 获取{@link SM2Engine}
- *
+ * 获取{@link SM2Engine},此对象为懒加载模式
+ *
* @return {@link SM2Engine}
*/
private SM2Engine getEngine() {
@@ -338,10 +379,10 @@ public class SM2 extends AbstractAsymmetricCrypto {
}
return this.engine;
}
-
+
/**
- * 获取{@link SM2Signer}
- *
+ * 获取{@link SM2Signer},此对象为懒加载模式
+ *
* @return {@link SM2Signer}
*/
private SM2Signer getSigner() {
diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2Engine.java b/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2Engine.java
deleted file mode 100644
index abe4bf6d4..000000000
--- a/hutool-crypto/src/main/java/cn/hutool/crypto/asymmetric/SM2Engine.java
+++ /dev/null
@@ -1,356 +0,0 @@
-package cn.hutool.crypto.asymmetric;
-
-import java.math.BigInteger;
-import java.util.Random;
-
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.CryptoServicesRegistrar;
-import org.bouncycastle.crypto.Digest;
-import org.bouncycastle.crypto.digests.SM3Digest;
-import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.crypto.params.ECKeyParameters;
-import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
-import org.bouncycastle.crypto.params.ECPublicKeyParameters;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.math.ec.ECConstants;
-import org.bouncycastle.math.ec.ECFieldElement;
-import org.bouncycastle.math.ec.ECMultiplier;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.FixedPointCombMultiplier;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.BigIntegers;
-import org.bouncycastle.util.Memoable;
-import org.bouncycastle.util.Pack;
-
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.crypto.CryptoException;
-
-/**
- * SM2加密解密引擎,来自Bouncy Castle库的SM2Engine类改造
- * SM2加密后的数据格式为(两种模式):
- *
- *
- * curve(C1) | data(C2) | digest(C3)
- * curve(C1) | digest(C3) | data(C2)
- *
- *
- * @author looly, bouncycastle
- * @since 4.5.0
- */
-public class SM2Engine {
-
- private final Digest digest;
-
- private boolean forEncryption;
- private ECKeyParameters ecKey;
- private ECDomainParameters ecParams;
- private int curveLength;
- private Random random;
- /** 加密解密模式 */
- private SM2Mode mode;
-
- /**
- * 构造
- */
- public SM2Engine() {
- this(new SM3Digest());
- }
-
- /**
- * 构造
- *
- * @param mode SM2密钥生成模式,可选C1C2C3和C1C3C2
- */
- public SM2Engine(SM2Mode mode) {
- this(new SM3Digest(), mode);
- }
-
- /**
- * 构造
- *
- * @param digest 摘要算法啊
- */
- public SM2Engine(Digest digest) {
- this(digest, null);
- }
-
- /**
- * 构造
- *
- * @param digest 摘要算法啊
- * @param mode SM2密钥生成模式,可选C1C2C3和C1C3C2
- */
- public SM2Engine(Digest digest, SM2Mode mode) {
- this.digest = digest;
- this.mode = ObjectUtil.defaultIfNull(mode, SM2Mode.C1C3C2);
- }
-
- /**
- * 初始化引擎
- *
- * @param forEncryption 是否为加密模式
- * @param param {@link CipherParameters},此处应为{@link ParametersWithRandom}(加密时)或{@link ECKeyParameters}(解密时)
- */
- public void init(boolean forEncryption, CipherParameters param) {
- this.forEncryption = forEncryption;
-
- if (param instanceof ParametersWithRandom) {
- final ParametersWithRandom rParam = (ParametersWithRandom) param;
- this.ecKey = (ECKeyParameters) rParam.getParameters();
- this.random = rParam.getRandom();
- } else {
- this.ecKey = (ECKeyParameters) param;
- }
- this.ecParams = this.ecKey.getParameters();
-
- if (forEncryption) {
- // 检查曲线点
- final ECPoint ecPoint = ((ECPublicKeyParameters) ecKey).getQ().multiply(ecParams.getH());
- if (ecPoint.isInfinity()) {
- throw new IllegalArgumentException("invalid key: [h]Q at infinity");
- }
-
- // 检查随机参数
- if (null == this.random) {
- this.random = CryptoServicesRegistrar.getSecureRandom();
- }
- }
-
- // 曲线位长度
- this.curveLength = (this.ecParams.getCurve().getFieldSize() + 7) / 8;
- }
-
- /**
- * 处理块,包括加密和解密
- *
- * @param in 数据
- * @param inOff 数据开始位置
- * @param inLen 数据长度
- * @return 结果
- */
- public byte[] processBlock(byte[] in, int inOff, int inLen) {
- if (forEncryption) {
- return encrypt(in, inOff, inLen);
- } else {
- return decrypt(in, inOff, inLen);
- }
- }
-
- /**
- * 设置加密类型
- *
- * @param mode {@link SM2Mode}
- * @return this
- */
- public SM2Engine setMode(SM2Mode mode) {
- this.mode = mode;
- return this;
- }
-
- /**
- * SM2算法模式
- * 在SM2算法中,C1C2C3为旧标准模式,C1C3C2为新标准模式
- *
- * @author looly
- *
- */
- public enum SM2Mode {
- C1C2C3, C1C3C2
- }
-
- protected ECMultiplier createBasePointMultiplier() {
- return new FixedPointCombMultiplier();
- }
-
- // --------------------------------------------------------------------------------------------------- Private method start
- /**
- * 加密
- *
- * @param in 数据
- * @param inOff 位置
- * @param inLen 长度
- * @return 密文
- */
- private byte[] encrypt(byte[] in, int inOff, int inLen) {
- // 加密数据
- byte[] c2 = new byte[inLen];
- System.arraycopy(in, inOff, c2, 0, c2.length);
-
- final ECMultiplier multiplier = createBasePointMultiplier();
-
- byte[] c1;
- ECPoint kPB;
- BigInteger k;
- do {
- k = nextK();
- // 产生随机数计算出曲线点C1
- c1 = multiplier.multiply(ecParams.getG(), k).normalize().getEncoded(false);
- kPB = ((ECPublicKeyParameters) ecKey).getQ().multiply(k).normalize();
- kdf(kPB, c2);
- } while (notEncrypted(c2, in, inOff));
-
- // 杂凑值,效验数据
- byte[] c3 = new byte[digest.getDigestSize()];
-
- addFieldElement(kPB.getAffineXCoord());
- this.digest.update(in, inOff, inLen);
- addFieldElement(kPB.getAffineYCoord());
-
- this.digest.doFinal(c3, 0);
-
- // 按照对应模式输出结果
- if (mode == SM2Mode.C1C3C2) {
- return Arrays.concatenate(c1, c3, c2);
- }
- return Arrays.concatenate(c1, c2, c3);
- }
-
- /**
- * 解密,只支持私钥解密
- *
- * @param in 密文
- * @param inOff 位置
- * @param inLen 长度
- * @return 解密后的内容
- */
- private byte[] decrypt(byte[] in, int inOff, int inLen) {
- // 获取曲线点
- final byte[] c1 = new byte[this.curveLength * 2 + 1];
- System.arraycopy(in, inOff, c1, 0, c1.length);
-
- ECPoint c1P = this.ecParams.getCurve().decodePoint(c1);
- if (c1P.multiply(this.ecParams.getH()).isInfinity()) {
- throw new CryptoException("[h]C1 at infinity");
- }
- c1P = c1P.multiply(((ECPrivateKeyParameters) ecKey).getD()).normalize();
-
- final int digestSize = this.digest.getDigestSize();
-
- // 解密C2数据
- final byte[] c2 = new byte[inLen - c1.length - digestSize];
-
- if (SM2Mode.C1C3C2 == this.mode) {
- // C2位于第三部分
- System.arraycopy(in, inOff + c1.length + digestSize, c2, 0, c2.length);
- } else {
- // C2位于第二部分
- System.arraycopy(in, inOff + c1.length, c2, 0, c2.length);
- }
- kdf(c1P, c2);
-
- // 使用摘要验证C2数据
- final byte[] c3 = new byte[digestSize];
-
- addFieldElement(c1P.getAffineXCoord());
- this.digest.update(c2, 0, c2.length);
- addFieldElement(c1P.getAffineYCoord());
- this.digest.doFinal(c3, 0);
-
- int check = 0;
- for (int i = 0; i != c3.length; i++) {
- check |= c3[i] ^ in[inOff + c1.length + ((SM2Mode.C1C3C2 == this.mode) ? 0 : c2.length) + i];
- }
-
- Arrays.fill(c1, (byte) 0);
- Arrays.fill(c3, (byte) 0);
-
- if (check != 0) {
- Arrays.fill(c2, (byte) 0);
- throw new CryptoException("invalid cipher text");
- }
-
- return c2;
- }
-
- private boolean notEncrypted(byte[] encData, byte[] in, int inOff) {
- for (int i = 0; i != encData.length; i++) {
- if (encData[i] != in[inOff + i]) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * 解密数据
- *
- * @param c1 c1点
- * @param encData 密文
- */
- private void kdf(ECPoint c1, byte[] encData) {
- final Digest digest = this.digest;
- int digestSize = digest.getDigestSize();
- byte[] buf = new byte[Math.max(4, digestSize)];
- int off = 0;
-
- Memoable memo = null;
- Memoable copy = null;
-
- if (digest instanceof Memoable) {
- addFieldElement(c1.getAffineXCoord());
- addFieldElement(c1.getAffineYCoord());
- memo = (Memoable) digest;
- copy = memo.copy();
- }
-
- int ct = 0;
-
- while (off < encData.length) {
- if (memo != null) {
- memo.reset(copy);
- } else {
- addFieldElement(c1.getAffineXCoord());
- addFieldElement(c1.getAffineYCoord());
- }
-
- Pack.intToBigEndian(++ct, buf, 0);
- digest.update(buf, 0, 4);
- digest.doFinal(buf, 0);
-
- int xorLen = Math.min(digestSize, encData.length - off);
- xor(encData, buf, off, xorLen);
- off += xorLen;
- }
- }
-
- /**
- * 异或
- *
- * @param data 数据
- * @param kdfOut kdf输出值
- * @param dOff d偏移
- * @param dRemaining d剩余
- */
- private void xor(byte[] data, byte[] kdfOut, int dOff, int dRemaining) {
- for (int i = 0; i != dRemaining; i++) {
- data[dOff + i] ^= kdfOut[i];
- }
- }
-
- /**
- * 下一个K值
- *
- * @return K值
- */
- private BigInteger nextK() {
- final int qBitLength = this.ecParams.getN().bitLength();
-
- BigInteger k;
- do {
- k = new BigInteger(qBitLength, this.random);
- } while (k.equals(ECConstants.ZERO) || k.compareTo(this.ecParams.getN()) >= 0);
-
- return k;
- }
-
- /**
- * 增加字段节点
- *
- * @param v 节点
- */
- private void addFieldElement(ECFieldElement v) {
- final byte[] p = BigIntegers.asUnsignedByteArray(this.curveLength, v.toBigInteger());
- this.digest.update(p, 0, p.length);
- }
- // --------------------------------------------------------------------------------------------------- Private method start
-}
diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/test/BCUtilTest.java b/hutool-crypto/src/test/java/cn/hutool/crypto/test/PemUtilTest.java
similarity index 58%
rename from hutool-crypto/src/test/java/cn/hutool/crypto/test/BCUtilTest.java
rename to hutool-crypto/src/test/java/cn/hutool/crypto/test/PemUtilTest.java
index 9b8ab803a..7db403b1b 100644
--- a/hutool-crypto/src/test/java/cn/hutool/crypto/test/BCUtilTest.java
+++ b/hutool-crypto/src/test/java/cn/hutool/crypto/test/PemUtilTest.java
@@ -1,40 +1,39 @@
package cn.hutool.crypto.test;
+import cn.hutool.core.io.resource.ResourceUtil;
+import cn.hutool.crypto.PemUtil;
+import cn.hutool.crypto.asymmetric.KeyType;
+import cn.hutool.crypto.asymmetric.RSA;
+import org.junit.Assert;
+import org.junit.Test;
+
import java.security.PrivateKey;
import java.security.PublicKey;
-import org.junit.Assert;
-import org.junit.Test;
+public class PemUtilTest {
-import cn.hutool.core.io.resource.ResourceUtil;
-import cn.hutool.crypto.BCUtil;
-import cn.hutool.crypto.asymmetric.KeyType;
-import cn.hutool.crypto.asymmetric.RSA;
-
-public class BCUtilTest {
-
@Test
public void readPrivateKeyTest() {
- PrivateKey privateKey = BCUtil.readPrivateKey(ResourceUtil.getStream("test_private_key.pem"));
+ PrivateKey privateKey = PemUtil.readPemPrivateKey(ResourceUtil.getStream("test_private_key.pem"));
Assert.assertNotNull(privateKey);
}
@Test
public void readPublicKeyTest() {
- PublicKey publicKey = BCUtil.readPublicKey(ResourceUtil.getStream("test_public_key.csr"));
+ PublicKey publicKey = PemUtil.readPemPublicKey(ResourceUtil.getStream("test_public_key.csr"));
Assert.assertNotNull(publicKey);
}
@Test
public void readPemKeyTest() {
- PublicKey publicKey = (PublicKey) BCUtil.readPemKey(ResourceUtil.getStream("test_public_key.csr"));
+ PublicKey publicKey = (PublicKey) PemUtil.readPemKey(ResourceUtil.getStream("test_public_key.csr"));
Assert.assertNotNull(publicKey);
}
@Test
public void validateKey() {
- PrivateKey privateKey = BCUtil.readPrivateKey(ResourceUtil.getStream("test_private_key.pem"));
- PublicKey publicKey = BCUtil.readPublicKey(ResourceUtil.getStream("test_public_key.csr"));
+ PrivateKey privateKey = PemUtil.readPemPrivateKey(ResourceUtil.getStream("test_private_key.pem"));
+ PublicKey publicKey = PemUtil.readPemPublicKey(ResourceUtil.getStream("test_public_key.csr"));
RSA rsa = new RSA(privateKey, publicKey);
String str = "你好,Hutool";//测试字符串
diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/test/SM2Test.java b/hutool-crypto/src/test/java/cn/hutool/crypto/test/SM2Test.java
index eabd71f5a..a119ddb23 100644
--- a/hutool-crypto/src/test/java/cn/hutool/crypto/test/SM2Test.java
+++ b/hutool-crypto/src/test/java/cn/hutool/crypto/test/SM2Test.java
@@ -1,13 +1,5 @@
package cn.hutool.crypto.test;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-
-import cn.hutool.core.lang.Console;
-import org.junit.Assert;
-import org.junit.Test;
-
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.HexUtil;
@@ -17,7 +9,13 @@ import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
-import cn.hutool.crypto.asymmetric.SM2Engine.SM2Mode;
+import org.bouncycastle.crypto.engines.SM2Engine;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
/**
* SM2算法单元测试
@@ -48,10 +46,9 @@ public class SM2Test {
KeyPair pair = SecureUtil.generateKeyPair("SM2");
byte[] privateKey = pair.getPrivate().getEncoded();
byte[] publicKey = pair.getPublic().getEncoded();
- Console.log(HexUtil.encodeHexStr(publicKey));
SM2 sm2 = SmUtil.sm2(privateKey, publicKey);
- sm2.setMode(SM2Mode.C1C3C2);
+ sm2.setMode(SM2Engine.Mode.C1C2C3);
// 公钥加密,私钥解密
byte[] encrypt = sm2.encrypt(StrUtil.bytes("我是一段测试aaaa", CharsetUtil.CHARSET_UTF_8), KeyType.PublicKey);
diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml
index 9c6b609fa..0a121e96c 100644
--- a/hutool-db/pom.xml
+++ b/hutool-db/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-db
diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml
index 183536a83..099d877d6 100644
--- a/hutool-dfa/pom.xml
+++ b/hutool-dfa/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-dfa
diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml
index d2bf56cca..06036ed4e 100644
--- a/hutool-extra/pom.xml
+++ b/hutool-extra/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-extra
diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml
index 2457f4bad..d101a8938 100644
--- a/hutool-http/pom.xml
+++ b/hutool-http/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-http
diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml
index a83553ded..3c44338c6 100644
--- a/hutool-json/pom.xml
+++ b/hutool-json/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-json
diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml
index e19e14b12..6e1c975cb 100644
--- a/hutool-log/pom.xml
+++ b/hutool-log/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-log
diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml
index 6abbe8acf..fdc1acc8e 100644
--- a/hutool-poi/pom.xml
+++ b/hutool-poi/pom.xml
@@ -8,7 +8,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-poi
diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml
index 01ebf41f7..1010d9711 100644
--- a/hutool-script/pom.xml
+++ b/hutool-script/pom.xml
@@ -7,7 +7,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-script
diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml
index 50f19e113..e93167157 100644
--- a/hutool-setting/pom.xml
+++ b/hutool-setting/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-setting
diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml
index d1eee8ff9..432ad0ce7 100644
--- a/hutool-socket/pom.xml
+++ b/hutool-socket/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-socket
diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml
index c95094e04..18b5f09d5 100644
--- a/hutool-system/pom.xml
+++ b/hutool-system/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool-system
diff --git a/pom.xml b/pom.xml
index 48a1bb296..ec167b5b4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
cn.hutool
hutool-parent
- 5.1.6-SNAPSHOT
+ 5.2.0-SNAPSHOT
hutool
提供丰富的Java工具方法
https://github.com/looly/hutool