diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3cf36bf52..af4b4a494 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@
* 【crypto】 增加PemUtil工具类
* 【dfa 】 WordTree增加Filter,支持自定义特殊字符过滤器
* 【poi 】 对于POI依赖升级到4.1.2
+* 【crypto】 增加国密SM2验签密钥格式支持(issue#686@Github)
### Bug修复
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/HexUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/HexUtil.java
index e039a88ea..903820116 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/HexUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/HexUtil.java
@@ -1,6 +1,7 @@
package cn.hutool.core.util;
import java.awt.Color;
+import java.math.BigInteger;
import java.nio.charset.Charset;
/**
@@ -198,6 +199,7 @@ public class HexUtil {
if (StrUtil.isEmpty(hexStr)) {
return null;
}
+ hexStr = StrUtil.removeAll(hexStr, ' ');
return decodeHex(hexStr.toCharArray());
}
@@ -338,6 +340,19 @@ public class HexUtil {
builder.append(toDigits[low]);
}
+ /**
+ * Hex(16进制)字符串转为BigInteger
+ * @param hexStr Hex(16进制字符串)
+ * @return {@link BigInteger}
+ * @since 5.2.0
+ */
+ public static BigInteger toBigInteger(String hexStr){
+ if(null == hexStr){
+ return null;
+ }
+ return new BigInteger(hexStr, 16);
+ }
+
// ---------------------------------------------------------------------------------------- Private method start
/**
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/HexUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/HexUtilTest.java
index 9c620d63b..99553f241 100644
--- a/hutool-core/src/test/java/cn/hutool/core/util/HexUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/util/HexUtilTest.java
@@ -38,4 +38,11 @@ public class HexUtilTest {
boolean isHex = HexUtil.isHexNumber(a);
Assert.assertTrue(isHex);
}
+
+ @Test
+ public void decodeTest(){
+ String str = "e8c670380cb220095268f40221fc748fa6ac39d6e930e63c30da68bad97f885d";
+ Assert.assertArrayEquals(HexUtil.decodeHex(str),
+ HexUtil.decodeHex(str.toUpperCase()));
+ }
}
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 d3d6cb9a9..0098e86b7 100644
--- a/hutool-crypto/src/main/java/cn/hutool/crypto/BCUtil.java
+++ b/hutool-crypto/src/main/java/cn/hutool/crypto/BCUtil.java
@@ -1,29 +1,27 @@
package cn.hutool.crypto;
import cn.hutool.core.util.HexUtil;
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
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.jcajce.provider.asymmetric.util.EC5Util;
+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 java.math.BigInteger;
import java.security.GeneralSecurityException;
-import java.security.KeyFactory;
+import java.security.InvalidKeyException;
+import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
-import java.security.spec.ECFieldFp;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
-import java.security.spec.EllipticCurve;
/**
* Bouncy Castle相关工具类封装
@@ -70,68 +68,99 @@ public class BCUtil {
}
/**
- * 解码恢复EC压缩公钥,支持Base64和Hex编码,(基于BouncyCastle)
- * 见:https://www.cnblogs.com/xinzhao/p/8963724.html
+ * 解码恢复EC压缩公钥,支持Base64和Hex编码,(基于BouncyCastle)
*
* @param encodeByte 压缩公钥
- * @param curveName EC曲线名,例如{@link KeyUtil#SM2_DEFAULT_CURVE}
+ * @param curveName EC曲线名,例如{@link SmUtil#SM2_DOMAIN_PARAMS}
* @return 公钥
* @since 4.4.4
*/
public static PublicKey decodeECPoint(byte[] encodeByte, String curveName) {
- final ECNamedCurveParameterSpec namedSpec = ECNamedCurveTable.getParameterSpec(curveName);
- final ECCurve curve = namedSpec.getCurve();
- final EllipticCurve ecCurve = new EllipticCurve(//
- new ECFieldFp(curve.getField().getCharacteristic()), //
- curve.getA().toBigInteger(), //
- curve.getB().toBigInteger());
- // 根据X恢复点Y
- final ECPoint point = ECPointUtil.decodePoint(ecCurve, encodeByte);
+ final X9ECParameters x9ECParameters = ECUtil.getNamedCurveByName(curveName);
+ final ECCurve curve = x9ECParameters.getCurve();
+ final ECPoint point = EC5Util.convertPoint(curve.decodePoint(encodeByte));
// 根据曲线恢复公钥格式
- ECNamedCurveSpec ecSpec = new ECNamedCurveSpec(curveName, curve, namedSpec.getG(), namedSpec.getN());
+ final ECNamedCurveSpec ecSpec = new ECNamedCurveSpec(curveName, curve, x9ECParameters.getG(), x9ECParameters.getN());
- final KeyFactory PubKeyGen = KeyUtil.getKeyFactory("EC");
try {
- return PubKeyGen.generatePublic(new ECPublicKeySpec(point, ecSpec));
+ return KeyUtil.getKeyFactory("EC").generatePublic(new ECPublicKeySpec(point, ecSpec));
} catch (GeneralSecurityException e) {
throw new CryptoException(e);
}
}
/**
- * ECKey转换为ECKeyParameters
+ * 构建ECDomainParameters对象
*
- * @param ecKey BCECPrivateKey或者BCECPublicKey
- * @return ECPrivateKeyParameters或者ECPublicKeyParameters
- * @since 5.1.6
+ * @param parameterSpec ECParameterSpec
+ * @return {@link ECDomainParameters}
+ * @since 5.2.0
*/
- public static ECKeyParameters toParams(ECKey ecKey) {
- final ECParameterSpec parameterSpec = ecKey.getParameters();
- final ECDomainParameters ecDomainParameters = toDomainParameters(parameterSpec);
+ public static ECDomainParameters toDomainParams(ECParameterSpec parameterSpec) {
+ return new ECDomainParameters(
+ parameterSpec.getCurve(),
+ parameterSpec.getG(),
+ parameterSpec.getN(),
+ parameterSpec.getH());
+ }
- if (ecKey instanceof BCECPrivateKey) {
- return new ECPrivateKeyParameters(((BCECPrivateKey) ecKey).getD(), ecDomainParameters);
- } else if (ecKey instanceof BCECPublicKey) {
- return new ECPublicKeyParameters(((BCECPublicKey) ecKey).getQ(), ecDomainParameters);
+ /**
+ * 构建ECDomainParameters对象
+ *
+ * @param curveName Curve名称
+ * @return {@link ECDomainParameters}
+ * @since 5.2.0
+ */
+ public static ECDomainParameters toDomainParams(String curveName) {
+ return toDomainParams(ECUtil.getNamedCurveByName(curveName));
+ }
+
+ /**
+ * 构建ECDomainParameters对象
+ *
+ * @param x9ECParameters {@link X9ECParameters}
+ * @return {@link ECDomainParameters}
+ * @since 5.2.0
+ */
+ public static ECDomainParameters toDomainParams(X9ECParameters x9ECParameters) {
+ return new ECDomainParameters(
+ x9ECParameters.getCurve(),
+ x9ECParameters.getG(),
+ x9ECParameters.getN(),
+ x9ECParameters.getH()
+ );
+ }
+
+ /**
+ * 密钥转换为AsymmetricKeyParameter
+ *
+ * @param key PrivateKey或者PublicKey
+ * @return ECPrivateKeyParameters或者ECPublicKeyParameters
+ * @since 5.2.0
+ */
+ public static AsymmetricKeyParameter toParams(Key key) {
+ try {
+ if (key instanceof PrivateKey) {
+ return ECUtil.generatePrivateKeyParameter((PrivateKey) key);
+ } else if (key instanceof PublicKey) {
+ return ECUtil.generatePublicKeyParameter((PublicKey) key);
+ }
+ } catch (InvalidKeyException e) {
+ throw new CryptoException(e);
}
return null;
}
/**
- * 构建ECDomainParameters对象
+ * 转换为 ECPrivateKeyParameters
*
- * @param parameterSpec ECParameterSpec
- * @return ECDomainParameters
- * @since 5.1.6
+ * @param dHex 私钥d值16进制字符串
+ * @return ECPrivateKeyParameters
*/
- public static ECDomainParameters toDomainParameters(ECParameterSpec parameterSpec) {
- return new ECDomainParameters(
- parameterSpec.getCurve(),
- parameterSpec.getG(),
- parameterSpec.getN(),
- parameterSpec.getH());
+ public static ECPrivateKeyParameters toSm2Params(String dHex) {
+ return toSm2Params(HexUtil.toBigInteger(dHex));
}
/**
@@ -142,7 +171,38 @@ public class BCUtil {
* @return ECPrivateKeyParameters
*/
public static ECPrivateKeyParameters toParams(String dHex, ECDomainParameters domainParameters) {
- return new ECPrivateKeyParameters(new BigInteger(dHex, 16), domainParameters);
+ return toParams(new BigInteger(dHex, 16), domainParameters);
+ }
+
+ /**
+ * 转换为 ECPrivateKeyParameters
+ *
+ * @param d 私钥d值
+ * @return ECPrivateKeyParameters
+ */
+ public static ECPrivateKeyParameters toSm2Params(byte[] d) {
+ return toSm2Params(new BigInteger(d));
+ }
+
+ /**
+ * 转换为 ECPrivateKeyParameters
+ *
+ * @param d 私钥d值
+ * @param domainParameters ECDomainParameters
+ * @return ECPrivateKeyParameters
+ */
+ public static ECPrivateKeyParameters toParams(byte[] d, ECDomainParameters domainParameters) {
+ return toParams(new BigInteger(d), domainParameters);
+ }
+
+ /**
+ * 转换为 ECPrivateKeyParameters
+ *
+ * @param d 私钥d值
+ * @return ECPrivateKeyParameters
+ */
+ public static ECPrivateKeyParameters toSm2Params(BigInteger d) {
+ return toParams(d, SmUtil.SM2_DOMAIN_PARAMS);
}
/**
@@ -153,6 +213,9 @@ public class BCUtil {
* @return ECPrivateKeyParameters
*/
public static ECPrivateKeyParameters toParams(BigInteger d, ECDomainParameters domainParameters) {
+ if(null == d){
+ return null;
+ }
return new ECPrivateKeyParameters(d, domainParameters);
}
@@ -161,12 +224,25 @@ public class BCUtil {
*
* @param x 公钥X
* @param y 公钥Y
- * @param curve ECCurve
* @param domainParameters ECDomainParameters
* @return ECPublicKeyParameters
*/
- public static ECPublicKeyParameters toParams(BigInteger x, BigInteger y, ECCurve curve, ECDomainParameters domainParameters) {
- return toParams(x.toByteArray(), y.toByteArray(), curve, domainParameters);
+ public static ECPublicKeyParameters toParams(BigInteger x, BigInteger y, ECDomainParameters domainParameters) {
+ if(null == x || null == y){
+ return null;
+ }
+ return toParams(x.toByteArray(), y.toByteArray(), domainParameters);
+ }
+
+ /**
+ * 转换为SM2的ECPublicKeyParameters
+ *
+ * @param xHex 公钥X
+ * @param yHex 公钥Y
+ * @return ECPublicKeyParameters
+ */
+ public static ECPublicKeyParameters toSm2Params(String xHex, String yHex) {
+ return toParams(xHex, yHex, SmUtil.SM2_DOMAIN_PARAMS);
}
/**
@@ -174,13 +250,22 @@ public class BCUtil {
*
* @param xHex 公钥X
* @param yHex 公钥Y
- * @param curve ECCurve
* @param domainParameters ECDomainParameters
* @return ECPublicKeyParameters
*/
- public static ECPublicKeyParameters toParams(String xHex, String yHex, ECCurve curve, ECDomainParameters domainParameters) {
- return toParams(HexUtil.decodeHex(xHex), HexUtil.decodeHex(yHex),
- curve, domainParameters);
+ public static ECPublicKeyParameters toParams(String xHex, String yHex, ECDomainParameters domainParameters) {
+ return toParams(HexUtil.decodeHex(xHex), HexUtil.decodeHex(yHex), domainParameters);
+ }
+
+ /**
+ * 转换为SM2的ECPublicKeyParameters
+ *
+ * @param xBytes 公钥X
+ * @param yBytes 公钥Y
+ * @return ECPublicKeyParameters
+ */
+ public static ECPublicKeyParameters toSm2Params(byte[] xBytes, byte[] yBytes) {
+ return toParams(xBytes, yBytes, SmUtil.SM2_DOMAIN_PARAMS);
}
/**
@@ -188,47 +273,89 @@ public class BCUtil {
*
* @param xBytes 公钥X
* @param yBytes 公钥Y
- * @param curve ECCurve
* @param domainParameters ECDomainParameters
* @return ECPublicKeyParameters
*/
- public static ECPublicKeyParameters toParams(byte[] xBytes, byte[] yBytes, ECCurve curve, ECDomainParameters domainParameters) {
- final byte uncompressedFlag = 0x04;
- int curveLength = getCurveLength(domainParameters);
- xBytes = fixLength(curveLength, xBytes);
- yBytes = fixLength(curveLength, yBytes);
- byte[] encodedPubKey = new byte[1 + xBytes.length + yBytes.length];
- encodedPubKey[0] = uncompressedFlag;
- System.arraycopy(xBytes, 0, encodedPubKey, 1, xBytes.length);
- System.arraycopy(yBytes, 0, encodedPubKey, 1 + xBytes.length, yBytes.length);
+ public static ECPublicKeyParameters toParams(byte[] xBytes, byte[] yBytes, ECDomainParameters domainParameters) {
+ if(null == xBytes || null == yBytes){
+ return null;
+ }
+ final ECCurve curve = domainParameters.getCurve();
+ final int curveLength = getCurveLength(curve);
+ final byte[] encodedPubKey = encodePoint(xBytes, yBytes, curveLength);
return new ECPublicKeyParameters(curve.decodePoint(encodedPubKey), domainParameters);
}
/**
- * 获取Curve长度
+ * 公钥转换为 {@link ECPublicKeyParameters}
*
- * @param ecKey Curve
- * @return Curve长度
+ * @param publicKey 公钥,传入null返回null
+ * @return {@link ECPublicKeyParameters}或null
*/
- public static int getCurveLength(ECKeyParameters ecKey) {
- return getCurveLength(ecKey.getParameters());
+ public static ECPublicKeyParameters toParams(PublicKey publicKey) {
+ if (null == publicKey) {
+ return null;
+ }
+ try {
+ return (ECPublicKeyParameters) ECUtil.generatePublicKeyParameter(publicKey);
+ } catch (InvalidKeyException e) {
+ throw new CryptoException(e);
+ }
+ }
+
+ /**
+ * 私钥转换为 {@link ECPrivateKeyParameters}
+ *
+ * @param privateKey 私钥,传入null返回null
+ * @return {@link ECPrivateKeyParameters}或null
+ */
+ public static ECPrivateKeyParameters toParams(PrivateKey privateKey) {
+ if (null == privateKey) {
+ return null;
+ }
+ try {
+ return (ECPrivateKeyParameters) ECUtil.generatePrivateKeyParameter(privateKey);
+ } catch (InvalidKeyException e) {
+ throw new CryptoException(e);
+ }
+ }
+
+ /**
+ * 将X,Y曲线点编码为bytes
+ *
+ * @param xBytes X坐标bytes
+ * @param yBytes Y坐标bytes
+ * @param curveLength 曲线编码后的长度
+ * @return 编码bytes
+ */
+ private static byte[] encodePoint(byte[] xBytes, byte[] yBytes, int curveLength) {
+ xBytes = fixLength(curveLength, xBytes);
+ yBytes = fixLength(curveLength, yBytes);
+ final byte[] encodedPubKey = new byte[1 + xBytes.length + yBytes.length];
+
+ // 压缩类型:无压缩
+ encodedPubKey[0] = 0x04;
+ System.arraycopy(xBytes, 0, encodedPubKey, 1, xBytes.length);
+ System.arraycopy(yBytes, 0, encodedPubKey, 1 + xBytes.length, yBytes.length);
+
+ return encodedPubKey;
}
/**
* 获取Curve长度
*
- * @param domainParams ECDomainParameters
+ * @param curve {@link ECCurve}
* @return Curve长度
*/
- public static int getCurveLength(ECDomainParameters domainParams) {
- return (domainParams.getCurve().getFieldSize() + 7) / 8;
+ private static int getCurveLength(ECCurve curve) {
+ return (curve.getFieldSize() + 7) / 8;
}
/**
* 修正长度
*
* @param curveLength 修正后的长度
- * @param src bytes
+ * @param src bytes
* @return 修正后的bytes
*/
private static byte[] fixLength(int curveLength, byte[] src) {
diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java b/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java
index defd400c0..aad2a8a73 100644
--- a/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java
+++ b/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java
@@ -93,7 +93,7 @@ public class KeyUtil {
* Default SM2 curve
*
*/
- public static final String SM2_DEFAULT_CURVE = "sm2p256v1";
+ public static final String SM2_DEFAULT_CURVE = SmUtil.SM2_CURVE_NAME;
/**
* 生成 {@link SecretKey},仅用于对称加密和摘要算法密钥生成
diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/SmUtil.java b/hutool-crypto/src/main/java/cn/hutool/crypto/SmUtil.java
index 09a189d51..0c292b38b 100644
--- a/hutool-crypto/src/main/java/cn/hutool/crypto/SmUtil.java
+++ b/hutool-crypto/src/main/java/cn/hutool/crypto/SmUtil.java
@@ -13,10 +13,9 @@ import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.params.ECDomainParameters;
-import org.bouncycastle.math.ec.ECPoint;
-import org.bouncycastle.math.ec.custom.gm.SM2P256V1Curve;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Hex;
@@ -28,30 +27,31 @@ import java.math.BigInteger;
/**
* SM国密算法工具类
* 此工具类依赖org.bouncycastle:bcpkix-jdk15on
- *
+ *
* @author looly
* @since 4.3.2
*/
public class SmUtil {
- /*
+ /**
+ * SM2默认曲线
+ */
+ public static final String SM2_CURVE_NAME = "sm2p256v1";
+ /**
* SM2推荐曲线参数(来自https://github.com/ZZMarquis/gmhelper)
*/
- public static final SM2P256V1Curve CURVE = new SM2P256V1Curve();
- public final static BigInteger SM2_ECC_GX = new BigInteger(
- "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16);
- public final static BigInteger SM2_ECC_GY = new BigInteger(
- "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16);
- public static final ECPoint G_POINT = CURVE.createPoint(SM2_ECC_GX, SM2_ECC_GY);
- public static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(CURVE, G_POINT,
- CURVE.getOrder(), CURVE.getCofactor());
+ public static final ECDomainParameters SM2_DOMAIN_PARAMS;
private final static int RS_LEN = 32;
+ static {
+ SM2_DOMAIN_PARAMS = BCUtil.toDomainParams(GMNamedCurves.getByName(SM2_CURVE_NAME));
+ }
+
/**
* 创建SM2算法对象
* 生成新的私钥公钥对
- *
+ *
* @return {@link SM2}
*/
public static SM2 sm2() {
@@ -62,9 +62,9 @@ public class SmUtil {
* 创建SM2算法对象
* 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
- *
+ *
* @param privateKeyStr 私钥Hex或Base64表示
- * @param publicKeyStr 公钥Hex或Base64表示
+ * @param publicKeyStr 公钥Hex或Base64表示
* @return {@link SM2}
*/
public static SM2 sm2(String privateKeyStr, String publicKeyStr) {
@@ -75,9 +75,9 @@ public class SmUtil {
* 创建SM2算法对象
* 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
- *
+ *
* @param privateKey 私钥
- * @param publicKey 公钥
+ * @param publicKey 公钥
* @return {@link SM2}
*/
public static SM2 sm2(byte[] privateKey, byte[] publicKey) {
@@ -89,7 +89,7 @@ public class SmUtil {
* 例:
* SM3加密:sm3().digest(data)
* SM3加密并转为16进制字符串:sm3().digestHex(data)
- *
+ *
* @return {@link SM3}
*/
public static SM3 sm3() {
@@ -98,7 +98,7 @@ public class SmUtil {
/**
* SM3加密,生成16进制SM3字符串
- *
+ *
* @param data 数据
* @return SM3字符串
*/
@@ -108,7 +108,7 @@ public class SmUtil {
/**
* SM3加密,生成16进制SM3字符串
- *
+ *
* @param data 数据
* @return SM3字符串
*/
@@ -118,7 +118,7 @@ public class SmUtil {
/**
* SM3加密文件,生成16进制SM3字符串
- *
+ *
* @param dataFile 被加密文件
* @return SM3字符串
*/
@@ -129,12 +129,12 @@ public class SmUtil {
/**
* SM4加密,生成随机KEY。注意解密时必须使用相同 {@link SymmetricCrypto}对象或者使用相同KEY
* 例:
- *
+ *
*
* SM4加密:sm4().encrypt(data) * SM4解密:sm4().decrypt(data) *- * + * * @return {@link SymmetricCrypto} */ public static SM4 sm4() { @@ -144,12 +144,12 @@ public class SmUtil { /** * SM4加密
* SM4加密:sm4(key).encrypt(data) * SM4解密:sm4(key).decrypt(data) *- * + * * @param key 密钥 * @return {@link SymmetricCrypto} */ @@ -159,8 +159,8 @@ public class SmUtil { /** * bc加解密使用旧标c1||c2||c3,此方法在加密后调用,将结果转化为c1||c3||c2 - * - * @param c1c2c3 加密后的bytes,顺序为C1C2C3 + * + * @param c1c2c3 加密后的bytes,顺序为C1C2C3 * @param ecDomainParameters {@link ECDomainParameters} * @return 加密后的bytes,顺序为C1C3C2 */ @@ -177,8 +177,8 @@ public class SmUtil { /** * bc加解密使用旧标c1||c3||c2,此方法在解密前调用,将密文转化为c1||c2||c3再去解密 - * - * @param c1c3c2 加密后的bytes,顺序为C1C3C2 + * + * @param c1c3c2 加密后的bytes,顺序为C1C3C2 * @param ecDomainParameters {@link ECDomainParameters} * @return c1c2c3 加密后的bytes,顺序为C1C2C3 */ @@ -196,7 +196,7 @@ public class SmUtil { /** * BC的SM3withSM2签名得到的结果的rs是asn1格式的,这个方法转化成直接拼接r||s
* 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
- *
- * @param algorithm 算法
+ *
+ * @param algorithm 算法
* @param privateKey 私钥
- * @param publicKey 公钥
+ * @param publicKey 公钥
* @since 3.1.1
*/
public BaseAsymmetric(String algorithm, PrivateKey privateKey, PublicKey publicKey) {
@@ -49,10 +59,10 @@ public class BaseAsymmetric
* 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密(签名)或者解密(校验)
- *
- * @param algorithm 算法
+ *
+ * @param algorithm 算法
* @param privateKey 私钥
- * @param publicKey 公钥
+ * @param publicKey 公钥
* @return this
*/
@SuppressWarnings("unchecked")
@@ -74,7 +84,7 @@ public class BaseAsymmetric
+ * 私钥和公钥同时为空时生成一对新的私钥和公钥
+ * 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
+ *
+ * @param privateKeyHex 私钥16进制
+ * @param publicKeyPointXHex 公钥X16进制
+ * @param publicKeyPointYHex 公钥Y16进制
+ * @since 5.2.0
+ */
+ public SM2(String privateKeyHex, String publicKeyPointXHex, String publicKeyPointYHex) {
+ this(BCUtil.toSm2Params(privateKeyHex), BCUtil.toSm2Params(publicKeyPointXHex, publicKeyPointYHex));
+ }
+
+ /**
+ * 构造
+ * 私钥和公钥同时为空时生成一对新的私钥和公钥
+ * 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
+ *
+ * @param privateKey 私钥
+ * @param publicKeyPointX 公钥X
+ * @param publicKeyPointY 公钥Y
+ * @since 5.2.0
+ */
+ public SM2(byte[] privateKey, byte[] publicKeyPointX, byte[] publicKeyPointY) {
+ this(BCUtil.toSm2Params(privateKey), BCUtil.toSm2Params(publicKeyPointX, publicKeyPointY));
+ }
+
+ /**
+ * 构造
+ * 私钥和公钥同时为空时生成一对新的私钥和公钥
+ * 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
+ *
+ * @param privateKeyParams 私钥
+ * @param publicKeyParams 公钥
+ */
+ public SM2(ECPrivateKeyParameters privateKeyParams, ECPublicKeyParameters publicKeyParams) {
+ super(ALGORITHM_SM2, null, null);
+ this.privateKeyParams = privateKeyParams;
+ this.publicKeyParams = publicKeyParams;
+ this.init();
}
// ------------------------------------------------------------------ Constructor end
@@ -93,18 +143,22 @@ public class SM2 extends AbstractAsymmetricCrypto
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密(签名)或者解密(校验)
*
- * @param privateKey 私钥
- * @param publicKey 公钥
* @return this
*/
- public SM2 init(PrivateKey privateKey, PublicKey publicKey) {
- return this.init(ALGORITHM_SM2, privateKey, publicKey);
+ public SM2 init() {
+ if (null == this.privateKeyParams && null == this.publicKeyParams) {
+ super.initKeys();
+ this.privateKeyParams = BCUtil.toParams(this.privateKey);
+ this.publicKeyParams = BCUtil.toParams(this.publicKey);
+ }
+ return this;
}
@Override
- protected SM2 init(String algorithm, PrivateKey privateKey, PublicKey publicKey) {
- super.init(algorithm, privateKey, publicKey);
- return initCipherParams();
+ public SM2 initKeys() {
+ // 阻断父类中自动生成密钥对的操作,此操作由本类中进行。
+ // 由于用户可能传入Params而非key,因此此时key必定为null,故此不再生成
+ return this;
}
// --------------------------------------------------------------------------------- Encrypt
@@ -202,6 +256,16 @@ public class SM2 extends AbstractAsymmetricCrypto