Search code examples
javasecuritycryptographybouncycastlepublic-key

Generate ECPublicKey from ECPrivateKey


I'm trying to generate a public key given a private key and known curve. Below is my code:

// 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()));

However, when I call: kf.generatePublic(new X509EncodedKeySpec(Q.getEncoded(false))) I get the exception: java.security.spec.InvalidKeySpecException: encoded key spec not recognised (not my misspelling)

I appears I'm incorrectly calculating Q, but I'm not sure where my error is.

Thanks for the help!


Solution

  • In case my future self needs the solution:

    // 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());
    ECPublicKeySpec pubSpec = new ECPublicKeySpec(Q, ecSpec);
    ECPublicKey publicKeyGenerated = (ECPublicKey) keyFactory.generatePublic(pubSpec);
    
    // Generated public key from private key
    System.out.print("Generated Public Key: " +
            BaseEncoding.base64Url().encode(publicKeyGenerated.getEncoded()));