mundane/public/
ed25519.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! The Ed25519 signature algorithm.
6
7use boringssl::{ed25519_keypair, ed25519_keypair_from_seed, ed25519_sign, ed25519_verify};
8use public::{PrivateKey, PublicKey, Signature};
9use util::Sealed;
10use Error;
11
12const ED25519_PUBLIC_KEY_LEN: usize = ::boringssl::ED25519_PUBLIC_KEY_LEN as usize;
13const ED25519_PRIVATE_KEY_LEN: usize = ::boringssl::ED25519_PRIVATE_KEY_LEN as usize;
14const ED25519_SIGNATURE_LEN: usize = ::boringssl::ED25519_SIGNATURE_LEN as usize;
15// BoringSSL stores both a private and a public key in their private key
16// representation. The private key comes first, followed by the public key.
17const ED25519_PUBLIC_KEY_OFFSET: usize = ED25519_PRIVATE_KEY_LEN - ED25519_PUBLIC_KEY_LEN;
18
19/// An Ed25519 public key.
20pub struct Ed25519PubKey {
21    key: [u8; ED25519_PUBLIC_KEY_LEN],
22}
23
24impl Ed25519PubKey {
25    /// Constructs a new public key from bytes.
26    #[must_use]
27    pub fn from_bytes(bytes: [u8; ED25519_PUBLIC_KEY_LEN]) -> Ed25519PubKey {
28        Ed25519PubKey { key: bytes }
29    }
30
31    /// Gets the raw bytes of the public key.
32    #[must_use]
33    pub fn bytes(&self) -> &[u8; ED25519_PUBLIC_KEY_LEN] {
34        &self.key
35    }
36}
37
38impl_debug!(Ed25519PubKey, "Ed25519PubKey");
39
40impl Sealed for Ed25519PubKey {}
41impl PublicKey for Ed25519PubKey {
42    type Private = Ed25519PrivKey;
43}
44
45/// An Ed25519 private key.
46///
47/// An `Ed25519PrivKey` actually includes both the private key and the public
48/// key in order to make multiple key signing operations with the same key more
49/// efficient.
50pub struct Ed25519PrivKey {
51    key: [u8; ED25519_PRIVATE_KEY_LEN],
52}
53
54impl_debug!(Ed25519PrivKey, "Ed25519PrivKey");
55
56impl Ed25519PrivKey {
57    /// Generates a new private key.
58    #[must_use]
59    pub fn generate() -> Ed25519PrivKey {
60        Ed25519PrivKey { key: ed25519_keypair() }
61    }
62
63    /// Constructs a new private key from a key pair.
64    ///
65    /// Usually, an Ed25519 private key will be stored as a single 64-byte blob:
66    /// the 32-byte private key followed by the 32-byte public key. However, we
67    /// accept the two keys as separate arguments in case they are stored
68    /// separately.
69    #[must_use]
70    pub fn from_key_pair_bytes(private: [u8; 32], public: &Ed25519PubKey) -> Ed25519PrivKey {
71        let mut key = [0u8; ED25519_PRIVATE_KEY_LEN];
72        (&mut key[..32]).copy_from_slice(&private);
73        (&mut key[ED25519_PUBLIC_KEY_OFFSET..]).copy_from_slice(&public.key);
74        Ed25519PrivKey { key }
75    }
76
77    /// Constructs a new private key.
78    ///
79    /// Unlike [`from_key_pair_bytes`], `from_private_key_bytes` reconstructs
80    /// the key (which includes both the private key and the public key
81    /// internally) from only the private key.
82    ///
83    /// [`from_key_pair_bytes`]: ::public::ed25519::Ed25519PrivKey::from_key_pair_bytes
84    #[must_use]
85    pub fn from_private_key_bytes(private: [u8; 32]) -> Ed25519PrivKey {
86        let (_, key) = ed25519_keypair_from_seed(&private);
87        Ed25519PrivKey { key }
88    }
89
90    /// Gets the raw bytes of the private key.
91    #[must_use]
92    pub fn bytes(&self) -> &[u8; ED25519_PRIVATE_KEY_LEN] {
93        &self.key
94    }
95}
96
97impl Sealed for Ed25519PrivKey {}
98impl PrivateKey for Ed25519PrivKey {
99    type Public = Ed25519PubKey;
100
101    fn public(&self) -> Ed25519PubKey {
102        let mut public = [0u8; ED25519_PUBLIC_KEY_LEN];
103        (&mut public[..]).copy_from_slice(&self.key[ED25519_PUBLIC_KEY_OFFSET..]);
104        Ed25519PubKey { key: public }
105    }
106}
107
108/// An Ed25519 signature.
109#[must_use]
110pub struct Ed25519Signature {
111    sig: [u8; ED25519_SIGNATURE_LEN],
112}
113
114impl_debug!(Ed25519Signature, "Ed25519Signature");
115
116impl Ed25519Signature {
117    /// Constructs an `Ed25519Signature` signature from raw bytes.
118    #[must_use]
119    pub fn from_bytes(bytes: [u8; ED25519_SIGNATURE_LEN]) -> Ed25519Signature {
120        Ed25519Signature { sig: bytes }
121    }
122
123    /// Gets the raw bytes of the signature.
124    #[must_use]
125    pub fn bytes(&self) -> &[u8; ED25519_SIGNATURE_LEN] {
126        &self.sig
127    }
128
129    /// Sign a message.
130    ///
131    /// `Ed25519Signature` implements [`Signature`], but `Signature`'s [`sign`]
132    /// function conservatively returns a `Result`. Ed25519 signatures never
133    /// fail, so this function is provided to allow the user to compute an
134    /// Ed25519 signature without having to perform error checking.
135    ///
136    /// [`Signature`]: ::public::Signature
137    /// [`sign`]: ::public::Signature::sign
138    #[must_use]
139    pub fn sign_ed25519(key: &Ed25519PrivKey, message: &[u8]) -> Ed25519Signature {
140        Ed25519Signature {
141            // ED25519_sign can only return an error on OOM
142            sig: ed25519_sign(message, &key.key).unwrap(),
143        }
144    }
145}
146
147impl Sealed for Ed25519Signature {}
148impl Signature for Ed25519Signature {
149    type PrivateKey = Ed25519PrivKey;
150
151    /// Sign a message.
152    ///
153    /// Though the [`Signature`] trait requires that [`sign`] return a `Result`,
154    /// `Ed25519Signature`'s implementation is guaranteed to always return `Ok`.
155    /// Callers may prefer the [`sign_ed25519`] function, which returns an
156    /// `Ed25519Signature` rather than a `Result`.
157    ///
158    /// [`Signature`]: ::public::Signature
159    /// [`sign`]: ::public::Signature::sign
160    /// [`sign_ed25519`]: ::public::ed25519::Ed25519Signature::sign_ed25519
161    fn sign(key: &Ed25519PrivKey, message: &[u8]) -> Result<Ed25519Signature, Error> {
162        Ok(Ed25519Signature::sign_ed25519(key, message))
163    }
164
165    fn is_valid(&self, key: &Ed25519PubKey, message: &[u8]) -> bool {
166        ed25519_verify(message, &self.sig, &key.key)
167    }
168}
169
170#[cfg(test)]
171mod tests {
172    use super::*;
173    use public::testutil::test_signature_smoke;
174
175    #[test]
176    fn test_priv_key_constructors() {
177        let key = Ed25519PrivKey::generate();
178        let mut private = [0u8; 32];
179        (&mut private[..]).copy_from_slice(&key.key[..32]);
180        let key2 = Ed25519PrivKey::from_private_key_bytes(private);
181        assert_eq!(&key.key[..], &key2.key[..]);
182
183        let mut private = [0u8; 32];
184        let mut public = [0u8; 32];
185        let bytes = *key.bytes();
186        (&mut private[..]).copy_from_slice(&bytes[..32]);
187        (&mut public[..]).copy_from_slice(&bytes[32..]);
188        let key2 = Ed25519PrivKey::from_key_pair_bytes(private, &Ed25519PubKey::from_bytes(public));
189        assert_eq!(&key.key[..], &key2.key[..]);
190    }
191
192    #[test]
193    fn test_smoke() {
194        let key = Ed25519PrivKey::generate();
195        let from_bytes = |bytes: &[u8]| {
196            let mut sig = [0u8; ED25519_SIGNATURE_LEN];
197            let len = ::std::cmp::min(sig.len(), bytes.len());
198            (&mut sig[..len]).copy_from_slice(&bytes[..len]);
199            Ed25519Signature::from_bytes(sig)
200        };
201        // for some reason, defining this as a closure results in type inference
202        // issues that aren't worth debugging
203        fn to_bytes(sig: &Ed25519Signature) -> &[u8] {
204            &sig.bytes()[..]
205        }
206        test_signature_smoke(&key, from_bytes, to_bytes);
207    }
208}