mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add ECKeyUtil
This commit is contained in:
parent
ac5728d410
commit
58b1cae320
@ -10,6 +10,7 @@
|
||||
* 【setting】 Setting增加store无参方法(issue#1072@Github)
|
||||
* 【setting】 StatementUtil增加null缓存(pr#1076@Github)
|
||||
* 【core 】 扩充Console功能,支持可变参数(issue#1077@Github)
|
||||
* 【crypto 】 增加ECKeyUtil(issue#I1UOF5@Gitee)
|
||||
|
||||
### Bug修复
|
||||
* 【core 】 修复Dict.of错误(issue#I1UUO5@Gitee)
|
||||
|
@ -172,7 +172,7 @@ public class BCUtil {
|
||||
* @return ECPrivateKeyParameters
|
||||
*/
|
||||
public static ECPrivateKeyParameters toParams(String dHex, ECDomainParameters domainParameters) {
|
||||
return toParams(new BigInteger(dHex, 16), domainParameters);
|
||||
return ECKeyUtil.toPrivateParams(dHex, domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -193,7 +193,7 @@ public class BCUtil {
|
||||
* @return ECPrivateKeyParameters
|
||||
*/
|
||||
public static ECPrivateKeyParameters toParams(byte[] d, ECDomainParameters domainParameters) {
|
||||
return toParams(new BigInteger(d), domainParameters);
|
||||
return ECKeyUtil.toPrivateParams(d, domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -214,10 +214,7 @@ public class BCUtil {
|
||||
* @return ECPrivateKeyParameters
|
||||
*/
|
||||
public static ECPrivateKeyParameters toParams(BigInteger d, ECDomainParameters domainParameters) {
|
||||
if(null == d){
|
||||
return null;
|
||||
}
|
||||
return new ECPrivateKeyParameters(d, domainParameters);
|
||||
return ECKeyUtil.toPrivateParams(d, domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -229,10 +226,7 @@ public class BCUtil {
|
||||
* @return ECPublicKeyParameters
|
||||
*/
|
||||
public static ECPublicKeyParameters toParams(BigInteger x, BigInteger y, ECDomainParameters domainParameters) {
|
||||
if(null == x || null == y){
|
||||
return null;
|
||||
}
|
||||
return toParams(x.toByteArray(), y.toByteArray(), domainParameters);
|
||||
return ECKeyUtil.toPublicParams(x, y, domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -278,13 +272,7 @@ public class BCUtil {
|
||||
* @return ECPublicKeyParameters
|
||||
*/
|
||||
public static ECPublicKeyParameters toParams(byte[] xBytes, byte[] yBytes, ECDomainParameters domainParameters) {
|
||||
if(null == xBytes || null == yBytes){
|
||||
return null;
|
||||
}
|
||||
final ECCurve curve = domainParameters.getCurve();
|
||||
final int curveLength = getCurveLength(curve);
|
||||
final byte[] encodedPubKey = encodePoint(xBytes, yBytes, curveLength);
|
||||
return new ECPublicKeyParameters(curve.decodePoint(encodedPubKey), domainParameters);
|
||||
return ECKeyUtil.toPublicParams(xBytes, yBytes, domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -294,14 +282,7 @@ public class BCUtil {
|
||||
* @return {@link ECPublicKeyParameters}或null
|
||||
*/
|
||||
public static ECPublicKeyParameters toParams(PublicKey publicKey) {
|
||||
if (null == publicKey) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return (ECPublicKeyParameters) ECUtil.generatePublicKeyParameter(publicKey);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
return ECKeyUtil.toPublicParams(publicKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -311,14 +292,7 @@ public class BCUtil {
|
||||
* @return {@link ECPrivateKeyParameters}或null
|
||||
*/
|
||||
public static ECPrivateKeyParameters toParams(PrivateKey privateKey) {
|
||||
if (null == privateKey) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return (ECPrivateKeyParameters) ECUtil.generatePrivateKeyParameter(privateKey);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
return ECKeyUtil.toPrivateParams(privateKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -344,58 +318,4 @@ public class BCUtil {
|
||||
public static PublicKey readPemPublicKey(InputStream pemStream) {
|
||||
return PemUtil.readPemPublicKey(pemStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将X,Y曲线点编码为bytes
|
||||
*
|
||||
* @param xBytes X坐标bytes
|
||||
* @param yBytes Y坐标bytes
|
||||
* @param curveLength 曲线编码后的长度
|
||||
* @return 编码bytes
|
||||
*/
|
||||
private static byte[] encodePoint(byte[] xBytes, byte[] yBytes, int curveLength) {
|
||||
xBytes = fixLength(curveLength, xBytes);
|
||||
yBytes = fixLength(curveLength, yBytes);
|
||||
final byte[] encodedPubKey = new byte[1 + xBytes.length + yBytes.length];
|
||||
|
||||
// 压缩类型:无压缩
|
||||
encodedPubKey[0] = 0x04;
|
||||
System.arraycopy(xBytes, 0, encodedPubKey, 1, xBytes.length);
|
||||
System.arraycopy(yBytes, 0, encodedPubKey, 1 + xBytes.length, yBytes.length);
|
||||
|
||||
return encodedPubKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Curve长度
|
||||
*
|
||||
* @param curve {@link ECCurve}
|
||||
* @return Curve长度
|
||||
*/
|
||||
private static int getCurveLength(ECCurve curve) {
|
||||
return (curve.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;
|
||||
}
|
||||
}
|
||||
|
244
hutool-crypto/src/main/java/cn/hutool/crypto/ECKeyUtil.java
Normal file
244
hutool-crypto/src/main/java/cn/hutool/crypto/ECKeyUtil.java
Normal file
@ -0,0 +1,244 @@
|
||||
package cn.hutool.crypto;
|
||||
|
||||
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.math.ec.ECCurve;
|
||||
import org.bouncycastle.util.BigIntegers;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
/**
|
||||
* EC密钥参数相关工具类封装
|
||||
*
|
||||
* @author looly
|
||||
* @since 5.4.3
|
||||
*/
|
||||
public class ECKeyUtil {
|
||||
|
||||
//--------------------------------------------------------------------------- Public Key
|
||||
/**
|
||||
* 转换为 ECPublicKeyParameters
|
||||
*
|
||||
* @param q 公钥Q值
|
||||
* @return ECPublicKeyParameters
|
||||
*/
|
||||
public static ECPublicKeyParameters toSm2PublicParams(byte[] q) {
|
||||
return toPublicParams(q, SmUtil.SM2_DOMAIN_PARAMS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为 ECPublicKeyParameters
|
||||
*
|
||||
* @param q 公钥Q值
|
||||
* @return ECPublicKeyParameters
|
||||
*/
|
||||
public static ECPublicKeyParameters toSm2PublicParams(String q) {
|
||||
return toPublicParams(q, SmUtil.SM2_DOMAIN_PARAMS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为SM2的ECPublicKeyParameters
|
||||
*
|
||||
* @param x 公钥X
|
||||
* @param y 公钥Y
|
||||
* @return ECPublicKeyParameters
|
||||
*/
|
||||
public static ECPublicKeyParameters toSm2PublicParams(String x, String y) {
|
||||
return toPublicParams(x, y, SmUtil.SM2_DOMAIN_PARAMS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为SM2的ECPublicKeyParameters
|
||||
*
|
||||
* @param xBytes 公钥X
|
||||
* @param yBytes 公钥Y
|
||||
* @return ECPublicKeyParameters
|
||||
*/
|
||||
public static ECPublicKeyParameters toSm2PublicParams(byte[] xBytes, byte[] yBytes) {
|
||||
return toPublicParams(xBytes, yBytes, SmUtil.SM2_DOMAIN_PARAMS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为ECPublicKeyParameters
|
||||
*
|
||||
* @param x 公钥X
|
||||
* @param y 公钥Y
|
||||
* @param domainParameters ECDomainParameters
|
||||
* @return ECPublicKeyParameters
|
||||
*/
|
||||
public static ECPublicKeyParameters toPublicParams(String x, String y, ECDomainParameters domainParameters) {
|
||||
return toPublicParams(SecureUtil.decode(x), SecureUtil.decode(y), domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为ECPublicKeyParameters
|
||||
*
|
||||
* @param xBytes 公钥X
|
||||
* @param yBytes 公钥Y
|
||||
* @param domainParameters ECDomainParameters曲线参数
|
||||
* @return ECPublicKeyParameters
|
||||
*/
|
||||
public static ECPublicKeyParameters toPublicParams(byte[] xBytes, byte[] yBytes, ECDomainParameters domainParameters) {
|
||||
return toPublicParams(BigIntegers.fromUnsignedByteArray(xBytes), BigIntegers.fromUnsignedByteArray(yBytes), domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为ECPublicKeyParameters
|
||||
*
|
||||
* @param x 公钥X
|
||||
* @param y 公钥Y
|
||||
* @param domainParameters ECDomainParameters
|
||||
* @return ECPublicKeyParameters
|
||||
*/
|
||||
public static ECPublicKeyParameters toPublicParams(BigInteger x, BigInteger y, ECDomainParameters domainParameters) {
|
||||
if (null == x || null == y) {
|
||||
return null;
|
||||
}
|
||||
final ECCurve curve = domainParameters.getCurve();
|
||||
return toPublicParams(curve.createPoint(x, y), domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为ECPublicKeyParameters
|
||||
*
|
||||
* @param pointEncoded 被编码的曲线坐标点
|
||||
* @param domainParameters ECDomainParameters
|
||||
* @return ECPublicKeyParameters
|
||||
* @since 5.4.3
|
||||
*/
|
||||
public static ECPublicKeyParameters toPublicParams(String pointEncoded, ECDomainParameters domainParameters) {
|
||||
final ECCurve curve = domainParameters.getCurve();
|
||||
return toPublicParams(curve.decodePoint(SecureUtil.decode(pointEncoded)), domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为ECPublicKeyParameters
|
||||
*
|
||||
* @param pointEncoded 被编码的曲线坐标点
|
||||
* @param domainParameters ECDomainParameters
|
||||
* @return ECPublicKeyParameters
|
||||
* @since 5.4.3
|
||||
*/
|
||||
public static ECPublicKeyParameters toPublicParams(byte[] pointEncoded, ECDomainParameters domainParameters) {
|
||||
final ECCurve curve = domainParameters.getCurve();
|
||||
return toPublicParams(curve.decodePoint(pointEncoded), domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为ECPublicKeyParameters
|
||||
*
|
||||
* @param point 曲线坐标点
|
||||
* @param domainParameters ECDomainParameters
|
||||
* @return ECPublicKeyParameters
|
||||
* @since 5.4.3
|
||||
*/
|
||||
public static ECPublicKeyParameters toPublicParams(org.bouncycastle.math.ec.ECPoint point, ECDomainParameters domainParameters) {
|
||||
return new ECPublicKeyParameters(point, domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 公钥转换为 {@link ECPublicKeyParameters}
|
||||
*
|
||||
* @param publicKey 公钥,传入null返回null
|
||||
* @return {@link ECPublicKeyParameters}或null
|
||||
*/
|
||||
public static ECPublicKeyParameters toPublicParams(PublicKey publicKey) {
|
||||
if (null == publicKey) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return (ECPublicKeyParameters) ECUtil.generatePublicKeyParameter(publicKey);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------- Private Key
|
||||
/**
|
||||
* 转换为 ECPrivateKeyParameters
|
||||
*
|
||||
* @param d 私钥d值16进制字符串
|
||||
* @return ECPrivateKeyParameters
|
||||
*/
|
||||
public static ECPrivateKeyParameters toSm2PrivateParams(String d) {
|
||||
return toPrivateParams(d, SmUtil.SM2_DOMAIN_PARAMS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为 ECPrivateKeyParameters
|
||||
*
|
||||
* @param d 私钥d值
|
||||
* @return ECPrivateKeyParameters
|
||||
*/
|
||||
public static ECPrivateKeyParameters toSm2PrivateParams(byte[] d) {
|
||||
return toPrivateParams(d, SmUtil.SM2_DOMAIN_PARAMS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为 ECPrivateKeyParameters
|
||||
*
|
||||
* @param d 私钥d值
|
||||
* @return ECPrivateKeyParameters
|
||||
*/
|
||||
public static ECPrivateKeyParameters toSm2PrivateParams(BigInteger d) {
|
||||
return toPrivateParams(d, SmUtil.SM2_DOMAIN_PARAMS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为 ECPrivateKeyParameters
|
||||
*
|
||||
* @param d 私钥d值16进制字符串
|
||||
* @param domainParameters ECDomainParameters
|
||||
* @return ECPrivateKeyParameters
|
||||
*/
|
||||
public static ECPrivateKeyParameters toPrivateParams(String d, ECDomainParameters domainParameters) {
|
||||
return toPrivateParams(BigIntegers.fromUnsignedByteArray(SecureUtil.decode(d)), domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为 ECPrivateKeyParameters
|
||||
*
|
||||
* @param d 私钥d值
|
||||
* @param domainParameters ECDomainParameters
|
||||
* @return ECPrivateKeyParameters
|
||||
*/
|
||||
public static ECPrivateKeyParameters toPrivateParams(byte[] d, ECDomainParameters domainParameters) {
|
||||
return toPrivateParams(BigIntegers.fromUnsignedByteArray(d), domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为 ECPrivateKeyParameters
|
||||
*
|
||||
* @param d 私钥d值
|
||||
* @param domainParameters ECDomainParameters
|
||||
* @return ECPrivateKeyParameters
|
||||
*/
|
||||
public static ECPrivateKeyParameters toPrivateParams(BigInteger d, ECDomainParameters domainParameters) {
|
||||
if (null == d) {
|
||||
return null;
|
||||
}
|
||||
return new ECPrivateKeyParameters(d, domainParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* 私钥转换为 {@link ECPrivateKeyParameters}
|
||||
*
|
||||
* @param privateKey 私钥,传入null返回null
|
||||
* @return {@link ECPrivateKeyParameters}或null
|
||||
*/
|
||||
public static ECPrivateKeyParameters toPrivateParams(PrivateKey privateKey) {
|
||||
if (null == privateKey) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return (ECPrivateKeyParameters) ECUtil.generatePrivateKeyParameter(privateKey);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new CryptoException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,12 +4,15 @@ import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.ECKeyUtil;
|
||||
import cn.hutool.crypto.KeyUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.SmUtil;
|
||||
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.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -205,4 +208,21 @@ public class SM2Test {
|
||||
String sign = "DCA0E80A7F46C93714B51C3EFC55A922BCEF7ECF0FE9E62B53BA6A7438B543A76C145A452CA9036F3CB70D7E6C67D4D9D7FE114E5367A2F6F5A4D39F2B10F3D6";
|
||||
Assert.assertTrue(sm2.verifyHex(data, sign));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sm2PlainWithPointTest2() {
|
||||
String d = "4BD9A450D7E68A5D7E08EB7A0BFA468FD3EB32B71126246E66249A73A9E4D44A";
|
||||
String q = "04970AB36C3B870FBC04041087DB1BC36FB4C6E125B5EA406DB0EC3E2F80F0A55D8AFF28357A0BB215ADC2928BE76F1AFF869BF4C0A3852A78F3B827812C650AD3";
|
||||
|
||||
String data = "123456";
|
||||
|
||||
final ECPublicKeyParameters ecPublicKeyParameters = ECKeyUtil.toSm2PublicParams(q);
|
||||
final ECPrivateKeyParameters ecPrivateKeyParameters = ECKeyUtil.toSm2PrivateParams(d);
|
||||
|
||||
final SM2 sm2 = new SM2(ecPrivateKeyParameters, ecPublicKeyParameters);
|
||||
final String encryptHex = sm2.encryptHex(data, KeyType.PublicKey);
|
||||
final String decryptStr = sm2.decryptStr(encryptHex, KeyType.PrivateKey);
|
||||
|
||||
Assert.assertEquals(data, decryptStr);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user