Add keypair serialization/deserialization #1016

issue junderw opened this issue on November 16, 2021
  1. junderw commented at 11:12 AM on November 16, 2021: none

    As discussed in #1015

    Adding a way to serialize/deserialize keypair would help with libraries that call from WASM etc.

    Maybe it's just as simple as committing to the format of the 96 bytes it takes in memory.

    seckey(32) || P.x (32) || P.y (32)

    By committing to this format we could remove the comment: The exact representation of data inside is implementation defined and not guaranteed to be portable between different platforms or versions.

  2. siv2r commented at 2:55 PM on December 30, 2021: contributor

    I can think of three possible formats for encoding secp256k1_keypair:

    • seckey || P.x || P.y - 96 bytes (as mentioned above)
    • seckey || P.x - 64 bytes (assume P.y is even)
    • seckey || compressed pubkey - 65 bytes

    BIP-340 does not enforce any particular format for encoding the keypair. So, I checked to see if libsecp has a keypair object for ecdsa key to follow a similar serialization format, but it does not have one.

    The following libraries implementing schnorr keypair follow the 64 bytes serialization format.

    1. rust-secp256k1

    2. schnorrkel (outside bitcoin community)

      • Keypair object documentation
      • to_bytes function only uses 32 bytes from the pubkey in keypair serialization

    Which one is preferred?

  3. junderw commented at 9:06 PM on December 30, 2021: none

    Rust code is encoding the private key into 64 hex characters (32 bytes)

    I still think keypair should be 96 bytes of private, x, y.

  4. elichai commented at 9:26 AM on January 2, 2022: contributor

    Is there a specific reason why you'd want to serialize the keypair and not just the secret key and reconstruct the keypair from that? (trying to understand the use cases)

  5. junderw commented at 5:59 PM on January 2, 2022: none

    Using WASM, requiring a re-calculation of the pubkey every time you cross the JS/WASM boundary is inefficient, it would be better to have and explicit serialization format to allow for passing the info directly across boundaries.

    There are hacks to get around it. (basically just passing the raw data in the underlying format) but since this is not guaranteed, my suggestion is to offer a serialization from and to keypair and the 96 byte representation.

  6. sipa commented at 6:14 PM on January 2, 2022: contributor

    Well you can just copy the bytes of a secp256k1_keypair; they're not guaranteed to be portable across releases/platforms, but within a session of code using the library, you can copy the bytes just fine (see comment in the source code "can be safely copied/movied"). I know I suggested this feature, but perhaps it isn't needed?

    I'm slightly worried about providing an actual stable serialization for this data though; it's not supposed to be stored longer term (it's essentially a private key with a precomputed public key; keeping it anywhere but in RAM is almost certainly slower than just recomputing it, and recomputing avoids the risk of having inconsistent private/public key data which all users of this code assume).

    This isn't a NACK, I just want to make sure the expectations/requirements are clear here.


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin-core/secp256k1. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-14 18:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me