logo
Expand description

RustCrypto: Ed25519

crate Docs Build Status Apache2/MIT licensed Rust Version Project Chat

Edwards Digital Signature Algorithm (EdDSA) over Curve25519 as specified in RFC 8032.

Documentation

About

This crate doesn’t contain an implementation of Ed25519, but instead contains an ed25519::Signature type which other crates can use in conjunction with the signature::Signer and signature::Verifier traits.

These traits allow crates which produce and consume Ed25519 signatures to be written abstractly in such a way that different signer/verifier providers can be plugged in, enabling support for using different Ed25519 implementations, including HSMs or Cloud KMS services.

Minimum Supported Rust Version

This crate requires Rust 1.57 at a minimum.

Previous 1.x releases of this crate supported an MSRV of 1.47. If you would like to use this crate with earlier releases of Rust, add the following version constraint in your project’s Cargo.toml to constrain it to the supported version range:

[dependencies]
ed25519 = ">=1, <1.4" # ed25519 1.4 requires MSRV 1.57

Note that is our policy that we may change the MSRV in the future, but it will be accompanied by a minor version bump.

SemVer Policy

  • All on-by-default features of this library are covered by SemVer
  • MSRV is considered exempt from SemVer as noted above
  • The pkcs8 module is exempted as it uses a pre-1.0 dependency, however, breaking changes to this module will be accompanied by a minor version bump.

License

All crates licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Using Ed25519 generically over algorithm implementations/providers

By using the ed25519 crate, you can write code which signs and verifies messages using the Ed25519 signature algorithm generically over any supported Ed25519 implementation (see the next section for available providers).

This allows consumers of your code to plug in whatever implementation they want to use without having to add all potential Ed25519 libraries you’d like to support as optional dependencies.

Example

use ed25519::signature::{Signer, Verifier};

pub struct HelloSigner<S>
where
    S: Signer<ed25519::Signature>
{
    pub signing_key: S
}

impl<S> HelloSigner<S>
where
    S: Signer<ed25519::Signature>
{
    pub fn sign(&self, person: &str) -> ed25519::Signature {
        // NOTE: use `try_sign` if you'd like to be able to handle
        // errors from external signing services/devices (e.g. HSM/KMS)
        // <https://docs.rs/signature/latest/signature/trait.Signer.html#tymethod.try_sign>
        self.signing_key.sign(format_message(person).as_bytes())
    }
}

pub struct HelloVerifier<V> {
    pub verify_key: V
}

impl<V> HelloVerifier<V>
where
    V: Verifier<ed25519::Signature>
{
    pub fn verify(
        &self,
        person: &str,
        signature: &ed25519::Signature
    ) -> Result<(), ed25519::Error> {
        self.verify_key.verify(format_message(person).as_bytes(), signature)
    }
}

fn format_message(person: &str) -> String {
    format!("Hello, {}!", person)
}

Using above example with ed25519-dalek

The ed25519-dalek crate natively supports the ed25519::Signature type defined in this crate along with the signature::Signer and signature::Verifier traits.

Below is an example of how a hypothetical consumer of the code above can instantiate and use the previously defined HelloSigner and HelloVerifier types with ed25519-dalek as the signing/verification provider:

use ed25519_dalek::{Signer, Verifier, Signature};
use rand_core::OsRng; // Requires the `std` feature of `rand_core`

/// `HelloSigner` defined above instantiated with `ed25519-dalek` as
/// the signing provider.
pub type DalekHelloSigner = HelloSigner<ed25519_dalek::Keypair>;

let signing_key = ed25519_dalek::Keypair::generate(&mut OsRng);
let signer = DalekHelloSigner { signing_key };
let person = "Joe"; // Message to sign
let signature = signer.sign(person);

/// `HelloVerifier` defined above instantiated with `ed25519-dalek`
/// as the signature verification provider.
pub type DalekHelloVerifier = HelloVerifier<ed25519_dalek::PublicKey>;

let verify_key: ed25519_dalek::PublicKey = signer.signing_key.public;
let verifier = DalekHelloVerifier { verify_key };
assert!(verifier.verify(person, &signature).is_ok());

Using above example with ring-compat

The ring-compat crate provides wrappers for ring which implement the signature::Signer and signature::Verifier traits for ed25519::Signature.

Below is an example of how a hypothetical consumer of the code above can instantiate and use the previously defined HelloSigner and HelloVerifier types with ring-compat as the signing/verification provider:

use ring_compat::signature::{
    ed25519::{Signature, SigningKey, VerifyingKey},
    Signer, Verifier
};
use rand_core::{OsRng, RngCore}; // Requires the `std` feature of `rand_core`

/// `HelloSigner` defined above instantiated with *ring* as
/// the signing provider.
pub type RingHelloSigner = HelloSigner<SigningKey>;

let mut ed25519_seed = [0u8; 32];
OsRng.fill_bytes(&mut ed25519_seed);

let signing_key = SigningKey::from_seed(&ed25519_seed).unwrap();
let verify_key = signing_key.verify_key();

let signer = RingHelloSigner { signing_key };
let person = "Joe"; // Message to sign
let signature = signer.sign(person);

/// `HelloVerifier` defined above instantiated with *ring*
/// as the signature verification provider.
pub type RingHelloVerifier = HelloVerifier<VerifyingKey>;

let verifier = RingHelloVerifier { verify_key };
assert!(verifier.verify(person, &signature).is_ok());

Available Ed25519 providers

The following libraries support the types/traits from the ed25519 crate:

Features

The following features are presently supported:

  • pkcs8: support for decoding/encoding PKCS#8-formatted private keys using the [KeypairBytes] type.

  • std (default): Enable std support in signature, which currently only affects whether signature::Error implements std::error::Error.

  • serde: Implement serde::Deserialize and serde::Serialize for Signature. Signatures are serialized as their bytes.

  • serde_bytes: Implement serde_bytes::Deserialize and serde_bytes::Serialize for Signature. This enables more compact representations for formats with an efficient byte array representation. As per the serde_bytes documentation, this can most easily be realised using the #[serde(with = "serde_bytes")] annotation, e.g.:

    #[derive(Deserialize, Serialize)]
    #[serde(transparent)]
    struct SignatureAsBytes(#[serde(with = "serde_bytes")] Signature);

Re-exports

pub use signature;

Structs

Signature errors.

Ed25519 signature.

Constants

Length of an Ed25519 signature in bytes.