How can you derive a P-256 public key from the X and Y points

Deriving a secp256k1 public key is also possible. For whatever reason, I'm only being provided X and Y, not the public portion.

I just need to get the binary representation of the public key given that I am provided X and Y.

• I might be really dumb right now, but isn't (X, Y) point on the curve and therefore the public key? – VincBreaker Feb 1 '19 at 17:18
• It's not clear what you have and what you want. For both P-256 and secp256k1, a public key is essentially a point on the Elliptic curve, which can be described by its X/Y coordinates, or in a shorter for: X and one bit. How that is formatted into bits, then often text, depends on context. There's no way to convert from one curve to the other, but it is possible to convert from one public key format to the other, once you know what format one is talking about. – fgrieu Feb 1 '19 at 17:24
• Yes - you both are correct, the public key is an x/y point - I just need to get the binary representation of the public key given that I am provided x/y – Optical Carrier Feb 1 '19 at 17:30

There are multiple ways of encoding a EC public key in binary as well.

Probably the most compatible one is a description of the generic SubjectPublicKeyInfo as used in X.509 certificates. The encoding scheme with the ASN.1 description can be found in RFC 5480. Now you "just" need an implementation for encoding / decoding such structures (using the ASN.1 distinguished encoding rules or DER).

Note that the most compatible public point encoding is the uncompressed point encoding, consisting of an identifer byte with value 04, followed by a statically sized (32 byte) encoding of the X coordinate as unsigned big integer, followed by the identically encoded Y coordinate.

Here is the encoding of a EC key:

SEQUENCE (2 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.10045.2.1 ecPublicKey (ANSI X9.62 public key type)
OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named elliptic curve)
BIT STRING (520 bit) 0000010011011011100101100101010011000111100010000110001111111011011100…


Here is the hexadecimal encoding, with the X and Y coordinate shown:

30 59
30 13
06 07 2A 86 48 CE 3D 02 01
06 08 2A 86 48 CE 3D 03 01 07
03 42 00

04

DB 96 54 C7 88 63 FB 73 26 BD C8 2A A4 28 8F 3B
B6 9C 96 4C B2 E1 8F 39 A4 3A 96 6F 87 2E 9C 79

B1 F8 FB F7 84 A4 9C AF 10 17 92 4D F6 8E D7 43
63 9F 9C 76 01 2C AC DE 86 72 7D 85 FD 23 F3 DF


As all the sizes are static, you should be able to simply create a statically sized, unsigned, big endian encoding of X and Y and place them after the header - which is anything before the X and the Y coordinates above, of course.

Possibly you may only require the encoding of the point, 04 with the X and Y coordinate following that as displayed above. That's a binary encoding as well, that can be used if the algorithm and curve is already known.

Beware that the statically encoded size of the points very much depends on the field size of the curve; this answer is therefore only valid for this particular curve.

• More than this I cannot really tell from your sparse description, good luck. – Maarten Bodewes Feb 2 '19 at 1:39
• For the avoidance of doubt: the X,Y values in X9.62/SEC1 uncompressed are 32 octets for the two curves mentioned in the Q, but in general are the size of the curve's underlying field and that varies depending on the curve. – dave_thompson_085 Feb 2 '19 at 9:57