I asked this question on StackOverflow but it seems like it's more appropriate for this Crypto community.

I am using the browser built in SubtleCrypto library in javascript to generate public and private keys as such:

let keyPair = await crypto.subtle.generateKey(
        name: "ECDSA",
        namedCurve: "P-521",
    ['sign', 'verify']
let exportedPublicKey = await crypto.subtle.exportKey("jwk", keyPair.publicKey)
let exportedPrivateKey = await crypto.subtle.exportKey("jwk", keyPair.privateKey)

This generates the following (just a test key):

enter image description here

Is there a way to convert the exported keys into a bit more "portable" format? Something which isn't JSON, isn't super long, maybe hex format? Maybe compressed format?

I tried passing "raw" instead of "jwk" for the exportKey function and that returns an "Operation is not supported" error because it's probably not supported for this format.

For example, Eth-Crypto has a publicKey.compress() way to compress the public key into a short enough string: '03a34d6aef3eb42335fb3cacb59478c0b44c0bbeb8bb4ca427dbc7044157a5d24b'


Similarly, Schnorr keys are also pretty short.

One of the comments to my question says that I can extract the parameters d, x and y and With x and y, creating the uncompressed/compressed key is trivial.

However, I am not sure how to do the second part regarding creating the uncompressed/compressed key from the extracted x, y and d. How can I do that?

  • 1
    $\begingroup$ For general EC crypto, there are several other portable representations (PKCS8 and SPKI, OpenPGP, also OpenSSH 'new' to an extent) but they aren't shorter. For some cryptocurrencies there are shorter forms that are limited to only one curve and thus are not portable; in particular the Ethereum form you show is only for secp256k1 not P521 (secp521r1). $\endgroup$ May 25, 2023 at 0:44
  • $\begingroup$ @dave_thompson_085 even if not shorter, how can I convert the JWK format to a hex/byte string format? $\endgroup$ May 25, 2023 at 2:23
  • 1
    $\begingroup$ Standard format for the point forming a compressed ECDSA public key is in sec1v2, §2.3.3, case 3. For P-521 that's 67 bytes: the byte 02 or 03 according to the low-order bit of $y\bmod p$, and 66 bytes coding $x\bmod p$ (big-endian). Some wrap this in the ASN.1 encoding for the full public key, see appendix C.3. Extra attributes and text encoding are application-dependent, and largely off-topic. Libraries to perform this are off-topic. Cross-posted. $\endgroup$
    – fgrieu
    May 25, 2023 at 8:20