mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-24 18:04:54 +08:00
fix sm2
This commit is contained in:
parent
82f982f809
commit
8fba51f62b
@ -1,5 +1,6 @@
|
||||
package cn.hutool.crypto;
|
||||
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||
import org.bouncycastle.crypto.params.ECKeyParameters;
|
||||
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
||||
@ -14,7 +15,7 @@ import org.bouncycastle.jce.spec.ECNamedCurveSpec;
|
||||
import org.bouncycastle.jce.spec.ECParameterSpec;
|
||||
import org.bouncycastle.math.ec.ECCurve;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PrivateKey;
|
||||
@ -31,6 +32,18 @@ import java.security.spec.EllipticCurve;
|
||||
* @since 4.5.0
|
||||
*/
|
||||
public class BCUtil {
|
||||
|
||||
/**
|
||||
* 只获取私钥里的d,32字节
|
||||
*
|
||||
* @param privateKey {@link PublicKey},必须为org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey
|
||||
* @return 压缩得到的X
|
||||
* @since 5.1.6
|
||||
*/
|
||||
public static byte[] encodeECPrivateKey(PrivateKey privateKey) {
|
||||
return ((BCECPrivateKey) privateKey).getD().toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码压缩EC公钥(基于BouncyCastle)<br>
|
||||
* 见:https://www.cnblogs.com/xinzhao/p/8963724.html
|
||||
@ -95,7 +108,7 @@ public class BCUtil {
|
||||
*/
|
||||
public static ECKeyParameters toParams(ECKey ecKey) {
|
||||
final ECParameterSpec parameterSpec = ecKey.getParameters();
|
||||
final ECDomainParameters ecDomainParameters = buildECDomainParameters(parameterSpec);
|
||||
final ECDomainParameters ecDomainParameters = toDomainParameters(parameterSpec);
|
||||
|
||||
if (ecKey instanceof BCECPrivateKey) {
|
||||
return new ECPrivateKeyParameters(((BCECPrivateKey) ecKey).getD(), ecDomainParameters);
|
||||
@ -113,11 +126,124 @@ public class BCUtil {
|
||||
* @return ECDomainParameters
|
||||
* @since 5.1.6
|
||||
*/
|
||||
public static ECDomainParameters buildECDomainParameters(ECParameterSpec parameterSpec) {
|
||||
public static ECDomainParameters toDomainParameters(ECParameterSpec parameterSpec) {
|
||||
return new ECDomainParameters(
|
||||
parameterSpec.getCurve(),
|
||||
parameterSpec.getG(),
|
||||
parameterSpec.getN(),
|
||||
parameterSpec.getH());
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为 ECPrivateKeyParameters
|
||||
*
|
||||
* @param dHex 私钥d值16进制字符串
|
||||
* @param domainParameters ECDomainParameters
|
||||
* @return ECPrivateKeyParameters
|
||||
*/
|
||||
public static ECPrivateKeyParameters toParams(String dHex, ECDomainParameters domainParameters) {
|
||||
return new ECPrivateKeyParameters(new BigInteger(dHex, 16), domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为 ECPrivateKeyParameters
|
||||
*
|
||||
* @param d 私钥d值
|
||||
* @param domainParameters ECDomainParameters
|
||||
* @return ECPrivateKeyParameters
|
||||
*/
|
||||
public static ECPrivateKeyParameters toParams(BigInteger d, ECDomainParameters domainParameters) {
|
||||
return new ECPrivateKeyParameters(d, domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为ECPublicKeyParameters
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为ECPublicKeyParameters
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为ECPublicKeyParameters
|
||||
*
|
||||
* @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);
|
||||
return new ECPublicKeyParameters(curve.decodePoint(encodedPubKey), domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Curve长度
|
||||
*
|
||||
* @param ecKey Curve
|
||||
* @return Curve长度
|
||||
*/
|
||||
public static int getCurveLength(ECKeyParameters ecKey) {
|
||||
return getCurveLength(ecKey.getParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Curve长度
|
||||
*
|
||||
* @param domainParams ECDomainParameters
|
||||
* @return Curve长度
|
||||
*/
|
||||
public static int getCurveLength(ECDomainParameters domainParams) {
|
||||
return (domainParams.getCurve().getFieldSize() + 7) / 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修正长度
|
||||
*
|
||||
* @param curveLength 修正后的长度
|
||||
* @param src bytes
|
||||
* @return 修正后的bytes
|
||||
*/
|
||||
private static byte[] fixLength(int curveLength, byte[] src) {
|
||||
if (src.length == curveLength) {
|
||||
return src;
|
||||
}
|
||||
|
||||
byte[] result = new byte[curveLength];
|
||||
if (src.length > curveLength) {
|
||||
// 裁剪末尾的指定长度
|
||||
System.arraycopy(src, src.length - result.length, result, 0, result.length);
|
||||
} else {
|
||||
// 放置于末尾
|
||||
System.arraycopy(src, 0, result, result.length - src.length, src.length);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
/**
|
||||
* PEM(Privacy Enhanced Mail)格式相关工具类。
|
||||
* PEM(Privacy Enhanced Mail)格式相关工具类。(基于Bouncy Castle)
|
||||
*
|
||||
* <p>
|
||||
* PEM一般为文本格式,以 -----BEGIN... 开头,以 -----END... 结尾,中间的内容是 BASE64 编码。
|
||||
|
@ -15,6 +15,8 @@ import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
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;
|
||||
|
||||
@ -32,6 +34,18 @@ import java.math.BigInteger;
|
||||
*/
|
||||
public class SmUtil {
|
||||
|
||||
/*
|
||||
* 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());
|
||||
|
||||
private final static int RS_LEN = 32;
|
||||
|
||||
/**
|
||||
|
@ -35,8 +35,8 @@ public class SM2 extends AbstractAsymmetricCrypto<SM2> {
|
||||
protected SM2Signer signer;
|
||||
|
||||
private SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2;
|
||||
private ECPublicKeyParameters publicKeyParams;
|
||||
private ECPrivateKeyParameters privateKeyParams;
|
||||
private ECPublicKeyParameters publicKeyParams;
|
||||
|
||||
// ------------------------------------------------------------------ Constructor start
|
||||
|
||||
@ -85,6 +85,7 @@ public class SM2 extends AbstractAsymmetricCrypto<SM2> {
|
||||
public SM2(PrivateKey privateKey, PublicKey publicKey) {
|
||||
super(ALGORITHM_SM2, privateKey, publicKey);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ Constructor end
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,28 @@
|
||||
package cn.hutool.crypto.test;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.crypto.BCUtil;
|
||||
import cn.hutool.crypto.SmUtil;
|
||||
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.junit.Test;
|
||||
|
||||
public class BCUtilTest {
|
||||
|
||||
@Test
|
||||
public void createECPublicKeyParametersTest() {
|
||||
String x = "706AD9DAA3E5CEAC3DA59F583429E8043BAFC576BE10092C4EA4D8E19846CA62";
|
||||
String y = "F7E938B02EED7280277493B8556E5B01CB436E018A562DFDC53342BF41FDF728";
|
||||
|
||||
final ECPublicKeyParameters keyParameters = BCUtil.toParams(x, y, SmUtil.CURVE, SmUtil.DOMAIN_PARAMS);
|
||||
Assert.notNull(keyParameters);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createECPrivateKeyParametersTest() {
|
||||
String privateKeyHex = "5F6CA5BB044C40ED2355F0372BF72A5B3AE6943712F9FDB7C1FFBAECC06F3829";
|
||||
|
||||
final ECPrivateKeyParameters keyParameters = BCUtil.toParams(privateKeyHex, SmUtil.DOMAIN_PARAMS);
|
||||
Assert.notNull(keyParameters);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user