从ECPrivateKey生成ECPublicKey

我正在尝试使用私钥和已知曲线生成公钥。 以下是我的代码:

// Generate Keys ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("secp256r1"); KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDSA", "BC"); keyPairGenerator.initialize(ecGenSpec, new SecureRandom()); java.security.KeyPair pair = keyPairGenerator.generateKeyPair(); ECPrivateKey privateKey = (ECPrivateKey) pair.getPrivate(); ECPublicKey publicKeyExpected = (ECPublicKey) pair.getPublic(); // Expected public key System.out.print("Expected Public Key: " + BaseEncoding.base64Url().encode(publicKeyExpected.getEncoded())); // Generate public key from private key X9ECParameters ecp = SECNamedCurves.getByName("secp256r1"); ECDomainParameters domainParams = new ECDomainParameters(ecp.getCurve(), ecp.getG(), ecp.getN(), ecp.getH(), ecp.getSeed()); ECPoint Q = domainParams.getG().multiply(privateKey.getS()); // is this correct? KeyFactory kf = KeyFactory.getInstance("ECDSA", "BC"); ECPublicKey publicKeyGenerated = (ECPublicKey) kf.generatePublic(new X509EncodedKeySpec(Q.getEncoded(false))); // exception here // Generated public key from private key System.out.print("Generated Public Key: " + BaseEncoding.base64Url().encode(publicKeyGenerated.getEncoded())); 

但是,当我调用: kf.generatePublic(new X509EncodedKeySpec(Q.getEncoded(false)))我得到exception: java.security.spec.InvalidKeySpecException: encoded key spec not recognised (不是我的拼写错误)

我似乎错误地计算Q ,但我不确定我的错误在哪里。

谢谢您的帮助!

如果我未来的自我需要解决方案:

 // Generate Keys ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("secp256r1"); KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDSA", "BC"); keyPairGenerator.initialize(ecGenSpec, new SecureRandom()); java.security.KeyPair pair = keyPairGenerator.generateKeyPair(); ECPrivateKey privateKey = (ECPrivateKey) pair.getPrivate(); ECPublicKey publicKeyExpected = (ECPublicKey) pair.getPublic(); // Expected public key System.out.print("Expected Public Key: " + BaseEncoding.base64Url().encode(publicKeyExpected.getEncoded())); // Generate public key from private key KeyFactory keyFactory = KeyFactory.getInstance("ECDSA", "BC"); ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("secp256r1"); ECPoint Q = ecSpec.getG().multiply(privateKey.getD()); byte[] publicDerBytes = Q.getEncoded(false); ECPoint point = ecSpec.getCurve().decodePoint(publicDerBytes); ECPublicKeySpec pubSpec = new ECPublicKeySpec(point, ecSpec); ECPublicKey publicKeyGenerated = (ECPublicKey) keyFactory.generatePublic(pubSpec); // Generated public key from private key System.out.print("Generated Public Key: " + BaseEncoding.base64Url().encode(publicKeyGenerated.getEncoded())); 

对@markw的答案进行了一些改进,从@ bas-goossen扩展了曲线名称检测: 如何从ECPublicKey中找到匹配的曲线名称

 public static ECPublicKey publicFromPrivate(final ECPrivateKey privateKey) throws Exception { ECParameterSpec params = privateKey.getParams(); org.bouncycastle.jce.spec.ECParameterSpec bcSpec = org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util .convertSpec(params, false); org.bouncycastle.math.ec.ECPoint q = bcSpec.getG().multiply(privateKey.getS()); org.bouncycastle.math.ec.ECPoint bcW = bcSpec.getCurve().decodePoint(q.getEncoded(false)); ECPoint w = new ECPoint( bcW.getAffineXCoord().toBigInteger(), bcW.getAffineYCoord().toBigInteger()); ECPublicKeySpec keySpec = new ECPublicKeySpec(w, tryFindNamedCurveSpec(params)); return (ECPublicKey) KeyFactory .getInstance("EC", org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME) .generatePublic(keySpec); } @SuppressWarnings("unchecked") public static ECParameterSpec tryFindNamedCurveSpec(ECParameterSpec params) { org.bouncycastle.jce.spec.ECParameterSpec bcSpec = org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util.convertSpec(params, false); for (Object name : Collections.list(org.bouncycastle.jce.ECNamedCurveTable.getNames())) { org.bouncycastle.jce.spec.ECNamedCurveParameterSpec bcNamedSpec = org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec((String) name); if (bcNamedSpec.getN().equals(bcSpec.getN()) && bcNamedSpec.getH().equals(bcSpec.getH()) && bcNamedSpec.getCurve().equals(bcSpec.getCurve()) && bcNamedSpec.getG().equals(bcSpec.getG())) { return new org.bouncycastle.jce.spec.ECNamedCurveSpec( bcNamedSpec.getName(), bcNamedSpec.getCurve(), bcNamedSpec.getG(), bcNamedSpec.getN(), bcNamedSpec.getH(), bcNamedSpec.getSeed()); } } return params; }