Skip to main content

ed25519/
lib.rs

1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![doc = include_str!("../README.md")]
4#![doc(html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")]
5#![allow(non_snake_case)]
6#![forbid(unsafe_code)]
7
8//! # Using Ed25519 generically over algorithm implementations/providers
9//!
10//! By using the `ed25519` crate, you can write code which signs and verifies
11//! messages using the Ed25519 signature algorithm generically over any
12//! supported Ed25519 implementation (see the next section for available
13//! providers).
14//!
15//! This allows consumers of your code to plug in whatever implementation they
16//! want to use without having to add all potential Ed25519 libraries you'd
17//! like to support as optional dependencies.
18//!
19//! ## Example
20//!
21//! ```
22//! use ed25519::signature::{Signer, Verifier};
23//!
24//! pub struct HelloSigner<S>
25//! where
26//!     S: Signer<ed25519::Signature>
27//! {
28//!     pub signing_key: S
29//! }
30//!
31//! impl<S> HelloSigner<S>
32//! where
33//!     S: Signer<ed25519::Signature>
34//! {
35//!     pub fn sign(&self, person: &str) -> ed25519::Signature {
36//!         // NOTE: use `try_sign` if you'd like to be able to handle
37//!         // errors from external signing services/devices (e.g. HSM/KMS)
38//!         // <https://docs.rs/signature/latest/signature/trait.Signer.html#tymethod.try_sign>
39//!         self.signing_key.sign(format_message(person).as_bytes())
40//!     }
41//! }
42//!
43//! pub struct HelloVerifier<V> {
44//!     pub verifying_key: V
45//! }
46//!
47//! impl<V> HelloVerifier<V>
48//! where
49//!     V: Verifier<ed25519::Signature>
50//! {
51//!     pub fn verify(
52//!         &self,
53//!         person: &str,
54//!         signature: &ed25519::Signature
55//!     ) -> Result<(), ed25519::Error> {
56//!         self.verifying_key.verify(format_message(person).as_bytes(), signature)
57//!     }
58//! }
59//!
60//! fn format_message(person: &str) -> String {
61//!     format!("Hello, {}!", person)
62//! }
63//! ```
64//!
65//! ## Using above example with `ed25519-dalek`
66//!
67//! The [`ed25519-dalek`] crate natively supports the [`ed25519::Signature`][`Signature`]
68//! type defined in this crate along with the [`signature::Signer`] and
69//! [`signature::Verifier`] traits.
70//!
71//! Below is an example of how a hypothetical consumer of the code above can
72//! instantiate and use the previously defined `HelloSigner` and `HelloVerifier`
73//! types with [`ed25519-dalek`] as the signing/verification provider:
74//!
75//! *NOTE: requires [`ed25519-dalek`] v2 or newer for compatibility with
76//! `ed25519` v2.2+*.
77//!
78//! ```ignore
79//! use ed25519_dalek::{Signer, Verifier, Signature};
80//! #
81//! # pub struct HelloSigner<S>
82//! # where
83//! #     S: Signer<Signature>
84//! # {
85//! #     pub signing_key: S
86//! # }
87//! #
88//! # impl<S> HelloSigner<S>
89//! # where
90//! #     S: Signer<Signature>
91//! # {
92//! #     pub fn sign(&self, person: &str) -> Signature {
93//! #         // NOTE: use `try_sign` if you'd like to be able to handle
94//! #         // errors from external signing services/devices (e.g. HSM/KMS)
95//! #         // <https://docs.rs/signature/latest/signature/trait.Signer.html#tymethod.try_sign>
96//! #         self.signing_key.sign(format_message(person).as_bytes())
97//! #     }
98//! # }
99//! #
100//! # pub struct HelloVerifier<V> {
101//! #     pub verifying_key: V
102//! # }
103//! #
104//! # impl<V> HelloVerifier<V>
105//! # where
106//! #     V: Verifier<Signature>
107//! # {
108//! #     pub fn verify(
109//! #         &self,
110//! #         person: &str,
111//! #         signature: &Signature
112//! #     ) -> Result<(), ed25519::Error> {
113//! #         self.verifying_key.verify(format_message(person).as_bytes(), signature)
114//! #     }
115//! # }
116//! #
117//! # fn format_message(person: &str) -> String {
118//! #     format!("Hello, {}!", person)
119//! # }
120//! use rand_core::OsRng; // Requires the `std` feature of `rand_core`
121//!
122//! /// `HelloSigner` defined above instantiated with `ed25519-dalek` as
123//! /// the signing provider.
124//! pub type DalekHelloSigner = HelloSigner<ed25519_dalek::SigningKey>;
125//!
126//! let signing_key = ed25519_dalek::SigningKey::generate(&mut OsRng);
127//! let signer = DalekHelloSigner { signing_key };
128//! let person = "Joe"; // Message to sign
129//! let signature = signer.sign(person);
130//!
131//! /// `HelloVerifier` defined above instantiated with `ed25519-dalek`
132//! /// as the signature verification provider.
133//! pub type DalekHelloVerifier = HelloVerifier<ed25519_dalek::VerifyingKey>;
134//!
135//! let verifying_key: ed25519_dalek::VerifyingKey = signer.signing_key.verifying_key();
136//! let verifier = DalekHelloVerifier { verifying_key };
137//! assert!(verifier.verify(person, &signature).is_ok());
138//! ```
139//!
140//! ## Using above example with `ring-compat`
141//!
142//! The [`ring-compat`] crate provides wrappers for [*ring*] which implement
143//! the [`signature::Signer`] and [`signature::Verifier`] traits for
144//! [`ed25519::Signature`][`Signature`].
145//!
146//! Below is an example of how a hypothetical consumer of the code above can
147//! instantiate and use the previously defined `HelloSigner` and `HelloVerifier`
148//! types with [`ring-compat`] as the signing/verification provider:
149//!
150//! ```ignore
151//! use ring_compat::signature::{
152//!     ed25519::{Signature, SigningKey, VerifyingKey},
153//!     Signer, Verifier
154//! };
155//! #
156//! # pub struct HelloSigner<S>
157//! # where
158//! #     S: Signer<Signature>
159//! # {
160//! #     pub signing_key: S
161//! # }
162//! #
163//! # impl<S> HelloSigner<S>
164//! # where
165//! #     S: Signer<Signature>
166//! # {
167//! #     pub fn sign(&self, person: &str) -> Signature {
168//! #         // NOTE: use `try_sign` if you'd like to be able to handle
169//! #         // errors from external signing services/devices (e.g. HSM/KMS)
170//! #         // <https://docs.rs/signature/latest/signature/trait.Signer.html#tymethod.try_sign>
171//! #         self.signing_key.sign(format_message(person).as_bytes())
172//! #     }
173//! # }
174//! #
175//! # pub struct HelloVerifier<V> {
176//! #     pub verifying_key: V
177//! # }
178//! #
179//! # impl<V> HelloVerifier<V>
180//! # where
181//! #     V: Verifier<Signature>
182//! # {
183//! #     pub fn verify(
184//! #         &self,
185//! #         person: &str,
186//! #         signature: &Signature
187//! #     ) -> Result<(), ed25519::Error> {
188//! #         self.verifying_key.verify(format_message(person).as_bytes(), signature)
189//! #     }
190//! # }
191//! #
192//! # fn format_message(person: &str) -> String {
193//! #     format!("Hello, {}!", person)
194//! # }
195//! use rand_core::{OsRng, Rng}; // Requires the `std` feature of `rand_core`
196//!
197//! /// `HelloSigner` defined above instantiated with *ring* as
198//! /// the signing provider.
199//! pub type RingHelloSigner = HelloSigner<SigningKey>;
200//!
201//! let mut ed25519_seed = [0u8; 32];
202//! OsRng.fill_bytes(&mut ed25519_seed);
203//!
204//! let signing_key = SigningKey::from_bytes(&ed25519_seed);
205//! let verifying_key = signing_key.verifying_key();
206//!
207//! let signer = RingHelloSigner { signing_key };
208//! let person = "Joe"; // Message to sign
209//! let signature = signer.sign(person);
210//!
211//! /// `HelloVerifier` defined above instantiated with *ring*
212//! /// as the signature verification provider.
213//! pub type RingHelloVerifier = HelloVerifier<VerifyingKey>;
214//!
215//! let verifier = RingHelloVerifier { verifying_key };
216//! assert!(verifier.verify(person, &signature).is_ok());
217//! ```
218//!
219//! # Available Ed25519 providers
220//!
221//! The following libraries support the types/traits from the `ed25519` crate:
222//!
223//! - [`ed25519-dalek`] - mature pure Rust implementation of Ed25519
224//! - [`ring-compat`] - compatibility wrapper for [*ring*]
225//! - [`yubihsm`] - host-side client library for `YubiHSM2` devices from Yubico
226//!
227//! [`ed25519-dalek`]: https://docs.rs/ed25519-dalek
228//! [`ring-compat`]: https://docs.rs/ring-compat
229//! [*ring*]: https://github.com/briansmith/ring
230//! [`yubihsm`]: https://github.com/iqlusioninc/yubihsm.rs/blob/develop/README.md
231//!
232//! # Features
233//!
234//! The following features are presently supported:
235//!
236//! - `pkcs8`: support for decoding/encoding PKCS#8-formatted private keys using the
237//!   [`KeypairBytes`] type.
238//! - `std` *(default)*: Enable `std` support in [`signature`], which currently only affects whether
239//!   [`signature::Error`] implements `std::error::Error`.
240//! - `serde`: Implement `serde::Deserialize` and `serde::Serialize` for [`Signature`]. Signatures
241//!   are serialized as their bytes.
242//! - `serde_bytes`: Implement `serde_bytes::Deserialize` and `serde_bytes::Serialize` for
243//!   [`Signature`]. This enables more compact representations for formats with an efficient byte
244//!   array representation. As per the `serde_bytes` documentation, this can most easily be realised
245//!   using the `#[serde(with = "serde_bytes")]` annotation, e.g.:
246//!
247//!   ```ignore
248//!   # use ed25519::Signature;
249//!   # use serde::{Deserialize, Serialize};
250//!   #[derive(Deserialize, Serialize)]
251//!   #[serde(transparent)]
252//!   struct SignatureAsBytes(#[serde(with = "serde_bytes")] Signature);
253//!   ```
254
255#[cfg(feature = "alloc")]
256extern crate alloc;
257
258mod hex;
259
260#[cfg(feature = "pkcs8")]
261pub mod pkcs8;
262
263pub use signature::{self, Error, SignatureEncoding};
264
265#[cfg(feature = "pkcs8")]
266pub use crate::pkcs8::{
267    KeypairBytes, PublicKeyBytes,
268    spki::{
269        AlgorithmIdentifierRef, AssociatedAlgorithmIdentifier,
270        der::{AnyRef, oid::ObjectIdentifier},
271    },
272};
273
274use core::fmt;
275
276#[cfg(feature = "alloc")]
277use alloc::vec::Vec;
278#[cfg(feature = "serde")]
279use serdect::serde::{Deserialize, Serialize, de, ser};
280
281#[cfg(all(feature = "alloc", feature = "pkcs8"))]
282use pkcs8::spki::{
283    SignatureBitStringEncoding,
284    der::{self, asn1::BitString},
285};
286
287#[cfg(feature = "zeroize")]
288use zeroize::Zeroize;
289
290#[cfg(feature = "zerocopy")]
291use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
292
293/// Size of a single component of an Ed25519 signature.
294const COMPONENT_SIZE: usize = 32;
295
296/// Byte representation of an `R` or `s` component of an Ed25519 signature.
297pub type ComponentBytes = [u8; COMPONENT_SIZE];
298
299/// Ed25519 signature serialized as a byte array.
300pub type SignatureBytes = [u8; Signature::BYTE_SIZE];
301
302/// Ed25519 signature.
303///
304/// This type represents a container for the byte serialization of an Ed25519
305/// signature, and does not necessarily represent well-formed field or curve
306/// elements.
307///
308/// Signature verification libraries are expected to reject invalid field
309/// elements at the time a signature is verified.
310#[derive(Copy, Clone, Eq, Hash, PartialEq)]
311#[cfg_attr(
312    feature = "zerocopy",
313    derive(FromBytes, IntoBytes, Immutable, KnownLayout, Unaligned)
314)]
315#[repr(C)]
316pub struct Signature {
317    R: ComponentBytes,
318    s: ComponentBytes,
319}
320
321impl Signature {
322    /// Size of an encoded Ed25519 signature in bytes.
323    pub const BYTE_SIZE: usize = COMPONENT_SIZE * 2;
324
325    /// Parse an Ed25519 signature from a byte slice.
326    #[must_use]
327    pub fn from_bytes(bytes: &SignatureBytes) -> Self {
328        let mut R = ComponentBytes::default();
329        let mut s = ComponentBytes::default();
330
331        let components = bytes.split_at(COMPONENT_SIZE);
332        R.copy_from_slice(components.0);
333        s.copy_from_slice(components.1);
334
335        Self { R, s }
336    }
337
338    /// Parse an Ed25519 signature from its `R` and `s` components.
339    #[must_use]
340    pub fn from_components(R: ComponentBytes, s: ComponentBytes) -> Self {
341        Self { R, s }
342    }
343
344    /// Parse an Ed25519 signature from a byte slice.
345    ///
346    /// # Errors
347    /// - Returns [`Error`] if the input byte slice is not 64-bytes.
348    pub fn from_slice(bytes: &[u8]) -> signature::Result<Self> {
349        SignatureBytes::try_from(bytes)
350            .map(Into::into)
351            .map_err(|_| Error::new())
352    }
353
354    /// Bytes for the `R` component of a signature.
355    #[must_use]
356    pub fn r_bytes(&self) -> &ComponentBytes {
357        &self.R
358    }
359
360    /// Bytes for the `s` component of a signature.
361    #[must_use]
362    pub fn s_bytes(&self) -> &ComponentBytes {
363        &self.s
364    }
365
366    /// Return the inner byte array.
367    #[must_use]
368    pub fn to_bytes(&self) -> SignatureBytes {
369        let mut ret = [0u8; Self::BYTE_SIZE];
370        let (R, s) = ret.split_at_mut(COMPONENT_SIZE);
371        R.copy_from_slice(&self.R);
372        s.copy_from_slice(&self.s);
373        ret
374    }
375
376    /// Convert this signature into a byte vector.
377    #[cfg(feature = "alloc")]
378    #[must_use]
379    pub fn to_vec(&self) -> Vec<u8> {
380        self.to_bytes().to_vec()
381    }
382}
383
384impl SignatureEncoding for Signature {
385    type Repr = SignatureBytes;
386
387    fn to_bytes(&self) -> SignatureBytes {
388        self.to_bytes()
389    }
390}
391
392#[cfg(all(feature = "alloc", feature = "pkcs8"))]
393impl SignatureBitStringEncoding for Signature {
394    fn to_bitstring(&self) -> der::Result<BitString> {
395        BitString::new(0, self.to_vec())
396    }
397}
398
399#[cfg(feature = "pkcs8")]
400impl AssociatedAlgorithmIdentifier for Signature {
401    type Params = AnyRef<'static>;
402
403    const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs8::ALGORITHM_ID;
404}
405
406impl From<Signature> for SignatureBytes {
407    fn from(sig: Signature) -> SignatureBytes {
408        sig.to_bytes()
409    }
410}
411
412impl From<&Signature> for SignatureBytes {
413    fn from(sig: &Signature) -> SignatureBytes {
414        sig.to_bytes()
415    }
416}
417
418impl From<SignatureBytes> for Signature {
419    fn from(bytes: SignatureBytes) -> Self {
420        Signature::from_bytes(&bytes)
421    }
422}
423
424impl From<&SignatureBytes> for Signature {
425    fn from(bytes: &SignatureBytes) -> Self {
426        Signature::from_bytes(bytes)
427    }
428}
429
430impl TryFrom<&[u8]> for Signature {
431    type Error = Error;
432
433    fn try_from(bytes: &[u8]) -> signature::Result<Self> {
434        Self::from_slice(bytes)
435    }
436}
437
438impl fmt::Debug for Signature {
439    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
440        f.debug_struct("ed25519::Signature")
441            .field("R", &hex::ComponentFormatter(self.r_bytes()))
442            .field("s", &hex::ComponentFormatter(self.s_bytes()))
443            .finish()
444    }
445}
446
447impl fmt::Display for Signature {
448    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
449        write!(f, "{self:X}")
450    }
451}
452
453#[cfg(feature = "serde")]
454impl Serialize for Signature {
455    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
456    where
457        S: ser::Serializer,
458    {
459        serdect::array::serialize_hex_upper_or_bin(&self.to_bytes(), serializer)
460    }
461}
462
463#[cfg(feature = "serde")]
464impl<'de> Deserialize<'de> for Signature {
465    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
466    where
467        D: de::Deserializer<'de>,
468    {
469        let mut bytes = [0u8; Signature::BYTE_SIZE];
470        serdect::array::deserialize_hex_or_bin(&mut bytes, deserializer)?;
471        Ok(bytes.into())
472    }
473}
474
475#[cfg(feature = "zeroize")]
476impl Zeroize for Signature {
477    fn zeroize(&mut self) {
478        self.R.zeroize();
479        self.s.zeroize();
480    }
481}