3

I generate a key on the HSM through the Graphene library, except when I try to get the public key raw value by getting its 'pointEC' attribute (equivalent to CKA_EC_POINT), I get a 134 character string:

044104c9d5b656518b5b7e0d747b86328c37a0d507de9b3863a43e77b559ab60c0f9b15985f83a8c20588164c0634f98eb4a4cf8ce70020e94ae21a247904fac8b1010

Now, I understand for this standard there's an X and Y integer, but I read that some math is required to make them valid for generating an Ethereum address. I also understand that the '04' means that it is an uncompressed public key, but I do not know why the '4104' keeps popping up or what it means. Are these just different ways of representing the same data? Could I just take the last 128 characters and hash it for a valid Ethereum address?

  • Have you tried it? – BadZen Apr 18 '19 at 14:01
  • The Ethereum address is just the Keccak hash of the last 20 bytes of the public key. So - last 40 characters. You'll need to make sure the public key is formatted similarly though, since you're getting it from some HSM and it's a raw value (byte order, x/y coordinate order in point, padding above 32 bits possible, etc). – BadZen Apr 18 '19 at 14:02
  • Is there a way to test if it'd be valid without making an actual transaction? I would just hash the last 128 characters, correct? – Carlos Hernandez Apr 18 '19 at 14:31

1 Answers1

7

What you are seeing is a BER/DER encoded uncompressed point. The first byte valued 04 is not the uncompressed point indicator. That's the 3rd byte. The first byte valued 04 encodes the tag byte for an ASN.1 OCTET STRING (also known as a byte array to most developers). You can view the structure here.

The byte with hex value 41 is the size of the bytes that comes after: 1 byte for the 04 uncompressed point indicator, 32 bytes for the statically sized X-coordinate and 32 bytes for the Y-coordinate.

So yes, you can take the last 64 bytes and split it in two if you need the X- and Y-coordinate. The 128 characters are just the hexadecimal representation of those bytes - but you should just worry about the bytes.

Of course, what you should do is to parse the ASN.1, determine and validate the length, take the uncompressed point, decode it and check that it is on the curve to validate your input. An EC key is valid if it includes the correct parameters. For Ethereum / BitCoin the curve is however implicitly known (secp256k1).

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • So to take the address, do I or do I NOT hash the public key with the 04? With the 0x? – Carlos Hernandez Apr 22 '19 at 19:51
  • No, what you hash is the bytes of the public key. So that's without either `04` byte and length encoding. I.e. it's just the last 64 bytes. After a bit of a search I found this info [here](https://etherworld.co/2017/11/17/understanding-the-concept-of-private-key-public-key-and-address-in-ethereum-blockchain/). Then you take the rightmost 20 bytes of the resulting hash hash. Do NOT hash the hexadecimal encoding or the `0x` bytes. Again, that's just the human readable representation of the key. – Maarten Bodewes Apr 22 '19 at 22:12