3

How to convert ECPrivateKey into ECPublicKey using FIPS BouncyCastle?

I use the following code (slightly simplified) to convert an ECPrivateKey into an ECPublicKey:

public static ECPublicKey getPublicKeyFromPrivateKey(ECPrivateKey privateKey) throws GeneralSecurityException {
    final KeyFactory keyFactory = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());
    final BCECPrivateKey bcecPrivateKey = (BCECPrivateKey) privateKey;
    final ECParameterSpec ecSpec = bcecPrivateKey.getParameters();
    final ECPoint q = ecSpec.getG().multiply(bcecPrivateKey.getD());
    final byte[] qBytes = q.getEncoded(false);
    final ECPoint point = ecSpec.getCurve().decodePoint(qBytes);
    final ECPublicKeySpec pubSpec = new ECPublicKeySpec(point, ecSpec);
    return (ECPublicKey) keyFactory.generatePublic(pubSpec);
}

This is working fine with non-FIPS BouncyCastle. Now, we have the requirement to do the same thing in a FIPS-compliant way. And here the problem is that classes like ECParameterSpec don't appear to exist in FIPS BouncyCastle 1.0.1. How can we do the same thing with FIPS BouncyCastle?

Simon Kissane
  • 4,373
  • 3
  • 34
  • 59

1 Answers1

2

I found the following solution which worked for me:

public static PublicKey getPublicKeyForPrivateKeyEC(ECPrivateKey privateKey) throws GeneralSecurityException {
    final KeyFactory keyFactory = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());
    final ECParameterSpec ecSpec = privateKey.getParams();
    final ECCurve ecCurve = FipsECUtil.convertCurve(ecSpec);
    final ECMultiplier multiplier = ecCurve.getMultiplier();
    final ECPoint generatorP = FipsECUtil.convertPoint(ecSpec, ecSpec.getGenerator());
    final ECPoint q = multiplier.multiply(generatorP, privateKey.getS());
    final byte[] publicDerBytes = q.getEncoded(false);
    final ECPoint point = ecCurve.decodePoint(publicDerBytes);
    final ECPublicKeySpec pubSpec = new ECPublicKeySpec(new java.security.spec.ECPoint(
        point.getAffineXCoord().toBigInteger(), 
        point.getAffineYCoord().toBigInteger()), ecSpec);
    return keyFactory.generatePublic(pubSpec);
}
Simon Kissane
  • 4,373
  • 3
  • 34
  • 59