Skip to main content

ed448/
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#![warn(
8    clippy::unwrap_used,
9    missing_docs,
10    rust_2018_idioms,
11    unused_lifetimes,
12    unused_qualifications,
13    unreachable_pub
14)]
15
16//! # Using Ed448 generically over algorithm implementations/providers
17//!
18//! By using the `ed448` crate, you can write code which signs and verifies
19//! messages using the Ed448 signature algorithm generically over any
20//! supported Ed448 implementation (see the next section for available
21//! providers).
22//!
23//! This allows consumers of your code to plug in whatever implementation they
24//! want to use without having to add all potential Ed448 libraries you'd
25//! like to support as optional dependencies.
26//!
27//! ## Example
28//!
29//! ```
30//! use ed448::signature::{Signer, Verifier};
31//!
32//! pub struct HelloSigner<S>
33//! where
34//!     S: Signer<ed448::Signature>
35//! {
36//!     pub signing_key: S
37//! }
38//!
39//! impl<S> HelloSigner<S>
40//! where
41//!     S: Signer<ed448::Signature>
42//! {
43//!     pub fn sign(&self, person: &str) -> ed448::Signature {
44//!         // NOTE: use `try_sign` if you'd like to be able to handle
45//!         // errors from external signing services/devices (e.g. HSM/KMS)
46//!         // <https://docs.rs/signature/latest/signature/trait.Signer.html#tymethod.try_sign>
47//!         self.signing_key.sign(format_message(person).as_bytes())
48//!     }
49//! }
50//!
51//! pub struct HelloVerifier<V> {
52//!     pub verifying_key: V
53//! }
54//!
55//! impl<V> HelloVerifier<V>
56//! where
57//!     V: Verifier<ed448::Signature>
58//! {
59//!     pub fn verify(
60//!         &self,
61//!         person: &str,
62//!         signature: &ed448::Signature
63//!     ) -> Result<(), ed448::Error> {
64//!         self.verifying_key.verify(format_message(person).as_bytes(), signature)
65//!     }
66//! }
67//!
68//! fn format_message(person: &str) -> String {
69//!     format!("Hello, {}!", person)
70//! }
71//! ```
72
73mod hex;
74
75#[cfg(feature = "pkcs8")]
76pub mod pkcs8;
77
78#[cfg(feature = "serde")]
79mod serde;
80
81pub use signature::{self, Error, SignatureEncoding};
82
83use core::fmt;
84
85#[cfg(feature = "pkcs8")]
86pub use crate::pkcs8::{
87    KeypairBytes, PublicKeyBytes,
88    spki::{
89        AlgorithmIdentifierRef, AssociatedAlgorithmIdentifier,
90        der::{AnyRef, oid::ObjectIdentifier},
91    },
92};
93
94#[cfg(all(feature = "alloc", feature = "pkcs8"))]
95use pkcs8::spki::{
96    SignatureBitStringEncoding,
97    der::{self, asn1::BitString},
98};
99
100/// Size of a single component of an Ed448 signature.
101pub const COMPONENT_SIZE: usize = 57;
102
103/// Size of an `R` or `s` component of an Ed448 signature when serialized
104/// as bytes.
105pub type ComponentBytes = [u8; COMPONENT_SIZE];
106
107/// Ed448 signature serialized as a byte array.
108pub type SignatureBytes = [u8; Signature::BYTE_SIZE];
109
110/// Ed448 signature.
111///
112/// This type represents a container for the byte serialization of an Ed448
113/// signature, and does not necessarily represent well-formed field or curve
114/// elements.
115///
116/// Signature verification libraries are expected to reject invalid field
117/// elements at the time a signature is verified.
118#[derive(Copy, Clone, Eq, Hash, PartialEq)]
119#[repr(C)]
120pub struct Signature {
121    R: ComponentBytes,
122    s: ComponentBytes,
123}
124
125impl Signature {
126    /// Size of an encoded Ed448 signature in bytes (114-bytes).
127    pub const BYTE_SIZE: usize = COMPONENT_SIZE * 2;
128
129    /// Parse an Ed448 signature from a byte slice.
130    #[must_use]
131    pub fn from_bytes(bytes: &SignatureBytes) -> Self {
132        let mut R = [0; COMPONENT_SIZE];
133        let mut s = [0; COMPONENT_SIZE];
134
135        let components = bytes.split_at(COMPONENT_SIZE);
136        R.copy_from_slice(components.0);
137        s.copy_from_slice(components.1);
138
139        Self { R, s }
140    }
141
142    /// Parse an Ed448 signature from a byte slice.
143    ///
144    /// # Errors
145    /// - Returns [`Error`] if the input byte slice is not 114-bytes.
146    pub fn from_slice(bytes: &[u8]) -> signature::Result<Self> {
147        SignatureBytes::try_from(bytes)
148            .map(Into::into)
149            .map_err(|_| Error::new())
150    }
151
152    /// Bytes for the `R` component of a signature.
153    #[must_use]
154    pub fn r_bytes(&self) -> &ComponentBytes {
155        &self.R
156    }
157
158    /// Bytes for the `s` component of a signature.
159    #[must_use]
160    pub fn s_bytes(&self) -> &ComponentBytes {
161        &self.s
162    }
163
164    /// Return the inner byte array.
165    #[must_use]
166    pub fn to_bytes(&self) -> SignatureBytes {
167        let mut ret = [0u8; Self::BYTE_SIZE];
168        let (R, s) = ret.split_at_mut(COMPONENT_SIZE);
169        R.copy_from_slice(&self.R);
170        s.copy_from_slice(&self.s);
171        ret
172    }
173
174    /// Create a [`Signature`] from the serialized `r` and `s` component values
175    /// which comprise the signature.
176    pub fn from_components(r: impl Into<ComponentBytes>, s: impl Into<ComponentBytes>) -> Self {
177        Self {
178            R: r.into(),
179            s: s.into(),
180        }
181    }
182}
183
184impl SignatureEncoding for Signature {
185    type Repr = SignatureBytes;
186
187    fn to_bytes(&self) -> SignatureBytes {
188        self.to_bytes()
189    }
190}
191
192impl From<Signature> for SignatureBytes {
193    fn from(sig: Signature) -> SignatureBytes {
194        sig.to_bytes()
195    }
196}
197
198impl From<&Signature> for SignatureBytes {
199    fn from(sig: &Signature) -> SignatureBytes {
200        sig.to_bytes()
201    }
202}
203
204impl From<SignatureBytes> for Signature {
205    fn from(bytes: SignatureBytes) -> Self {
206        Signature::from_bytes(&bytes)
207    }
208}
209
210impl From<&SignatureBytes> for Signature {
211    fn from(bytes: &SignatureBytes) -> Self {
212        Signature::from_bytes(bytes)
213    }
214}
215
216impl TryFrom<&[u8]> for Signature {
217    type Error = Error;
218
219    fn try_from(bytes: &[u8]) -> signature::Result<Self> {
220        Self::from_slice(bytes)
221    }
222}
223
224impl fmt::Debug for Signature {
225    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226        f.debug_struct("ed448::Signature")
227            .field("R", self.r_bytes())
228            .field("s", self.s_bytes())
229            .finish()
230    }
231}
232
233impl fmt::Display for Signature {
234    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
235        write!(f, "{self:X}")
236    }
237}
238
239#[cfg(all(feature = "alloc", feature = "pkcs8"))]
240impl SignatureBitStringEncoding for Signature {
241    fn to_bitstring(&self) -> der::Result<BitString> {
242        BitString::new(0, self.to_bytes())
243    }
244}
245
246#[cfg(feature = "pkcs8")]
247impl AssociatedAlgorithmIdentifier for Signature {
248    type Params = AnyRef<'static>;
249
250    const ALGORITHM_IDENTIFIER: AlgorithmIdentifierRef<'static> = pkcs8::ALGORITHM_ID;
251}