add method

This commit is contained in:
Looly
2021-02-25 23:53:51 +08:00
parent 8c0ad9c69c
commit 4c772ead35
5 changed files with 54 additions and 11 deletions

View File

@@ -12,6 +12,7 @@
* 【crypto 】 Sm2增加getD和getQ方法issue#I37Z4C@Gitee
* 【cache 】 AbstractCache增加keySet方法issue#I37Z4C@Gitee
* 【core 】 NumberWordFormatter增加formatSimple方法pr#1436@Github
* 【crypto 】 增加读取openSSL生成的sm2私钥
### Bug修复
* 【json 】 JSONUtil.isJson方法改变trim策略解决特殊空白符导致判断失败问题

View File

@@ -1,5 +1,11 @@
package cn.hutool.crypto;
import cn.hutool.core.io.IORuntimeException;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.sec.ECPrivateKey;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
@@ -8,6 +14,7 @@ import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.util.BigIntegers;
import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.Key;
@@ -262,4 +269,19 @@ public class ECKeyUtil {
throw new CryptoException(e);
}
}
/**
* 将SM2算法的{@link ECPrivateKey} 转换为 {@link PrivateKey}
* @param privateKey {@link ECPrivateKey}
* @return {@link 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);
return KeyUtil.generatePrivateKey("SM2", info.getEncoded(ASN1Encoding.DER));
} catch (IOException e) {
throw new IORuntimeException(e);
}
}
}

View File

@@ -3,6 +3,7 @@ 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;
@@ -159,4 +160,15 @@ public class PemUtil {
IoUtil.close(writer);
}
}
/**
* 读取OpenSSL生成的ANS1格式的Pem私钥文件
*
* @param keyStream 私钥pem流
* @return {@link PrivateKey}
*/
public static PrivateKey readSm2PemPrivateKey(InputStream keyStream){
final ECPrivateKey ecPrivateKey = ECPrivateKey.getInstance(readPem(keyStream));
return ECKeyUtil.toSm2PrivateKey(ecPrivateKey);
}
}

View File

@@ -10,6 +10,7 @@ import cn.hutool.crypto.digest.mac.BCHMacEngine;
import cn.hutool.crypto.digest.mac.MacEngine;
import cn.hutool.crypto.symmetric.SM4;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.params.ECDomainParameters;
@@ -31,6 +32,7 @@ import java.math.BigInteger;
*/
public class SmUtil {
private final static int RS_LEN = 32;
/**
* SM2默认曲线
*/
@@ -38,13 +40,11 @@ public class SmUtil {
/**
* SM2推荐曲线参数来自https://github.com/ZZMarquis/gmhelper
*/
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));
}
public static final ECDomainParameters SM2_DOMAIN_PARAMS = BCUtil.toDomainParams(GMNamedCurves.getByName(SM2_CURVE_NAME));
/**
* SM2国密算法公钥参数的Oid标识
*/
public static final ASN1ObjectIdentifier ID_SM2_PUBLIC_KEY_PARAM = new ASN1ObjectIdentifier("1.2.156.10197.1.301");
/**
* 创建SM2算法对象<br>

View File

@@ -4,10 +4,11 @@ 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 cn.hutool.crypto.asymmetric.SM2;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.PublicKey;
@@ -45,9 +46,16 @@ public class PemUtilTest {
}
@Test
@Ignore
public void readECPrivateKeyTest() {
PrivateKey privateKey = PemUtil.readPemPrivateKey(ResourceUtil.getStream("test_ec_private_key.pem"));
Assert.assertNotNull(privateKey);
PrivateKey privateKey = PemUtil.readSm2PemPrivateKey(ResourceUtil.getStream("test_ec_private_key.pem"));
SM2 sm2 = new SM2(privateKey, null);
sm2.usePlainEncoding();
//需要签名的明文,得到明文对应的字节数组
byte[] dataBytes = "我是一段测试aaaa".getBytes(StandardCharsets.UTF_8);
byte[] sign = sm2.sign(dataBytes, null);
// 64位签名
Assert.assertEquals(64, sign.length);
}
}