Ring: API for obtaining ECDSA public key from an ECDSAKeyPair

Created on 6 Jul 2018  路  9Comments  路  Source: briansmith/ring

For context, the Ed25519KeyPair has a public_key_bytes() method that can be used to obtain a serialized Ed25519 public key from a keypair.

There is no cooresponding API, from what I can tell, to obtain a serialized public key from an ECDSAKeyPair. It seems ECDSAKeyPair discards the public key and stores only the Scalar after e.g. loading a PKCS#8 file.

This would be useful to me as for my application I'm dynamically generating keypairs. I think I've figured out how to work around this by extracting the public key from the generated PKCS#8 file, but I think it'd be nice to have a first-class API for getting a serialized public key for an ECDSAKeyPair like there is for Ed25519KeyPair.

Most helpful comment

  • Generate a random keypair

https://briansmith.org/rustdoc/ring/signature/struct.Ed25519KeyPair.html#method.generate_pkcs8
https://briansmith.org/rustdoc/ring/signature/struct.EcdsaKeyPair.html#method.generate_pkcs8

  • Obtain the public key portion of the keypair

https://briansmith.org/rustdoc/ring/signature/trait.KeyPair.html#tymethod.public_key

I can't find any examples that show how to generate a key, obtain the corresponding public key, and use that to verify a signature.

https://briansmith.org/rustdoc/ring/signature/index.html#signing-and-verifying-with-ed25519

All 9 comments

I think there are three issues:

  1. There's no type that represents a (serialized) public key for signature verification; we just use &[u8] but that doesn't work well for returning a copy of the public key from a function.
  2. Generating a ECDSA keypair that one doesn't need to be serialized. In this case, it would be nice to avoid PKCS#8 completely and return the private key directly along with the public key, or allow the public key to be extracted from private key. Either way, I think we'd need to do (1) first.
  3. There's no way to get the public key from the private key loaded from a PKCS#8 document. At one time I considered this a feature because I believe that a better API would require the caller to pass in the public key as an input to ensure they know what public key they want, but now I admit it is too limiting for general-purpose use.

FWIW, the use case where this came up was 2. I'm simulating an HSM and wanted to generate and store a random key, and then return its public key via the HSM's public key command.

Another use case is in Signatory:

https://github.com/tendermint/signatory/blob/c97b4d876908990a6e97313647c02d0b22d31e48/src/providers/ring/ecdsa.rs#L48

Signatory's signer traits presently require all signers have a method for obtaining the public key. This is particularly useful for building abstractions across hardware and software signers, since it provides a simple, common API for handling public keys that isn't tangled up with initializing the signers, where building trait abstractions is a lot trickier since loading a key from a byte slice versus initializing a hardware device are quite a bit different.

That said, re: 3) I do see the case for initializing all signers with a public key. I can think about how to build traits that unify the initialization of soft and hard signers which takes a public key as input, rather than a method that outputs one.

Why do we need ECDSAKeyPair or any KeyPair in the library? Wouldn't it be better to deal simply with an algorithm and keys? This way we won't make any assumptions on how user will use them. If a user want to organize them, the stuct can be simply created on the application level.

let (public_key, private_key) = generate_keys(alg);
let signature = sign(alg, private_key, message);
verify(alg, public_key, message, signature);

Why do we need ECDSAKeyPair or any KeyPair in the library? Wouldn't it be better to deal simply with an algorithm and keys? This way we won't make any assumptions on how user will use them. If a user want to organize them, the stuct can be simply created on the application level.

  1. For symmetry: EdDSA private keys don't work without knowing the public key. RSA private keys don't work without the public key.

  2. For security, part 1: It is somewhat unusual that ECDSA private keys can do something interesting without the public key; in fact it is a sign of badness because as it means the public key isn't )(can't be) incorporated into the signature at the ECDSA signing primitive layer. If you are designing a new protocol then you should be sure that the public key is incorporated into every signature at some level.

  3. For security, part 2: It is generally good practice to load a private key by these steps: Find the public key (and identity) I want to use, then load the private key for that public key. One should mathematically and/or cryptographically verify that the private key corresponds to the public key that is being shared with peers. If you don't do it this way then you are risking using the wrong private key. (Note that even NIST recommends this.)

Unless I'm missing something, as of ring 0.14 this is no longer possible with either ECDSA or Ed25519:

  • Generate a random keypair
  • Obtain the public key portion of the keypair

The latter used to be possible for ed25519::signing::KeyPair using the public_key_bytes method but that was removed.

I can't find any examples that show how to generate a key, obtain the corresponding public key, and use that to verify a signature.

For ECDSA I've written my own hacks to extract the public key from the generated PKCS#8 document. Is there some API for this I'm missing?

  • Generate a random keypair

https://briansmith.org/rustdoc/ring/signature/struct.Ed25519KeyPair.html#method.generate_pkcs8
https://briansmith.org/rustdoc/ring/signature/struct.EcdsaKeyPair.html#method.generate_pkcs8

  • Obtain the public key portion of the keypair

https://briansmith.org/rustdoc/ring/signature/trait.KeyPair.html#tymethod.public_key

I can't find any examples that show how to generate a key, obtain the corresponding public key, and use that to verify a signature.

https://briansmith.org/rustdoc/ring/signature/index.html#signing-and-verifying-with-ed25519

Appears the KeyPair trait is what I was looking for.

Was this page helpful?
0 / 5 - 0 ratings