Skip to content

Commit

Permalink
signature v2.0.0-pre (#1141)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
tarcieri authored Oct 29, 2022
1 parent f8c2ff2 commit 36aa416
Show file tree
Hide file tree
Showing 18 changed files with 195 additions and 240 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/signature.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ jobs:
override: true
profile: minimal
- run: cargo build --target ${{ matrix.target }} --release --no-default-features
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features derive-preview
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features derive
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features digest-preview
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features hazmat-preview
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features rand-preview
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features derive,digest-preview,rand-preview

minimal-versions:
uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master
Expand Down Expand Up @@ -83,4 +83,4 @@ jobs:
override: true
profile: minimal
- run: cargo test --release
working-directory: signature/derive
working-directory: signature/derive
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions crypto/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "crypto"
version = "0.4.0" # Also update html_root_url in lib.rs when bumping this
version = "0.5.0-pre" # Also update html_root_url in lib.rs when bumping this
description = """
Resources for building cryptosystems in Rust using the RustCrypto project's ecosystem.
"""
Expand All @@ -23,7 +23,7 @@ cipher = { version = "0.4", optional = true }
digest = { version = "0.10", optional = true, features = ["mac"] }
elliptic-curve = { version = "0.12", optional = true, path = "../elliptic-curve" }
password-hash = { version = "0.4", optional = true, path = "../password-hash" }
signature = { version = "1.5", optional = true, default-features = false, path = "../signature" }
signature = { version = "=2.0.0-pre", optional = true, default-features = false, path = "../signature" }
universal-hash = { version = "0.5", optional = true, path = "../universal-hash" }

[features]
Expand Down
10 changes: 4 additions & 6 deletions signature/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "signature"
description = "Traits for cryptographic signature algorithms (e.g. ECDSA, Ed25519)"
version = "1.6.4"
version = "2.0.0-pre"
authors = ["RustCrypto Developers"]
license = "Apache-2.0 OR MIT"
documentation = "https://docs.rs/signature"
Expand All @@ -15,21 +15,19 @@ categories = ["cryptography", "no-std"]
[dependencies]
digest = { version = "0.10.3", optional = true, default-features = false }
rand_core = { version = "0.6", optional = true, default-features = false }
signature_derive = { version = "=1.0.0-pre.7", optional = true, path = "derive" }
derive = { package = "signature_derive", version = "=1.0.0-pre.7", optional = true, path = "derive" }

[dev-dependencies]
hex-literal = "0.3"
sha2 = { version = "0.10", default-features = false }

[features]
default = ["std"]
std = []
alloc = []
std = ["alloc"]

# Preview features are unstable and exempt from semver.
# See https://docs.rs/signature/latest/signature/#unstable-features for more information.
derive-preview = ["digest-preview", "signature_derive"]
digest-preview = ["digest"]
hazmat-preview = []
rand-preview = ["rand_core"]

[package.metadata.docs.rs]
Expand Down
25 changes: 11 additions & 14 deletions signature/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# RustCrypto: Digital Signature Algorithms
# [RustCrypto]: Digital Signature Algorithms

[![crate][crate-image]][crate-link]
[![Docs][docs-image]][docs-link]
Expand All @@ -8,14 +8,10 @@
[![Project Chat][chat-image]][chat-link]

This crate contains traits which provide generic, object-safe APIs for
generating and verifying [digital signatures][1].
generating and verifying [digital signatures].

Used by the [`ecdsa`][2] and [`ed25519`][3] crates, with forthcoming support
in the [`rsa`][4] crate.

See also the [Signatory][5] crate for trait wrappers for using these traits
with many popular Rust cryptography crates, including `ed25519-dalek`, *ring*,
`secp256k1-rs`, and `sodiumoxide`.
Used by the [`dsa`], [`ecdsa`], [`ed25519`], and [`rsa`] crates maintained by
the [RustCrypto] organization, as well as [`ed25519-dalek`].

[Documentation][docs-link]

Expand Down Expand Up @@ -63,10 +59,11 @@ dual licensed as above, without any additional terms or conditions.
[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg
[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260048-signatures

[//]: # (general links)
[//]: # (links)

[1]: https://en.wikipedia.org/wiki/Digital_signature
[2]: https://github.com/RustCrypto/signatures/tree/master/ecdsa
[3]: https://github.com/RustCrypto/signatures/tree/master/ed25519
[4]: https://github.com/RustCrypto/RSA
[5]: https://docs.rs/signatory
[digital signatures]: https://en.wikipedia.org/wiki/Digital_signature
[`dsa`]: https://github.com/RustCrypto/signatures/tree/master/dsa
[`ecdsa`]: https://github.com/RustCrypto/signatures/tree/master/ecdsa
[`ed25519`]: https://github.com/RustCrypto/signatures/tree/master/ed25519
[`ed25519-dalek`]: https://github.com/dalek-cryptography/ed25519-dalek
[`rsa`]: https://github.com/RustCrypto/RSA
2 changes: 1 addition & 1 deletion signature/async/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ rust-version = "1.56"

[dependencies]
async-trait = "0.1.9"
signature = { version = "1.6", path = ".." }
signature = { version = "=2.0.0-pre", path = ".." }

[features]
digest = ["signature/digest-preview"]
Expand Down
37 changes: 5 additions & 32 deletions signature/async/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#![forbid(unsafe_code)]
#![warn(missing_docs, rust_2018_idioms, unused_qualifications)]

pub use signature::{self, Error, Signature};
pub use signature::{self, Error};

#[cfg(feature = "digest")]
pub use signature::digest::{self, Digest};
Expand All @@ -22,7 +22,7 @@ use async_trait::async_trait;
pub trait AsyncSigner<S>
where
Self: Send + Sync,
S: Signature + Send + 'static,
S: Send + 'static,
{
/// Attempt to sign the given message, returning a digital signature on
/// success, or an error if something went wrong.
Expand All @@ -35,7 +35,7 @@ where
#[async_trait]
impl<S, T> AsyncSigner<S> for T
where
S: Signature + Send + 'static,
S: Send + 'static,
T: signature::Signer<S> + Send + Sync,
{
async fn sign_async(&self, msg: &[u8]) -> Result<S, Error> {
Expand All @@ -53,7 +53,7 @@ pub trait AsyncDigestSigner<D, S>
where
Self: Send + Sync,
D: Digest + Send + 'static,
S: Signature + 'static,
S: 'static,
{
/// Attempt to sign the given prehashed message [`Digest`], returning a
/// digital signature on success, or an error if something went wrong.
Expand All @@ -65,37 +65,10 @@ where
impl<D, S, T> AsyncDigestSigner<D, S> for T
where
D: Digest + Send + 'static,
S: Signature + Send + 'static,
S: Send + 'static,
T: signature::DigestSigner<D, S> + Send + Sync,
{
async fn sign_digest_async(&self, digest: D) -> Result<S, Error> {
self.try_sign_digest(digest)
}
}

/// Keypair with async signer component and an associated verifying key.
///
/// This represents a type which holds both an async signing key and a verifying key.
#[deprecated(since = "0.2.1", note = "use signature::Keypair instead")]
pub trait AsyncKeypair<S>: AsRef<Self::VerifyingKey>
where
S: Signature + Send + 'static,
{
/// Verifying key type for this keypair.
type VerifyingKey;

/// Get the verifying key which can verify signatures produced by the
/// signing key portion of this keypair.
fn verifying_key(&self) -> &Self::VerifyingKey {
self.as_ref()
}
}

#[allow(deprecated)]
impl<S, T> AsyncKeypair<S> for T
where
S: Signature + Send + 'static,
T: signature::Keypair<S> + Send + Sync,
{
type VerifyingKey = <T as signature::Keypair<S>>::VerifyingKey;
}
27 changes: 15 additions & 12 deletions signature/derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ fn emit_digest_signer_impl(input: DeriveInput) -> TokenStream2 {

let mut params = DeriveParams::new(input);
params.add_bound(&d_ident, parse_quote!(::signature::digest::Digest));
params.add_bound(&s_ident, parse_quote!(::signature::Signature));
params.add_param(&s_ident);
params.add_bound(
&Ident::new("Self", Span::call_site()),
parse_quote!(::signature::hazmat::PrehashSigner<#s_ident>),
Expand Down Expand Up @@ -167,7 +167,7 @@ fn emit_digest_verifier_impl(input: DeriveInput) -> TokenStream2 {

let mut params = DeriveParams::new(input);
params.add_bound(&d_ident, parse_quote!(::signature::digest::Digest));
params.add_bound(&s_ident, parse_quote!(::signature::Signature));
params.add_param(&s_ident);
params.add_bound(
&Ident::new("Self", Span::call_site()),
parse_quote!(::signature::hazmat::PrehashVerifier<#s_ident>),
Expand Down Expand Up @@ -235,14 +235,7 @@ impl DeriveParams {
/// Add a generic parameter with the given bound.
fn add_bound(&mut self, name: &Ident, bound: TraitBound) {
if name != "Self" {
self.impl_generics.push(TypeParam {
attrs: vec![],
ident: name.clone(),
colon_token: None,
bounds: Default::default(),
eq_token: None,
default: None,
});
self.add_param(name);
}

let type_path = parse_quote!(#name);
Expand All @@ -261,6 +254,18 @@ impl DeriveParams {
.predicates
.push(WherePredicate::Type(predicate_type))
}

/// Add a generic parameter without a bound.
fn add_param(&mut self, name: &Ident) {
self.impl_generics.push(TypeParam {
attrs: vec![],
ident: name.clone(),
colon_token: None,
bounds: Default::default(),
eq_token: None,
default: None,
});
}
}

#[cfg(test)]
Expand Down Expand Up @@ -345,7 +350,6 @@ mod tests {
impl<C: EllipticCurve, __D, __S> ::signature::DigestSigner<__D, __S> for MySigner<C>
where
__D: ::signature::digest::Digest,
__S: ::signature::Signature,
Self: ::signature::hazmat::PrehashSigner<__S>
{
fn try_sign_digest(&self, digest: __D) -> ::signature::Result<__S> {
Expand Down Expand Up @@ -374,7 +378,6 @@ mod tests {
impl<C: EllipticCurve, __D, __S> ::signature::DigestVerifier<__D, __S> for MyVerifier<C>
where
__D: ::signature::digest::Digest,
__S: ::signature::Signature,
Self: ::signature::hazmat::PrehashVerifier<__S>
{
fn verify_digest(&self, digest: __D, signature: &__S) -> ::signature::Result<()> {
Expand Down
38 changes: 38 additions & 0 deletions signature/src/encoding.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//! Encoding support.
use crate::{Error, Result};

#[cfg(feature = "alloc")]
use alloc::{boxed::Box, vec::Vec};

/// Support for decoding/encoding signatures as bytes.
pub trait SignatureEncoding:
Clone + Sized + for<'a> TryFrom<&'a [u8], Error = Error> + Into<Self::Repr>
{
/// Byte representation of a signature.
type Repr: 'static + AsRef<[u8]> + AsMut<[u8]> + Clone + Default + Send + Sync;

/// Decode signature from its byte representation.
fn from_bytes(bytes: &Self::Repr) -> Result<Self> {
Self::try_from(bytes.as_ref())
}

/// Encode signature as its byte representation.
fn to_bytes(&self) -> Self::Repr {
self.clone().into()
}

/// Encode signature as a byte vector.
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
fn to_vec(&self) -> Vec<u8> {
self.to_bytes().as_ref().to_vec()
}

/// Encode the signature as a boxed byte slice.
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
fn to_boxed_slice(&self) -> Box<[u8]> {
self.to_vec().into_boxed_slice()
}
}
6 changes: 1 addition & 5 deletions signature/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,8 @@ pub type Result<T> = core::result::Result<T, Error>;
///
/// [BB'06]: https://en.wikipedia.org/wiki/Daniel_Bleichenbacher
#[derive(Default)]
#[non_exhaustive]
pub struct Error {
/// Prevent from being instantiated as `Error {}` when the `std` feature
/// is disabled
_private: (),

/// Source of the error (if applicable).
#[cfg(feature = "std")]
source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
Expand All @@ -50,7 +47,6 @@ impl Error {
source: impl Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
) -> Self {
Self {
_private: (),
source: Some(source.into()),
}
}
Expand Down
8 changes: 4 additions & 4 deletions signature/src/hazmat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
//! feature is semi-unstable and not subject to regular 1.x SemVer guarantees.
//! However, any breaking changes will be accompanied with a minor version bump.
use crate::{Error, Signature};
use crate::Error;

#[cfg(feature = "rand-preview")]
use crate::rand_core::{CryptoRng, RngCore};

/// Sign the provided message prehash, returning a digital signature.
pub trait PrehashSigner<S: Signature> {
pub trait PrehashSigner<S> {
/// Attempt to sign the given message digest, returning a digital signature
/// on success, or an error if something went wrong.
///
Expand All @@ -35,7 +35,7 @@ pub trait PrehashSigner<S: Signature> {
/// Sign the provided message prehash using the provided external randomness source, returning a digital signature.
#[cfg(feature = "rand-preview")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand-preview")))]
pub trait RandomizedPrehashSigner<S: Signature> {
pub trait RandomizedPrehashSigner<S> {
/// Attempt to sign the given message digest, returning a digital signature
/// on success, or an error if something went wrong.
///
Expand All @@ -56,7 +56,7 @@ pub trait RandomizedPrehashSigner<S: Signature> {
}

/// Verify the provided message prehash using `Self` (e.g. a public key)
pub trait PrehashVerifier<S: Signature> {
pub trait PrehashVerifier<S> {
/// Use `Self` to verify that the provided signature for a given message
/// `prehash` is authentic.
///
Expand Down
Loading

0 comments on commit 36aa416

Please sign in to comment.