add method

This commit is contained in:
Looly
2021-02-26 22:50:35 +08:00
parent ba8b4ad760
commit 32c4952d31
10 changed files with 243 additions and 34 deletions

View File

@@ -3,7 +3,7 @@
------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
# 5.5.9 (2021-02-25) # 5.5.9 (2021-02-26)
### 新特性 ### 新特性
* 【crypto 】 PemUtil.readPemKey支持ECpr#1366@Github * 【crypto 】 PemUtil.readPemKey支持ECpr#1366@Github
@@ -13,6 +13,7 @@
* 【cache 】 AbstractCache增加keySet方法issue#I37Z4C@Gitee * 【cache 】 AbstractCache增加keySet方法issue#I37Z4C@Gitee
* 【core 】 NumberWordFormatter增加formatSimple方法pr#1436@Github * 【core 】 NumberWordFormatter增加formatSimple方法pr#1436@Github
* 【crypto 】 增加读取openSSL生成的sm2私钥 * 【crypto 】 增加读取openSSL生成的sm2私钥
* 【crypto 】 增加众多方法SM2兼容各类密钥格式issue#I37Z75@Gitee
### Bug修复 ### Bug修复
* 【json 】 JSONUtil.isJson方法改变trim策略解决特殊空白符导致判断失败问题 * 【json 】 JSONUtil.isJson方法改变trim策略解决特殊空白符导致判断失败问题

View File

@@ -11,6 +11,7 @@ import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@@ -694,4 +695,14 @@ public class CollUtilTest {
Assert.assertEquals(0, CollUtil.page(3, 5, objects).size()); Assert.assertEquals(0, CollUtil.page(3, 5, objects).size());
} }
@Test
public void subtractToListTest(){
List<Long> list1 = Arrays.asList(1L, 2L, 3L);
List<Long> list2 = Arrays.asList(2L, 3L);
List<Long> result = CollUtil.subtractToList(list1, list2);
Assert.assertEquals(1, result.size());
Assert.assertEquals(1L, result.get(0), 1);
}
} }

View File

@@ -11,7 +11,11 @@ import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; 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.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.FixedPointCombMultiplier;
import org.bouncycastle.util.BigIntegers; import org.bouncycastle.util.BigIntegers;
import java.io.IOException; import java.io.IOException;
@@ -20,6 +24,7 @@ import java.security.InvalidKeyException;
import java.security.Key; import java.security.Key;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.spec.KeySpec;
/** /**
* EC密钥参数相关工具类封装 * EC密钥参数相关工具类封装
@@ -45,7 +50,21 @@ public class ECKeyUtil {
return null; 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 //--------------------------------------------------------------------------- Public Key
/** /**
* 转换为 ECPublicKeyParameters * 转换为 ECPublicKeyParameters
* *
@@ -91,8 +110,8 @@ public class ECKeyUtil {
/** /**
* 转换为ECPublicKeyParameters * 转换为ECPublicKeyParameters
* *
* @param x 公钥X * @param x 公钥X
* @param y 公钥Y * @param y 公钥Y
* @param domainParameters ECDomainParameters * @param domainParameters ECDomainParameters
* @return ECPublicKeyParametersx或y为{@code null}则返回{@code null} * @return ECPublicKeyParametersx或y为{@code null}则返回{@code null}
*/ */
@@ -109,7 +128,7 @@ public class ECKeyUtil {
* @return ECPublicKeyParameters * @return ECPublicKeyParameters
*/ */
public static ECPublicKeyParameters toPublicParams(byte[] xBytes, byte[] yBytes, ECDomainParameters domainParameters) { public static ECPublicKeyParameters toPublicParams(byte[] xBytes, byte[] yBytes, ECDomainParameters domainParameters) {
if(null == xBytes || null == yBytes){ if (null == xBytes || null == yBytes) {
return null; return null;
} }
return toPublicParams(BigIntegers.fromUnsignedByteArray(xBytes), BigIntegers.fromUnsignedByteArray(yBytes), domainParameters); return toPublicParams(BigIntegers.fromUnsignedByteArray(xBytes), BigIntegers.fromUnsignedByteArray(yBytes), domainParameters);
@@ -187,6 +206,7 @@ public class ECKeyUtil {
} }
//--------------------------------------------------------------------------- Private Key //--------------------------------------------------------------------------- Private Key
/** /**
* 转换为 ECPrivateKeyParameters * 转换为 ECPrivateKeyParameters
* *
@@ -220,7 +240,7 @@ public class ECKeyUtil {
/** /**
* 转换为 ECPrivateKeyParameters * 转换为 ECPrivateKeyParameters
* *
* @param d 私钥d值16进制字符串 * @param d 私钥d值16进制字符串
* @param domainParameters ECDomainParameters * @param domainParameters ECDomainParameters
* @return ECPrivateKeyParameters * @return ECPrivateKeyParameters
*/ */
@@ -272,10 +292,11 @@ public class ECKeyUtil {
/** /**
* 将SM2算法的{@link ECPrivateKey} 转换为 {@link PrivateKey} * 将SM2算法的{@link ECPrivateKey} 转换为 {@link PrivateKey}
*
* @param privateKey {@link ECPrivateKey} * @param privateKey {@link ECPrivateKey}
* @return {@link PrivateKey} * @return {@link PrivateKey}
*/ */
public static PrivateKey toSm2PrivateKey(ECPrivateKey privateKey){ public static PrivateKey toSm2PrivateKey(ECPrivateKey privateKey) {
try { try {
final PrivateKeyInfo info = new PrivateKeyInfo( final PrivateKeyInfo info = new PrivateKeyInfo(
new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, SmUtil.ID_SM2_PUBLIC_KEY_PARAM), privateKey); new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, SmUtil.ID_SM2_PUBLIC_KEY_PARAM), privateKey);
@@ -284,4 +305,92 @@ public class ECKeyUtil {
throw new IORuntimeException(e); 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},支持包括:
*
* <ul>
* <li>D值</li>
* <li>PKCS#8</li>
* <li>PKCS#1</li>
* </ul>
*
* @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},支持包括:
*
* <ul>
* <li>Q值</li>
* <li>X.509</li>
* <li>PKCS#1</li>
* </ul>
*
* @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);
}
} }

View File

@@ -256,8 +256,8 @@ public class KeyUtil {
* 采用PKCS#8规范此规范定义了私钥信息语法和加密私钥语法<br> * 采用PKCS#8规范此规范定义了私钥信息语法和加密私钥语法<br>
* 算法见https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#KeyFactory * 算法见https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#KeyFactory
* *
* @param algorithm 算法 * @param algorithm 算法如RSA、EC、SM2等
* @param key 密钥,必须为DER编码存储 * @param key 密钥,PKCS#8格式
* @return 私钥 {@link PrivateKey} * @return 私钥 {@link PrivateKey}
*/ */
public static PrivateKey generatePrivateKey(String algorithm, byte[] key) { public static PrivateKey generatePrivateKey(String algorithm, byte[] key) {
@@ -271,7 +271,7 @@ public class KeyUtil {
* 生成私钥,仅用于非对称加密<br> * 生成私钥,仅用于非对称加密<br>
* 算法见https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#KeyFactory * 算法见https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#KeyFactory
* *
* @param algorithm 算法 * @param algorithm 算法如RSA、EC、SM2等
* @param keySpec {@link KeySpec} * @param keySpec {@link KeySpec}
* @return 私钥 {@link PrivateKey} * @return 私钥 {@link PrivateKey}
* @since 3.1.1 * @since 3.1.1

View File

@@ -3,7 +3,6 @@ package cn.hutool.crypto;
import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil; 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.PemObject;
import org.bouncycastle.util.io.pem.PemObjectGenerator; import org.bouncycastle.util.io.pem.PemObjectGenerator;
import org.bouncycastle.util.io.pem.PemReader; 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流 * @param keyStream 私钥pem流
* @return {@link PrivateKey} * @return {@link PrivateKey}
*/ */
public static PrivateKey readSm2PemPrivateKey(InputStream keyStream) { public static PrivateKey readSm2PemPrivateKey(InputStream keyStream) {
final ECPrivateKey ecPrivateKey = ECPrivateKey.getInstance(readPem(keyStream)); try{
return ECKeyUtil.toSm2PrivateKey(ecPrivateKey); return KeyUtil.generatePrivateKey("sm2", ECKeyUtil.createOpenSSHPrivateKeySpec(readPem(keyStream)));
} finally {
IoUtil.close(keyStream);
}
} }
/** /**

View File

@@ -14,6 +14,8 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.gm.GMNamedCurves; import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.crypto.digests.SM3Digest; import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.params.ECDomainParameters; 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.crypto.signers.StandardDSAEncoding;
import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Hex; import org.bouncycastle.util.encoders.Hex;
@@ -22,11 +24,20 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.PrivateKey;
import java.security.PublicKey;
/** /**
* SM国密算法工具类<br> * SM国密算法工具类<br>
* 此工具类依赖org.bouncycastle:bcprov-jdk15to18 * 此工具类依赖org.bouncycastle:bcprov-jdk15to18
* *
* <p>封装包括:</p>
* <ul>
* <li>SM2 椭圆曲线非对称加密和签名</li>
* <li>SM3 杂凑算法</li>
* <li>SM4 对称加密</li>
* </ul>
*
* @author looly * @author looly
* @since 4.3.2 * @since 4.3.2
*/ */
@@ -74,14 +85,42 @@ public class SmUtil {
* 私钥和公钥同时为空时生成一对新的私钥和公钥<br> * 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 * 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
* *
* @param privateKey 私钥 * @param privateKey 私钥必须使用PKCS#8规范
* @param publicKey 公钥 * @param publicKey 公钥必须使用X509规范
* @return {@link SM2} * @return {@link SM2}
*/ */
public static SM2 sm2(byte[] privateKey, byte[] publicKey) { public static SM2 sm2(byte[] privateKey, byte[] publicKey) {
return new SM2(privateKey, publicKey); return new SM2(privateKey, publicKey);
} }
/**
* 创建SM2算法对象<br>
* 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
*
* @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算法对象<br>
* 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
*
* @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加密<br> * SM3加密<br>
* 例:<br> * 例:<br>
@@ -192,8 +231,7 @@ public class SmUtil {
} }
/** /**
* BC的SM3withSM2签名得到的结果的rs是asn1格式的这个方法转化成直接拼接r||s<br> * BC的SM3withSM2签名得到的结果的rs是asn1格式的这个方法转化成直接拼接r||s
* 来自https://blog.csdn.net/pridas/article/details/86118774
* *
* @param rsDer rs in asn1 format * @param rsDer rs in asn1 format
* @return sign result in plain byte array * @return sign result in plain byte array
@@ -214,8 +252,7 @@ public class SmUtil {
} }
/** /**
* BC的SM3withSM2验签需要的rs是asn1格式的这个方法将直接拼接r||s的字节数组转化成asn1格式<br> * BC的SM3withSM2验签需要的rs是asn1格式的这个方法将直接拼接r||s的字节数组转化成asn1格式
* 来自https://blog.csdn.net/pridas/article/details/86118774
* *
* @param sign in plain byte array * @param sign in plain byte array
* @return rs result in asn1 format * @return rs result in asn1 format

View File

@@ -4,7 +4,7 @@ import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.HexUtil; import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.BCUtil; import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.CryptoException; import cn.hutool.crypto.CryptoException;
import cn.hutool.crypto.KeyUtil; import cn.hutool.crypto.ECKeyUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.Digest;
@@ -74,13 +74,13 @@ public class SM2 extends AbstractAsymmetricCrypto<SM2> {
* 私钥和公钥同时为空时生成一对新的私钥和公钥<br> * 私钥和公钥同时为空时生成一对新的私钥和公钥<br>
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 * 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密
* *
* @param privateKey 私钥,必须使用PKCS#8规范 * @param privateKey 私钥,可以使用PKCS#8、D值或PKCS#1规范
* @param publicKey 公钥,必须使用X509规范 * @param publicKey 公钥,可以使用X509、Q值或PKCS#1规范
*/ */
public SM2(byte[] privateKey, byte[] publicKey) { public SM2(byte[] privateKey, byte[] publicKey) {
this(// this(
KeyUtil.generatePrivateKey(ALGORITHM_SM2, privateKey), // ECKeyUtil.decodePrivateKeyParams(privateKey),
KeyUtil.generatePublicKey(ALGORITHM_SM2, publicKey)// ECKeyUtil.decodePublicKeyParams(publicKey)
); );
} }

View File

@@ -1,7 +1,7 @@
package cn.hutool.crypto.digest; package cn.hutool.crypto.digest;
/** /**
* SM3算法 * SM3杂凑算法
* *
* @author looly * @author looly
* @since 4.6.8 * @since 4.6.8

View File

@@ -1,11 +1,14 @@
package cn.hutool.crypto.test; package cn.hutool.crypto.test;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.PemUtil; import cn.hutool.crypto.PemUtil;
import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA; import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.asymmetric.SM2; import cn.hutool.crypto.asymmetric.SM2;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@@ -58,4 +61,20 @@ public class PemUtilTest {
// 64位签名 // 64位签名
Assert.assertEquals(64, sign.length); 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);
}
} }

View File

@@ -12,7 +12,7 @@ import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2; import cn.hutool.crypto.asymmetric.SM2;
import org.bouncycastle.crypto.engines.SM2Engine; import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters; 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.Assert;
import org.junit.Test; import org.junit.Test;
@@ -136,7 +136,7 @@ public class SM2Test {
//签名值 //签名值
String signHex = "2881346e038d2ed706ccdd025f2b1dafa7377d5cf090134b98756fafe084dddbcdba0ab00b5348ed48025195af3f1dda29e819bb66aa9d4d088050ff148482a1"; String signHex = "2881346e038d2ed706ccdd025f2b1dafa7377d5cf090134b98756fafe084dddbcdba0ab00b5348ed48025195af3f1dda29e819bb66aa9d4d088050ff148482a1";
final SM2 sm2 = new SM2(null, ECKeyUtil.toSm2PublicParams(publicKeyHex)); final SM2 sm2 = new SM2(null, publicKeyHex);
sm2.usePlainEncoding(); sm2.usePlainEncoding();
boolean verify = sm2.verify(dataBytes, HexUtil.decodeHex(signHex)); boolean verify = sm2.verify(dataBytes, HexUtil.decodeHex(signHex));
@@ -251,10 +251,7 @@ public class SM2Test {
String data = "123456"; String data = "123456";
final ECPublicKeyParameters ecPublicKeyParameters = ECKeyUtil.toSm2PublicParams(q); final SM2 sm2 = new SM2(d, q);
final ECPrivateKeyParameters ecPrivateKeyParameters = ECKeyUtil.toSm2PrivateParams(d);
final SM2 sm2 = new SM2(ecPrivateKeyParameters, ecPublicKeyParameters);
sm2.setMode(SM2Engine.Mode.C1C2C3); sm2.setMode(SM2Engine.Mode.C1C2C3);
final String encryptHex = sm2.encryptHex(data, KeyType.PublicKey); final String encryptHex = sm2.encryptHex(data, KeyType.PublicKey);
final String decryptStr = sm2.decryptStr(encryptHex, KeyType.PrivateKey); final String decryptStr = sm2.decryptStr(encryptHex, KeyType.PrivateKey);
@@ -277,8 +274,41 @@ public class SM2Test {
} }
@Test @Test
public void test(){ public void getPublicKeyByPrivateKeyTest(){
String priKey = "MHcCAQEEIE29XqAFV/rkJbnJzCoQRJLTeAHG2TR0h9ZCWag0+ZMEoAoGCCqBHM9VAYItoUQDQgAESkOzNigIsH5ehFvr9yQNQ66genyOrm+Q4umCA4aWXPeRzmcTAWSlTineiReTFN2lqor2xaulT8u3a4w3AM/F6A=="; // issue#I38SDPopenSSL生成的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=="; 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));
} }
} }