From 32c4952d3188ce2b204b20f4d5874a5b3b6bef0a Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 26 Feb 2021 22:50:35 +0800 Subject: [PATCH] add method --- CHANGELOG.md | 3 +- .../hutool/core/collection/CollUtilTest.java | 11 ++ .../main/java/cn/hutool/crypto/ECKeyUtil.java | 119 +++++++++++++++++- .../main/java/cn/hutool/crypto/KeyUtil.java | 6 +- .../main/java/cn/hutool/crypto/PemUtil.java | 10 +- .../main/java/cn/hutool/crypto/SmUtil.java | 49 +++++++- .../java/cn/hutool/crypto/asymmetric/SM2.java | 12 +- .../java/cn/hutool/crypto/digest/SM3.java | 2 +- .../cn/hutool/crypto/test/PemUtilTest.java | 19 +++ .../crypto/test/asymmetric/SM2Test.java | 46 +++++-- 10 files changed, 243 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0321de887..a29c00be7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------------------------------------- -# 5.5.9 (2021-02-25) +# 5.5.9 (2021-02-26) ### 新特性 * 【crypto 】 PemUtil.readPemKey支持EC(pr#1366@Github) @@ -13,6 +13,7 @@ * 【cache 】 AbstractCache增加keySet方法(issue#I37Z4C@Gitee) * 【core 】 NumberWordFormatter增加formatSimple方法(pr#1436@Github) * 【crypto 】 增加读取openSSL生成的sm2私钥 +* 【crypto 】 增加众多方法,SM2兼容各类密钥格式(issue#I37Z75@Gitee) ### Bug修复 * 【json 】 JSONUtil.isJson方法改变trim策略,解决特殊空白符导致判断失败问题 diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java index aa16fcab4..076dd64fb 100644 --- a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java @@ -11,6 +11,7 @@ import org.junit.Assert; import org.junit.Test; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -694,4 +695,14 @@ public class CollUtilTest { Assert.assertEquals(0, CollUtil.page(3, 5, objects).size()); } + + @Test + public void subtractToListTest(){ + List list1 = Arrays.asList(1L, 2L, 3L); + List list2 = Arrays.asList(2L, 3L); + + List result = CollUtil.subtractToList(list1, list2); + Assert.assertEquals(1, result.size()); + Assert.assertEquals(1L, result.get(0), 1); + } } diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/ECKeyUtil.java b/hutool-crypto/src/main/java/cn/hutool/crypto/ECKeyUtil.java index 055d0bf57..283101da8 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/ECKeyUtil.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/ECKeyUtil.java @@ -11,7 +11,11 @@ import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; +import org.bouncycastle.jcajce.spec.OpenSSHPrivateKeySpec; +import org.bouncycastle.jcajce.spec.OpenSSHPublicKeySpec; import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.math.ec.FixedPointCombMultiplier; import org.bouncycastle.util.BigIntegers; import java.io.IOException; @@ -20,6 +24,7 @@ import java.security.InvalidKeyException; import java.security.Key; import java.security.PrivateKey; import java.security.PublicKey; +import java.security.spec.KeySpec; /** * EC密钥参数相关工具类封装 @@ -45,7 +50,21 @@ public class ECKeyUtil { return null; } + /** + * 根据私钥参数获取公钥参数 + * + * @param privateKeyParameters 私钥参数 + * @return 公钥参数 + * @since 5.5.9 + */ + public static ECPublicKeyParameters getPublicParams(ECPrivateKeyParameters privateKeyParameters) { + final ECDomainParameters domainParameters = privateKeyParameters.getParameters(); + final ECPoint q = new FixedPointCombMultiplier().multiply(domainParameters.getG(), privateKeyParameters.getD()); + return new ECPublicKeyParameters(q, domainParameters); + } + //--------------------------------------------------------------------------- Public Key + /** * 转换为 ECPublicKeyParameters * @@ -91,8 +110,8 @@ public class ECKeyUtil { /** * 转换为ECPublicKeyParameters * - * @param x 公钥X - * @param y 公钥Y + * @param x 公钥X + * @param y 公钥Y * @param domainParameters ECDomainParameters * @return ECPublicKeyParameters,x或y为{@code null}则返回{@code null} */ @@ -109,7 +128,7 @@ public class ECKeyUtil { * @return ECPublicKeyParameters */ public static ECPublicKeyParameters toPublicParams(byte[] xBytes, byte[] yBytes, ECDomainParameters domainParameters) { - if(null == xBytes || null == yBytes){ + if (null == xBytes || null == yBytes) { return null; } return toPublicParams(BigIntegers.fromUnsignedByteArray(xBytes), BigIntegers.fromUnsignedByteArray(yBytes), domainParameters); @@ -187,6 +206,7 @@ public class ECKeyUtil { } //--------------------------------------------------------------------------- Private Key + /** * 转换为 ECPrivateKeyParameters * @@ -220,7 +240,7 @@ public class ECKeyUtil { /** * 转换为 ECPrivateKeyParameters * - * @param d 私钥d值16进制字符串 + * @param d 私钥d值16进制字符串 * @param domainParameters ECDomainParameters * @return ECPrivateKeyParameters */ @@ -272,10 +292,11 @@ public class ECKeyUtil { /** * 将SM2算法的{@link ECPrivateKey} 转换为 {@link PrivateKey} + * * @param privateKey {@link ECPrivateKey} * @return {@link PrivateKey} */ - public static PrivateKey toSm2PrivateKey(ECPrivateKey privateKey){ + public static PrivateKey toSm2PrivateKey(ECPrivateKey privateKey) { try { final PrivateKeyInfo info = new PrivateKeyInfo( new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, SmUtil.ID_SM2_PUBLIC_KEY_PARAM), privateKey); @@ -284,4 +305,92 @@ public class ECKeyUtil { throw new IORuntimeException(e); } } + + /** + * 创建{@link OpenSSHPrivateKeySpec} + * + * @param key 私钥,需为PKCS#1格式 + * @return {@link OpenSSHPrivateKeySpec} + * @since 5.5.9 + */ + public static KeySpec createOpenSSHPrivateKeySpec(byte[] key) { + return new OpenSSHPrivateKeySpec(key); + } + + /** + * 创建{@link OpenSSHPublicKeySpec} + * + * @param key 公钥,需为PKCS#1格式 + * @return {@link OpenSSHPublicKeySpec} + * @since 5.5.9 + */ + public static KeySpec createOpenSSHPublicKeySpec(byte[] key) { + return new OpenSSHPublicKeySpec(key); + } + + /** + * 尝试解析转换各种类型私钥为{@link ECPrivateKeyParameters},支持包括: + * + *
    + *
  • D值
  • + *
  • PKCS#8
  • + *
  • PKCS#1
  • + *
+ * + * @param privateKeyBytes 私钥 + * @return {@link ECPrivateKeyParameters} + * @since 5.5.9 + */ + public static ECPrivateKeyParameters decodePrivateKeyParams(byte[] privateKeyBytes) { + try { + // 尝试D值 + return toSm2PrivateParams(privateKeyBytes); + } catch (Exception ignore) { + // ignore + } + + PrivateKey privateKey; + //尝试PKCS#8 + try { + privateKey = KeyUtil.generatePrivateKey("sm2", privateKeyBytes); + } catch (Exception ignore) { + // 尝试PKCS#1 + privateKey = KeyUtil.generatePrivateKey("sm2", createOpenSSHPrivateKeySpec(privateKeyBytes)); + } + + return toPrivateParams(privateKey); + } + + /** + * 尝试解析转换各种类型公钥为{@link ECPublicKeyParameters},支持包括: + * + *
    + *
  • Q值
  • + *
  • X.509
  • + *
  • PKCS#1
  • + *
+ * + * @param publicKeyBytes 公钥 + * @return {@link ECPublicKeyParameters} + * @since 5.5.9 + */ + public static ECPublicKeyParameters decodePublicKeyParams(byte[] publicKeyBytes) { + try { + // 尝试Q值 + return toSm2PublicParams(publicKeyBytes); + } catch (Exception ignore) { + // ignore + } + + PublicKey publicKey; + //尝试X.509 + try { + publicKey = KeyUtil.generatePublicKey("sm2", publicKeyBytes); + } catch (Exception ignore) { + // 尝试PKCS#1 + publicKey = KeyUtil.generatePublicKey("sm2", createOpenSSHPublicKeySpec(publicKeyBytes)); + } + + return toPublicParams(publicKey); + } } 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 21e2e7cab..3d97f1fc1 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/KeyUtil.java @@ -256,8 +256,8 @@ public class KeyUtil { * 采用PKCS#8规范,此规范定义了私钥信息语法和加密私钥语法
* 算法见:https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#KeyFactory * - * @param algorithm 算法 - * @param key 密钥,必须为DER编码存储 + * @param algorithm 算法,如RSA、EC、SM2等 + * @param key 密钥,PKCS#8格式 * @return 私钥 {@link PrivateKey} */ public static PrivateKey generatePrivateKey(String algorithm, byte[] key) { @@ -271,7 +271,7 @@ public class KeyUtil { * 生成私钥,仅用于非对称加密
* 算法见:https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#KeyFactory * - * @param algorithm 算法 + * @param algorithm 算法,如RSA、EC、SM2等 * @param keySpec {@link KeySpec} * @return 私钥 {@link PrivateKey} * @since 3.1.1 diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/PemUtil.java b/hutool-crypto/src/main/java/cn/hutool/crypto/PemUtil.java index 5e3e29797..c7ca4205b 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/PemUtil.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/PemUtil.java @@ -3,7 +3,6 @@ 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.asn1.sec.ECPrivateKey; import org.bouncycastle.util.io.pem.PemObject; import org.bouncycastle.util.io.pem.PemObjectGenerator; import org.bouncycastle.util.io.pem.PemReader; @@ -134,14 +133,17 @@ public class PemUtil { } /** - * 读取OpenSSL生成的ANS1格式的Pem私钥文件 + * 读取OpenSSL生成的ANS1格式的Pem私钥文件,必须为PKCS#1格式 * * @param keyStream 私钥pem流 * @return {@link PrivateKey} */ public static PrivateKey readSm2PemPrivateKey(InputStream keyStream) { - final ECPrivateKey ecPrivateKey = ECPrivateKey.getInstance(readPem(keyStream)); - return ECKeyUtil.toSm2PrivateKey(ecPrivateKey); + try{ + return KeyUtil.generatePrivateKey("sm2", ECKeyUtil.createOpenSSHPrivateKeySpec(readPem(keyStream))); + } finally { + IoUtil.close(keyStream); + } } /** 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 2f8d61b7f..2bc3a2236 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/SmUtil.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/SmUtil.java @@ -14,6 +14,8 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.gm.GMNamedCurves; import org.bouncycastle.crypto.digests.SM3Digest; import org.bouncycastle.crypto.params.ECDomainParameters; +import org.bouncycastle.crypto.params.ECPrivateKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.signers.StandardDSAEncoding; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.encoders.Hex; @@ -22,11 +24,20 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; +import java.security.PrivateKey; +import java.security.PublicKey; /** * SM国密算法工具类
* 此工具类依赖org.bouncycastle:bcprov-jdk15to18 * + *

封装包括:

+ *
    + *
  • SM2 椭圆曲线非对称加密和签名
  • + *
  • SM3 杂凑算法
  • + *
  • SM4 对称加密
  • + *
+ * * @author looly * @since 4.3.2 */ @@ -74,14 +85,42 @@ public class SmUtil { * 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 * - * @param privateKey 私钥 - * @param publicKey 公钥 + * @param privateKey 私钥,必须使用PKCS#8规范 + * @param publicKey 公钥,必须使用X509规范 * @return {@link SM2} */ public static SM2 sm2(byte[] privateKey, byte[] publicKey) { return new SM2(privateKey, publicKey); } + /** + * 创建SM2算法对象
+ * 私钥和公钥同时为空时生成一对新的私钥和公钥
+ * 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 + * + * @param privateKey 私钥 + * @param publicKey 公钥 + * @return {@link SM2} + * @since 5.5.9 + */ + public static SM2 sm2(PrivateKey privateKey, PublicKey publicKey) { + return new SM2(privateKey, publicKey); + } + + /** + * 创建SM2算法对象
+ * 私钥和公钥同时为空时生成一对新的私钥和公钥
+ * 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 + * + * @param privateKeyParams 私钥参数 + * @param publicKeyParams 公钥参数 + * @return {@link SM2} + * @since 5.5.9 + */ + public static SM2 sm2(ECPrivateKeyParameters privateKeyParams, ECPublicKeyParameters publicKeyParams) { + return new SM2(privateKeyParams, publicKeyParams); + } + /** * SM3加密
* 例:
@@ -192,8 +231,7 @@ public class SmUtil { } /** - * BC的SM3withSM2签名得到的结果的rs是asn1格式的,这个方法转化成直接拼接r||s
- * 来自:https://blog.csdn.net/pridas/article/details/86118774 + * BC的SM3withSM2签名得到的结果的rs是asn1格式的,这个方法转化成直接拼接r||s * * @param rsDer rs in asn1 format * @return sign result in plain byte array @@ -214,8 +252,7 @@ public class SmUtil { } /** - * BC的SM3withSM2验签需要的rs是asn1格式的,这个方法将直接拼接r||s的字节数组转化成asn1格式
- * 来自:https://blog.csdn.net/pridas/article/details/86118774 + * BC的SM3withSM2验签需要的rs是asn1格式的,这个方法将直接拼接r||s的字节数组转化成asn1格式 * * @param sign in plain byte array * @return rs result in asn1 format 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 ad4c3cf78..48d05370f 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 @@ -4,7 +4,7 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.util.HexUtil; import cn.hutool.crypto.BCUtil; import cn.hutool.crypto.CryptoException; -import cn.hutool.crypto.KeyUtil; +import cn.hutool.crypto.ECKeyUtil; import cn.hutool.crypto.SecureUtil; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.Digest; @@ -74,13 +74,13 @@ public class SM2 extends AbstractAsymmetricCrypto { * 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 * - * @param privateKey 私钥,必须使用PKCS#8规范 - * @param publicKey 公钥,必须使用X509规范 + * @param privateKey 私钥,可以使用PKCS#8、D值或PKCS#1规范 + * @param publicKey 公钥,可以使用X509、Q值或PKCS#1规范 */ public SM2(byte[] privateKey, byte[] publicKey) { - this(// - KeyUtil.generatePrivateKey(ALGORITHM_SM2, privateKey), // - KeyUtil.generatePublicKey(ALGORITHM_SM2, publicKey)// + this( + ECKeyUtil.decodePrivateKeyParams(privateKey), + ECKeyUtil.decodePublicKeyParams(publicKey) ); } diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/digest/SM3.java b/hutool-crypto/src/main/java/cn/hutool/crypto/digest/SM3.java index 08f9c76a7..2b6b2afe5 100644 --- a/hutool-crypto/src/main/java/cn/hutool/crypto/digest/SM3.java +++ b/hutool-crypto/src/main/java/cn/hutool/crypto/digest/SM3.java @@ -1,7 +1,7 @@ package cn.hutool.crypto.digest; /** - * SM3算法 + * SM3杂凑算法 * * @author looly * @since 4.6.8 diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/test/PemUtilTest.java b/hutool-crypto/src/test/java/cn/hutool/crypto/test/PemUtilTest.java index 637c09c6f..f71d74f15 100644 --- a/hutool-crypto/src/test/java/cn/hutool/crypto/test/PemUtilTest.java +++ b/hutool-crypto/src/test/java/cn/hutool/crypto/test/PemUtilTest.java @@ -1,11 +1,14 @@ package cn.hutool.crypto.test; +import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.resource.ResourceUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.PemUtil; import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.asymmetric.RSA; import cn.hutool.crypto.asymmetric.SM2; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import java.nio.charset.StandardCharsets; @@ -58,4 +61,20 @@ public class PemUtilTest { // 64位签名 Assert.assertEquals(64, sign.length); } + + @Test + @Ignore + public void readECPrivateKeyTest2() { + // https://gitee.com/loolly/hutool/issues/I37Z75 + byte[] d = PemUtil.readPem(FileUtil.getInputStream("d:/test/keys/priv.key")); + byte[] publicKey = PemUtil.readPem(FileUtil.getInputStream("d:/test/keys/pub.key")); + + SM2 sm2 = new SM2(d, publicKey); + sm2.usePlainEncoding(); + + String content = "我是Hanley."; + byte[] sign = sm2.sign(StrUtil.utf8Bytes(content)); + boolean verify = sm2.verify(StrUtil.utf8Bytes(content), sign); + Assert.assertTrue(verify); + } } diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/test/asymmetric/SM2Test.java b/hutool-crypto/src/test/java/cn/hutool/crypto/test/asymmetric/SM2Test.java index 5399629cb..ffb5e1dbc 100644 --- a/hutool-crypto/src/test/java/cn/hutool/crypto/test/asymmetric/SM2Test.java +++ b/hutool-crypto/src/test/java/cn/hutool/crypto/test/asymmetric/SM2Test.java @@ -12,7 +12,7 @@ import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.asymmetric.SM2; import org.bouncycastle.crypto.engines.SM2Engine; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; -import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.jcajce.spec.OpenSSHPrivateKeySpec; import org.junit.Assert; import org.junit.Test; @@ -136,7 +136,7 @@ public class SM2Test { //签名值 String signHex = "2881346e038d2ed706ccdd025f2b1dafa7377d5cf090134b98756fafe084dddbcdba0ab00b5348ed48025195af3f1dda29e819bb66aa9d4d088050ff148482a1"; - final SM2 sm2 = new SM2(null, ECKeyUtil.toSm2PublicParams(publicKeyHex)); + final SM2 sm2 = new SM2(null, publicKeyHex); sm2.usePlainEncoding(); boolean verify = sm2.verify(dataBytes, HexUtil.decodeHex(signHex)); @@ -251,10 +251,7 @@ public class SM2Test { String data = "123456"; - final ECPublicKeyParameters ecPublicKeyParameters = ECKeyUtil.toSm2PublicParams(q); - final ECPrivateKeyParameters ecPrivateKeyParameters = ECKeyUtil.toSm2PrivateParams(d); - - final SM2 sm2 = new SM2(ecPrivateKeyParameters, ecPublicKeyParameters); + final SM2 sm2 = new SM2(d, q); sm2.setMode(SM2Engine.Mode.C1C2C3); final String encryptHex = sm2.encryptHex(data, KeyType.PublicKey); final String decryptStr = sm2.decryptStr(encryptHex, KeyType.PrivateKey); @@ -277,8 +274,41 @@ public class SM2Test { } @Test - public void test(){ - String priKey = "MHcCAQEEIE29XqAFV/rkJbnJzCoQRJLTeAHG2TR0h9ZCWag0+ZMEoAoGCCqBHM9VAYItoUQDQgAESkOzNigIsH5ehFvr9yQNQ66genyOrm+Q4umCA4aWXPeRzmcTAWSlTineiReTFN2lqor2xaulT8u3a4w3AM/F6A=="; + public void getPublicKeyByPrivateKeyTest(){ + // issue#I38SDP,openSSL生成的PKCS#1格式私钥 + String priKey = "MHcCAQEEIE29XqAFV/rkJbnJzCoQRJLTeAHG2TR0h9ZCWag0+ZMEoAoGCCqBHM9VAYItoUQDQgAESkOzNigIsH5ehFvr9y" + + "QNQ66genyOrm+Q4umCA4aWXPeRzmcTAWSlTineiReTFN2lqor2xaulT8u3a4w3AM/F6A=="; + + PrivateKey privateKey = KeyUtil.generatePrivateKey("sm2", new OpenSSHPrivateKeySpec(SecureUtil.decode(priKey))); + final ECPrivateKeyParameters privateKeyParameters = ECKeyUtil.toPrivateParams(privateKey); + + final SM2 sm2 = new SM2(privateKeyParameters, ECKeyUtil.getPublicParams(privateKeyParameters)); + + String src = "Sm2Test"; + byte[] data = sm2.encrypt(src, KeyType.PublicKey); + byte[] sign = sm2.sign(src.getBytes(StandardCharsets.UTF_8)); + + Assert.assertTrue(sm2.verify( src.getBytes(StandardCharsets.UTF_8), sign)); + + byte[] dec = sm2.decrypt(data, KeyType.PrivateKey); + Assert.assertArrayEquals(dec, src.getBytes(StandardCharsets.UTF_8)); + } + + @Test + public void readPublicKeyTest(){ + String priKey = "MHcCAQEEIE29XqAFV/rkJbnJzCoQRJLTeAHG2TR0h9ZCWag0+ZMEoAoGCCqBHM9VAYItoUQDQgAESkOzNigIsH5ehFvr9y" + + "QNQ66genyOrm+Q4umCA4aWXPeRzmcTAWSlTineiReTFN2lqor2xaulT8u3a4w3AM/F6A=="; String pubKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAESkOzNigIsH5ehFvr9yQNQ66genyOrm+Q4umCA4aWXPeRzmcTAWSlTineiReTFN2lqor2xaulT8u3a4w3AM/F6A=="; + + SM2 sm2 = SmUtil.sm2(priKey, pubKey); + + String src = "Sm2Test中文"; + byte[] data = sm2.encrypt(src, KeyType.PublicKey); + byte[] sign = sm2.sign(src.getBytes(StandardCharsets.UTF_8)); + + Assert.assertTrue(sm2.verify( src.getBytes(StandardCharsets.UTF_8), sign)); + + byte[] dec = sm2.decrypt(data, KeyType.PrivateKey); + Assert.assertArrayEquals(dec, src.getBytes(StandardCharsets.UTF_8)); } }