Skip to content

Instantly share code, notes, and snippets.

@Gsealy
Last active February 8, 2022 07:46
Show Gist options
  • Save Gsealy/778efb420d325582541a1ec67a98b73e to your computer and use it in GitHub Desktop.
Save Gsealy/778efb420d325582541a1ec67a98b73e to your computer and use it in GitHub Desktop.
EC秘钥对工具,计算公钥,压缩公钥,解压缩,转换为ASN.1结构
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
public class CalculatePubKey {
private static final String privKey = "308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104204833b1bae3464a7495896b9a332cdaa31f4b3b072cc79336d6b6270604d2f7aca00a06082a8648ce3d030107a144034200042f2cc7e74cdd56bfb6b30b92ec59eea14011973ebadb31cc04b151f9eb15d5ebc5d28fd940889c3b0eb234c1bd7d5fbf4c6d2f1692cfd41c37a361a19e6f32b9";
private static final String pubKey = "3059301306072a8648ce3d020106082a8648ce3d030107034200042f2cc7e74cdd56bfb6b30b92ec59eea14011973ebadb31cc04b151f9eb15d5ebc5d28fd940889c3b0eb234c1bd7d5fbf4c6d2f1692cfd41c37a361a19e6f32b9";
private static PrivateKey priv;
private static PublicKey pub;
static {
try {
instance();
} catch (Exception e) {
}
}
public static void main(String[] args) throws Exception {
PublicKey pub = getPublicKey(priv);
System.out.println("original ---> " + pubKey);
System.out.println("calculate --> " + Hex.toHexString(pub.getEncoded()));
byte[] hex = encodePoint(pub);
System.out.println("encode -----> " + Hex.toHexString(hex));
PublicKey pubkey = decodePoint(Hex.toHexString(hex), "prime256v1");
System.out.println("decode -----> " + Hex.toHexString(pubkey.getEncoded()));
}
/**
* initial private key and public key
*
* @throws Exception
*/
public static void instance() throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("EC", new BouncyCastleProvider());
PKCS8EncodedKeySpec encodedPrivateKey = new PKCS8EncodedKeySpec(Hex.decode(privKey));
priv = keyFactory.generatePrivate(encodedPrivateKey);
X509EncodedKeySpec encodedPublicKey = new X509EncodedKeySpec(Hex.decode(pubKey));
pub = keyFactory.generatePublic(encodedPublicKey);
}
/**
* generate public from private key
*
* @param privateKey
* @return
* @throws Exception
*/
public static PublicKey getPublicKey(PrivateKey privateKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("EC", new BouncyCastleProvider());
ECPrivateKeySpec privSpec = keyFactory.getKeySpec(privateKey, ECPrivateKeySpec.class);
ECParameterSpec privParams = privSpec.getParams();
// calculate public key
ECPoint Q = privParams.getG().multiply(privSpec.getD());
return toAsn1PublicKey(Q, getPrivateKeyOID(privateKey));
}
/**
* 从EC私钥中获取OID
*
* @param privateKey
* @return
*/
public static ASN1Primitive getPrivateKeyOID(PrivateKey privateKey) {
try (ASN1InputStream aIn = new ASN1InputStream(privateKey.getEncoded())) {
PrivateKeyInfo info = PrivateKeyInfo.getInstance(aIn.readObject());
return info.getPrivateKeyAlgorithm().getParameters().toASN1Primitive();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* return ASN1Primitive OID from publickey
*
* @param publicKey
* @return oid
*/
public static ASN1Primitive getPublicKeyOID(PublicKey publicKey) {
try (ASN1InputStream aIn = new ASN1InputStream(publicKey.getEncoded())) {
SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(aIn.readObject());
return info.getAlgorithm().getParameters().toASN1Primitive();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* encode EC PublicKey
*
* @param publicKey EC公钥
* @return 压缩的公钥
* @throws InvalidKeySpecException 不是EC公钥,抛出异常
*/
public static byte[] encodePoint(PublicKey publicKey) throws InvalidKeySpecException {
if (publicKey instanceof ECPublicKey) {
BCECPublicKey bcPubKey = (BCECPublicKey) publicKey;
return bcPubKey.getQ().getEncoded(true);
}
throw new InvalidKeySpecException("cannot identify EC public key.");
}
/**
* decode 16进制的Point X
*
* @param compressedKey
* @param curveName
* @throws InvalidKeySpecException
* @throws NoSuchAlgorithmException
*/
public static PublicKey decodePoint(String compressedKey, String curveName)
throws NoSuchAlgorithmException, InvalidKeySpecException {
X9ECParameters spec = ECNamedCurveTable.getByName(curveName);
// 根据X恢复点Y
ECPoint W = spec.getCurve().decodePoint(Hex.decode(compressedKey));
return toAsn1PublicKey(W, curveName);
}
public static PublicKey toAsn1PublicKey(ECPoint W, ASN1Primitive oid)
throws NoSuchAlgorithmException, InvalidKeySpecException {
ASN1ObjectIdentifier asn1Oid = new ASN1ObjectIdentifier(oid.toString());
String curvename = ECNamedCurveTable.getName(asn1Oid);
return toAsn1PublicKey(W, curvename);
}
/**
* ECPoint 构建ASN.1结构公钥
*
* @param W
* @param curveName
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
*/
public static PublicKey toAsn1PublicKey(ECPoint W, String curveName)
throws NoSuchAlgorithmException, InvalidKeySpecException {
KeyFactory keyFactory = KeyFactory.getInstance("EC", new BouncyCastleProvider());
X9ECParameters spec = ECUtil.getNamedCurveByName(curveName);
java.security.spec.ECParameterSpec params = new ECNamedCurveSpec(curveName, spec.getCurve(), spec.getG(),
spec.getN());
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(EC5Util.convertPoint(W), params);
return keyFactory.generatePublic(pubKeySpec);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment