-1

I am passing a byte[] to my method and I am trying to generate a pubKey. Looking at the error look's like i first need to decompress before generating pubKey.

How can I decode a compressed coordinate ?

private static PublicKey getPublicKeyFromBytes(byte[] pubKey) throws NoSuchAlgorithmException, InvalidKeySpecException 
{
       
        ECPoint point = new ECPoint(new BigInteger(pubKey), BigInteger.ZERO);
        ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("prime256v1");
        KeyFactory kf = KeyFactory.getInstance("ECDSA", new BouncyCastleProvider());
        ECNamedCurveSpec params = new ECNamedCurveSpec("prime256v1", spec.getCurve(), spec.getG(), spec.getN());
        ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(point, params);
        ECPublicKey pk = (ECPublicKey) kf.generatePublic(pubKeySpec);
        return pk;
}

Error message:

Exception in thread "main" java.security.spec.InvalidKeySpecException: invalid KeySpec: x value invalid for SecP256R1FieldElement
    at org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi.engineGeneratePublic(Unknown Source)
user2748161
  • 89
  • 1
  • 3
  • 15
  • The way to proceed depends on whether the point is specified compressed or uncompressed, see [here](https://crypto.stackexchange.com/a/56442). E.g., if it is specified uncompressed, the leading byte is 04, the next 32 bytes are the x-coordinate and the next 32 bytes are the y-coordinate (for prime256v1). For x and y unsigned `BigInteger`s are to be created (`new BigInteger(1, ...)`) and with this the `ECPoint`. – Topaco Nov 16 '20 at 18:13
  • It would be easier to help you, if you could include the public key you are trying to read. Just include the output of `Base64.getEncoder().encodeToString(pubKey)`. – Rasmus Faber Nov 17 '20 at 09:48
  • On my machine, `getPublicKeyFromBytes()` triggers the posted error for an uncompressed as well as compressed X9.62 key, i.e. from the error it can't be concluded whether your data represents an uncompressed or compressed key (or even another format). In contrast, `loadPubKey()` works for both, an uncompressed as well as compressed X9.62 key. Since your data triggers an error with the latter method, your data probably doesn't match the X9.62 format. Maybe it's an X.509 key. If you don't want to post the key, you can check this e.g. with https://lapo.it/asn1js/. – Topaco Nov 17 '20 at 20:09

1 Answers1

2

If your pubKey is an X9.62 compressed or uncompressed point you can use the decodePoint()-method on the ECCurve:

ECPoint point = spec.getCurve().decodePoint(pubKey);
Rasmus Faber
  • 48,631
  • 24
  • 141
  • 189
  • when i use curve.decodePoint(pubKey) I am getting invalid point `in thread "main" java.lang.IllegalArgumentException: Invalid point encoding 0x-58 at org.bouncycastle.math.ec.ECCurve.decodePoint(Unknown Source)` – user2748161 Nov 17 '20 at 17:24
  • `public static PublicKey loadPubKey(byte[] encodedPublicKey) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException { KeyFactory kf = KeyFactory.getInstance("ECDH", new BouncyCastleProvider()); ECParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("prime256v1"); ECCurve curve = parameterSpec.getCurve(); ECPoint point = curve.decodePoint(encodedPublicKey); ECPublicKeySpec pubSpec = new ECPublicKeySpec(point, parameterSpec); return kf.generatePublic(pubSpec); }` – user2748161 Nov 17 '20 at 17:27
  • @user2748161 : According to the error message your encoded point starts with 0xA8 (-0x58). That doesn't match any format that I can think of. At this point I can't help you further unless you post the key (feel free to blank out stuff in the middle, even though you shouldn't have a problem with posting a _public_ key) or at least lets us know exactly where the data is coming from. – Rasmus Faber Nov 18 '20 at 08:23