ed25519/
lib.rs

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