Skip to content

signature 2.0 tracking issue #237

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
tarcieri opened this issue Jul 29, 2020 · 9 comments
Closed

signature 2.0 tracking issue #237

tarcieri opened this issue Jul 29, 2020 · 9 comments
Labels
digest Hash function crate signature Digital signature crate

Comments

@tarcieri
Copy link
Member

tarcieri commented Jul 29, 2020

This is a tracking ticket for potential breaking changes to the signature crate which target a 2.0 release. There's no planned release date for this besides "some time after a minimum viable implementation of const generics in stable Rust", so this issue is mostly for brainstorming and tracking current defects/issues which require SemVer breaking changes to address.

As a bit of background, the impetus for stabilizing an initial 1.0 release was to also allow for a 1.0 release of the ed25519 crate. The signature and ed25519 crates together allow for writing code which is generic over how Ed25519 signing and/or verification is implemented. These traits and signature types are now used by ed25519-dalek as well as the signatory crates.

This stabilization, while providing a useful 1.0 for Ed25519, made a number of compromises (see #78). Most notably, while there are many ways it could benefit from either generic-array or const generics, the public API avoided them both, mainly to avoid having every generic-array bump be a SemVer breaking change and get to a reasonably useful 1.0 quickly.

All of that said, it seems the minimum viable implementation of const generics may be coming sooner than we think, potentially in 2020. This issue is intended to track potential proposals that could use them, as well as existing API defects it'd be nice to fix in a SemVer breaking release.


Replace AsRef<[u8]> bound on Signature trait with associated const SIZE and Into<[u8; Self::SIZE]> bound

The AsRef bound provides a common API for converting a signature into a byte slice, but has the following limitations:

  • Requires "bag-of-bytes" signature types as opposed to ones with internal structure: the current API requires that all signature types provide a simple reference conversion to a byte slice, which precludes an intermediate parsing step to e.g. well-structured scalar or group element types. With const generics, this can be replaced with an Into conversion to a byte array, allowing an intermediate serialization step from these well-structured types to a "bag-of-bytes" wire representation.
  • No way to bound on signature size: by not providing type-level information about the signature size at all, the type system can't reason about signature sizes. This would mainly be useful for doing type-level calculations of the sizes of messages that incorporate signatures in a way that's generic over the signature size.

Disable std Cargo feature by default

This is a notable inconsistency with the other RustCrypto/traits crates, and since all of these crates have a no_std focus, it's nice to have this off-by-default.

The std feature is used entirely for the purposes of error handling to gate a std::error::Error impl which, when std is available, can provide a Box-ed source.

Error improvements

Presently in any no_std context, including ones with alloc, the error source is lost. It seems like some middle ground is possible in the alloc case, like retaining the source, but exposing it through an inherent method rather than std::error::Error. This could even be defined in a way that's purely additive by having the std::error::Error impl invoke the inherent Error::source method.

Stabilization of *-preview features.

Since many features of the signature crate are also blocked on const generics for a 1.0 release, they were shipped as *-preview features, with a SemVer guarantee that breaking changes to *-preview features would come with a minor version bump (more or less the same way it works with 0.x versions).

There are open tracking issues for each of these features:

It would probably make sense to stabilize the digest feature first via a const generics-based digest 1.0 crate, then have signature 2.0 depend on digest 1.0 (See #238).

@shamatar
Copy link

Is there are plan to extend traits to support Schnorr signatures where it's necessary to specify a Fiat-Shamir transformation function over message, public key and nonce? Same thing potentially applies to EdDSA.

Separately, hazmat functions take scalar-like secret value https://docs.rs/ecdsa/0.8.1/ecdsa/hazmat/trait.SignPrimitive.html Would it be reasonable to separate/duplicate Scalar into PublicScalar (s value of the signature) and SecretScalar (private key, nonce)? In can not prevent a reuse, but may hint a user.

@tarcieri
Copy link
Member Author

tarcieri commented Sep 26, 2020

Is there are plan to extend traits to support Schnorr signatures where it's necessary to specify a Fiat-Shamir transformation function over message, public key and nonce? Same thing potentially applies to EdDSA.

In cases like this, Signer and Verifier traits presently expect the signature algorithm implementation to handle this internally. This is how these traits are impl'd in ed25519-dalek, for example:

https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.Keypair.html#impl-Signer%3CSignature%3E

Would it be reasonable to separate/duplicate Scalar into PublicScalar (s value of the signature) and SecretScalar (private key, nonce)?

The closest thing to that right now is the elliptic_curve::SecretKey type, which provides a self-zeroizing wrapper around a Scalar value which also ensures the inner value isn't leaked via Debug impls:

https://docs.rs/elliptic-curve/0.6.2/elliptic_curve/secret_key/struct.SecretKey.html

@burdges
Copy link

burdges commented Sep 26, 2020

I prefer if symmetric cryptography overall transitioned to more flexible STROBE-like constructions, ala merlin, etc., and abstractions that permit judicious usage of asymmetric primitives, ala zk circuit friendly primitives, MuSig-DN, etc. I presume this lies beyond the RustCrypto "mandate", which seems more about providing monomorphised but flexible access to the historical constructions. I therefore do not view this as particularly relevant here, but really "signatures" should be doing this aggressively.

I want VRFs to become "user friendly" too. I think teaching "VRFs are signatures" is a part of that story, but actually placing VRFs and signatures behind a common abstraction sounds far more harmful than useful: Almost all sane VRFs sign two+ things while signatures sign only one. VRFs require different batching interfaces. etc. Again nothing relevant for signature 2.0 I think, but I'll keep experimenting with different VRF interfaces elsewhere.

@tarcieri
Copy link
Member Author

tarcieri commented Sep 26, 2020

I presume this lies beyond the RustCrypto "mandate", which seems more about providing monomorphised but flexible access to the historical constructions.

RustCrypto generally has a focus on "mainstream" cryptography, for lack of a better word.

I want VRFs to become "user friendly" too.

I'm a big fan of VRFs and perhaps RustCrypto should provide some VRF traits.

I definitely also think of them as a (randomly) commit and verify scheme consisting of a random-looking value and a proof, where in many use cases you want to publish the former and sequester the latter.

@burdges
Copy link

burdges commented Sep 26, 2020

I took a direct approach to a VRF interface in https://github.com/w3f/schnorrkel/blob/master/src/vrf.rs but the results proved disappointing. I'm experimenting with a new de-builder methods approach in https://github.com/w3f/ring-vrf/blob/master/src/schnorr.rs but maybe overly complex.

It's tricky because you have n+1 messages, and n outputs for which you should often but not always hide access until after verification, you need pre-outputs to be serializable only inside the signature, not hashable, etc., your batch verifiable form differs, and this pre-ring VRF has another component that interfaces with the SNARK.

Aside form ring/group VRFs, there are no good options besides Schnorr DLEQ proofs, like VEd25519, schnorrkel, etc. right now: Any unique signature like BLS, RSA-FDH, etc. suck because you always want a VRF signature to sign extra data not fed into one of the VRF inputs in practice. Rabin-Williams might prove interesting, purely for speed. And PQ sounds wide open.

@shamatar
Copy link

Hey Jeff! :)

I would love to see good generic MuSig-DN with may be other hash function to generate nonce, e.g. Rescue is as good PRF for this purpose and should have less constraints.

@tarcieri
Copy link
Member Author

A note on this:

Replace AsRef<[u8]> bound on Signature trait with associated const SIZE and Into<[u8; Self::SIZE]> bound

We still need to support variable-width signatures for ASN.1 DER-encodings. So it seems we may need separate traits to support fixed-width versus variable-width encodings.

tarcieri added a commit that referenced this issue Oct 24, 2022
This commit contains the first breaking changes to the `signature` crate
made since its initial 1.0 stabilization. Planning for these changes
occurred in #237.

The following changes have been made:

- The `Signature` trait has been renamed to `SignatureEncoding`. The
  `Signature` bound on `*Signer` and `*Verifier` traits has been
  removed, meaning there are no longer any mandatory trait bounds on the
  signature paramters at all.

- The `AsRef<[u8]>` bound formerly found on the `Signature` crate has
  been replaced with an associated `Repr` type, inspired by the
  `group::GroupEncoding` trait. This means signature types no longer
  need to retain a serialized form, and can parse the bag-of-bytes
  representation to something more convenient, which is useful for e.g.
  batch verification.

- The `std` feature is no longer enabled by default, which matches the
  other RustCrypto/traits crates.

- The `derive-preview` and `hazmat-preview` features have been
  stabilized.

- The former `Keypair` trait has been renamed to `KeypairRef`, and the
  signature generic parameter removed. A new `Keypair` trait has been
  added which returns an owned instance of the associated
  `VerifyingKey`, and a blanket impl of `Keypair` for `KeypairRef` has
  been added. This addresses the issues described in #1124.
@tarcieri
Copy link
Member Author

I've opened a PR which prospectively implements some of the changes planned in this issue: #1141

tarcieri added a commit that referenced this issue Oct 24, 2022
This commit contains the first breaking changes to the `signature` crate
made since its initial 1.0 stabilization. Planning for these changes
occurred in #237.

The following changes have been made:

- The `Signature` trait has been renamed to `SignatureEncoding`. The
  `Signature` bound on `*Signer` and `*Verifier` traits has been
  removed, meaning there are no longer any mandatory trait bounds on the
  signature paramters at all.

- The `AsRef<[u8]>` bound formerly found on the `Signature` crate has
  been replaced with an associated `Repr` type, inspired by the
  `group::GroupEncoding` trait. This means signature types no longer
  need to retain a serialized form, and can parse the bag-of-bytes
  representation to something more convenient, which is useful for e.g.
  batch verification.

- The `std` feature is no longer enabled by default, which matches the
  other RustCrypto/traits crates.

- The `derive-preview` and `hazmat-preview` features have been
  stabilized.

- The former `Keypair` trait has been renamed to `KeypairRef`, and the
  signature generic parameter removed. A new `Keypair` trait has been
  added which returns an owned instance of the associated
  `VerifyingKey`, and a blanket impl of `Keypair` for `KeypairRef` has
  been added. This addresses the issues described in #1124.
tarcieri added a commit that referenced this issue Oct 24, 2022
This commit contains the first breaking changes to the `signature` crate
made since its initial 1.0 stabilization. Planning for these changes
occurred in #237.

The following changes have been made:

- The `Signature` trait has been renamed to `SignatureEncoding`. The
  `Signature` bound on `*Signer` and `*Verifier` traits has been
  removed, meaning there are no longer any mandatory trait bounds on the
  signature paramters at all.

- The `AsRef<[u8]>` bound formerly found on the `Signature` crate has
  been replaced with an associated `Repr` type, inspired by the
  `group::GroupEncoding` trait. This means signature types no longer
  need to retain a serialized form, and can parse the bag-of-bytes
  representation to something more convenient, which is useful for e.g.
  batch verification.

- The `std` feature is no longer enabled by default, which matches the
  other RustCrypto/traits crates.

- The `derive-preview` and `hazmat-preview` features have been
  stabilized.

- The former `Keypair` trait has been renamed to `KeypairRef`, and the
  signature generic parameter removed. A new `Keypair` trait has been
  added which returns an owned instance of the associated
  `VerifyingKey`, and a blanket impl of `Keypair` for `KeypairRef` has
  been added. This addresses the issues described in #1124.
tarcieri added a commit that referenced this issue Oct 24, 2022
This commit contains the first breaking changes to the `signature` crate
made since its initial 1.0 stabilization. Planning for these changes
occurred in #237.

The following changes have been made:

- The `Signature` trait has been renamed to `SignatureEncoding`. The
  `Signature` bound on `*Signer` and `*Verifier` traits has been
  removed, meaning there are no longer any mandatory trait bounds on the
  signature paramters at all.

- The `AsRef<[u8]>` bound formerly found on the `Signature` crate has
  been replaced with an associated `Repr` type, inspired by the
  `group::GroupEncoding` trait. This means signature types no longer
  need to retain a serialized form, and can parse the bag-of-bytes
  representation to something more convenient, which is useful for e.g.
  batch verification.

- The `std` feature is no longer enabled by default, which matches the
  other RustCrypto/traits crates.

- The `derive-preview` and `hazmat-preview` features have been
  stabilized.

- The former `Keypair` trait has been renamed to `KeypairRef`, and the
  signature generic parameter removed. A new `Keypair` trait has been
  added which returns an owned instance of the associated
  `VerifyingKey`, and a blanket impl of `Keypair` for `KeypairRef` has
  been added. This addresses the issues described in #1124.
tarcieri added a commit that referenced this issue Oct 29, 2022
This commit contains the first breaking changes to the `signature` crate
made since its initial 1.0 stabilization. Planning for these changes
occurred in #237.

The following changes have been made:

- The `Signature` trait has been renamed to `SignatureEncoding`. The
  `Signature` bound on `*Signer` and `*Verifier` traits has been
  removed, meaning there are no longer any mandatory trait bounds on the
  signature parameters at all.

- The `AsRef<[u8]>` bound formerly found on the `Signature` crate has
  been replaced with an associated `Repr` type, inspired by the
  `group::GroupEncoding` trait. This means signature types no longer
  need to retain a serialized form, and can parse the bag-of-bytes
  representation to something more convenient, which is useful for e.g.
  batch verification.

- The `std` feature is no longer enabled by default, which matches the
  other RustCrypto/traits crates.

- The `derive-preview` and `hazmat-preview` features have been
  stabilized.

- The former `Keypair` trait has been renamed to `KeypairRef`, and the
  signature generic parameter removed. A new `Keypair` trait has been
  added which returns an owned instance of the associated
  `VerifyingKey`, and a blanket impl of `Keypair` for `KeypairRef` has
  been added. This addresses the issues described in #1124.
@tarcieri
Copy link
Member Author

#1141 has been merged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
digest Hash function crate signature Digital signature crate
Projects
None yet
Development

No branches or pull requests

3 participants