oos1111
oos1111

Reputation: 63

How can I get X and Y components from a ECC public key in PEM format without private key?

I know we can use openssl to do that. However that requires the private key. In my case, I don't have the private key and only have the public key. I uses Google Cloud HSM and the private key is not accessible directly. I can only download the public key. Then how can I do it?

My public key, it uses secp256r1:

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhspCFgsa/oSDJajb8DvaLhLURUbD
C2UXU1E/a//ht4NMLTadhSMc195SL8YD55tPXR6bvERBrZfYEmpBlkr8BQ==
-----END PUBLIC KEY-----

Upvotes: 2

Views: 2722

Answers (2)

Simon G.
Simon G.

Reputation: 6707

Is openssl required as the solution? I cannot see a way of getting the information you ask for that way.

I got this information via a simple Java program:

Curve Name: secp256r1 [NIST P-256,X9.62 prime256v1] (1.2.840.10045.3.1.7)
Public Key X Coordinate (hex): c015519931128efe3dfd267250c4f9547dd0d6ac39823e0e5581212020210976
Public Key Y Coordinate (hex): 771433a3cdbb28a7a0522038af4aee45d43d0226439ca752db416eea21ad6076

The Java code:

String keyAsTxt = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhspCFgsa/oSDJajb8DvaLhLURUbDC2UXU1E/a//ht4NMLTadhSMc195SL8YD55tPXR6bvERBrZfYEmpBlkr8BQ==";
byte[] keyAsBytes = Base64.getDecoder().decode(keyAsTxt);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyAsBytes);
KeyFactory keyFactory = KeyFactory.getInstance("EC");
PublicKey publicKey = keyFactory.generatePublic(keySpec);

if (publicKey instanceof ECPublicKey) {
    ECPublicKey ecPublicKey = (ECPublicKey) publicKey;
    String xCoord = ecPublicKey.getW().getAffineX().toString(16);
    String yCoord = ecPublicKey.getW().getAffineY().toString(16);

    ECParameterSpec ecSpec = ecPublicKey.getParams();
    String curveName = ecSpec.toString(); // This will give you the curve parameters

    System.out.println("Curve Name: " + curveName);
    System.out.println("Public Key X Coordinate (hex): " + xCoord);
    System.out.println("Public Key Y Coordinate (hex): " + yCoord);
}

Upvotes: 4

Tobias K.
Tobias K.

Reputation: 3082

You could use:

openssl ec -pubin -noout -text -conv_form uncompressed

This will output:

Public-Key: (256 bit)
pub:
    04:86:ca:42:16:0b:1a:fe:84:83:25:a8:db:f0:3b:
    da:2e:12:d4:45:46:c3:0b:65:17:53:51:3f:6b:ff:
    e1:b7:83:4c:2d:36:9d:85:23:1c:d7:de:52:2f:c6:
    03:e7:9b:4f:5d:1e:9b:bc:44:41:ad:97:d8:12:6a:
    41:96:4a:fc:05
ASN1 OID: prime256v1
NIST CURVE: P-256

04 indicating it is uncompressed (we forced this), the X and Y coordinates are just concatenated behind each other:

X (hex): 86:ca:42:16:0b:1a:fe:84:83:25:a8:db:f0:3b:da:2e:12:d4:45:46:c3:0b:65:17:53:51:3f:6b:ff:e1:b7:83
Y (hex): 4c:2d:36:9d:85:23:1c:d7:de:52:2f:c6:03:e7:9b:4f:5d:1e:9b:bc:44:41:ad:97:d8:12:6a:41:96:4a:fc:05

A possible bash pipeline could be (would need to assure openssl text cli output is stable):

| grep -E "^ +.*" | tr -d ' \n' | sed 's/^...//' | sed 's/./ /96'

Upvotes: 1

Related Questions