How to decompress X9.62 coordinate
Asked Answered
M

1

-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)
Manful answered 16/11, 2020 at 17:30 Comment(3)
The way to proceed depends on whether the point is specified compressed or uncompressed, see here. 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 BigIntegers are to be created (new BigInteger(1, ...)) and with this the ECPoint.Brinton
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).Sandhurst
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 lapo.it/asn1js.Brinton
S
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);
Sandhurst answered 17/11, 2020 at 10:4 Comment(3)
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)Manful
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); }Manful
@Manful : 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.Sandhurst

© 2022 - 2025 — McMap. All rights reserved.