Last active
February 8, 2022 07:46
-
-
Save Gsealy/778efb420d325582541a1ec67a98b73e to your computer and use it in GitHub Desktop.
EC秘钥对工具,计算公钥,压缩公钥,解压缩,转换为ASN.1结构
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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