mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
fix sm2
This commit is contained in:
parent
82f982f809
commit
8fba51f62b
@ -1,5 +1,6 @@
|
|||||||
package cn.hutool.crypto;
|
package cn.hutool.crypto;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.HexUtil;
|
||||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||||
import org.bouncycastle.crypto.params.ECKeyParameters;
|
import org.bouncycastle.crypto.params.ECKeyParameters;
|
||||||
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
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.jce.spec.ECParameterSpec;
|
||||||
import org.bouncycastle.math.ec.ECCurve;
|
import org.bouncycastle.math.ec.ECCurve;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.math.BigInteger;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.KeyFactory;
|
import java.security.KeyFactory;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
@ -31,6 +32,18 @@ import java.security.spec.EllipticCurve;
|
|||||||
* @since 4.5.0
|
* @since 4.5.0
|
||||||
*/
|
*/
|
||||||
public class BCUtil {
|
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>
|
* 编码压缩EC公钥(基于BouncyCastle)<br>
|
||||||
* 见:https://www.cnblogs.com/xinzhao/p/8963724.html
|
* 见:https://www.cnblogs.com/xinzhao/p/8963724.html
|
||||||
@ -95,7 +108,7 @@ public class BCUtil {
|
|||||||
*/
|
*/
|
||||||
public static ECKeyParameters toParams(ECKey ecKey) {
|
public static ECKeyParameters toParams(ECKey ecKey) {
|
||||||
final ECParameterSpec parameterSpec = ecKey.getParameters();
|
final ECParameterSpec parameterSpec = ecKey.getParameters();
|
||||||
final ECDomainParameters ecDomainParameters = buildECDomainParameters(parameterSpec);
|
final ECDomainParameters ecDomainParameters = toDomainParameters(parameterSpec);
|
||||||
|
|
||||||
if (ecKey instanceof BCECPrivateKey) {
|
if (ecKey instanceof BCECPrivateKey) {
|
||||||
return new ECPrivateKeyParameters(((BCECPrivateKey) ecKey).getD(), ecDomainParameters);
|
return new ECPrivateKeyParameters(((BCECPrivateKey) ecKey).getD(), ecDomainParameters);
|
||||||
@ -113,11 +126,124 @@ public class BCUtil {
|
|||||||
* @return ECDomainParameters
|
* @return ECDomainParameters
|
||||||
* @since 5.1.6
|
* @since 5.1.6
|
||||||
*/
|
*/
|
||||||
public static ECDomainParameters buildECDomainParameters(ECParameterSpec parameterSpec) {
|
public static ECDomainParameters toDomainParameters(ECParameterSpec parameterSpec) {
|
||||||
return new ECDomainParameters(
|
return new ECDomainParameters(
|
||||||
parameterSpec.getCurve(),
|
parameterSpec.getCurve(),
|
||||||
parameterSpec.getG(),
|
parameterSpec.getG(),
|
||||||
parameterSpec.getN(),
|
parameterSpec.getN(),
|
||||||
parameterSpec.getH());
|
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;
|
import java.security.PublicKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PEM(Privacy Enhanced Mail)格式相关工具类。
|
* PEM(Privacy Enhanced Mail)格式相关工具类。(基于Bouncy Castle)
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* PEM一般为文本格式,以 -----BEGIN... 开头,以 -----END... 结尾,中间的内容是 BASE64 编码。
|
* PEM一般为文本格式,以 -----BEGIN... 开头,以 -----END... 结尾,中间的内容是 BASE64 编码。
|
||||||
|
@ -15,6 +15,8 @@ import org.bouncycastle.asn1.ASN1Sequence;
|
|||||||
import org.bouncycastle.asn1.DERSequence;
|
import org.bouncycastle.asn1.DERSequence;
|
||||||
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.math.ec.ECPoint;
|
||||||
|
import org.bouncycastle.math.ec.custom.gm.SM2P256V1Curve;
|
||||||
import org.bouncycastle.util.Arrays;
|
import org.bouncycastle.util.Arrays;
|
||||||
import org.bouncycastle.util.encoders.Hex;
|
import org.bouncycastle.util.encoders.Hex;
|
||||||
|
|
||||||
@ -32,6 +34,18 @@ import java.math.BigInteger;
|
|||||||
*/
|
*/
|
||||||
public class SmUtil {
|
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;
|
private final static int RS_LEN = 32;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,8 +35,8 @@ public class SM2 extends AbstractAsymmetricCrypto<SM2> {
|
|||||||
protected SM2Signer signer;
|
protected SM2Signer signer;
|
||||||
|
|
||||||
private SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2;
|
private SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2;
|
||||||
private ECPublicKeyParameters publicKeyParams;
|
|
||||||
private ECPrivateKeyParameters privateKeyParams;
|
private ECPrivateKeyParameters privateKeyParams;
|
||||||
|
private ECPublicKeyParameters publicKeyParams;
|
||||||
|
|
||||||
// ------------------------------------------------------------------ Constructor start
|
// ------------------------------------------------------------------ Constructor start
|
||||||
|
|
||||||
@ -85,6 +85,7 @@ public class SM2 extends AbstractAsymmetricCrypto<SM2> {
|
|||||||
public SM2(PrivateKey privateKey, PublicKey publicKey) {
|
public SM2(PrivateKey privateKey, PublicKey publicKey) {
|
||||||
super(ALGORITHM_SM2, privateKey, publicKey);
|
super(ALGORITHM_SM2, privateKey, publicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------ Constructor end
|
// ------------------------------------------------------------------ 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…
x
Reference in New Issue
Block a user