2

I would like to get a compressed EC public key representation, and I did this by following this answer. But when I try to cast a java.security.PublicKey to a org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey I get an exception:

jdk.crypto.ec/sun.security.ec.ECPublicKeyImpl cannot be cast to org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey

Imports:

import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.math.ec.ECPoint;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;

Code:

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256k1");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
keyGen.initialize(ecSpec, random);
KeyPair pair = keyGen.generateKeyPair();

ECPoint ecPoint = ((BCECPublicKey) pair.getPublic()).getQ(); - Exception

System.out.println(new String(ecPoint.getEncoded(true)));
SwagiWagi
  • 411
  • 5
  • 17
  • 2
    You can create an instance with `BCECPublicKey bcecPublicKey = new BCECPublicKey((ECPublicKey)pair.getPublic(), BouncyCastleProvider.CONFIGURATION)` and get the public key in compressed format with `bcecPublicKey.getQ().getEncoded(true)`. – Topaco Jan 15 '21 at 20:51

1 Answers1

2

KeyPairGenerator.getInstance(String) gets you the first security provider that implements the given algorithm. Without further configuration it is "SunEC".

Since you clearly want to rely on BouncyCastle to generate your key, use the 2 parameter factory method:

final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME);

However, if you were to receive the KeyPair object as parameter, you can not assume it comes from BouncyCastle and you should convert it manually to a BCECPublicKey as in Topaco's comment:

final BCECPublicKey pubKey = pair.getPublic() instanceof BCECPublicKey
  ? (BCECPublicKey) pair.getPublic()
  : new BCECPublicKey((ECPublicKey) pair.getPublic(), BouncyCastleProvider.CONFIGURATION);
Piotr P. Karwasz
  • 12,857
  • 3
  • 20
  • 43
  • Check [this answer](https://stackoverflow.com/a/33347595/11748454): your data just contains a point coordinates, you need the curve to have a public key. – Piotr P. Karwasz Jan 22 '21 at 18:26