mundane/public/
ed25519.rs
1use 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;
15const ED25519_PUBLIC_KEY_OFFSET: usize = ED25519_PRIVATE_KEY_LEN - ED25519_PUBLIC_KEY_LEN;
18
19pub struct Ed25519PubKey {
21 key: [u8; ED25519_PUBLIC_KEY_LEN],
22}
23
24impl Ed25519PubKey {
25 #[must_use]
27 pub fn from_bytes(bytes: [u8; ED25519_PUBLIC_KEY_LEN]) -> Ed25519PubKey {
28 Ed25519PubKey { key: bytes }
29 }
30
31 #[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
45pub struct Ed25519PrivKey {
51 key: [u8; ED25519_PRIVATE_KEY_LEN],
52}
53
54impl_debug!(Ed25519PrivKey, "Ed25519PrivKey");
55
56impl Ed25519PrivKey {
57 #[must_use]
59 pub fn generate() -> Ed25519PrivKey {
60 Ed25519PrivKey { key: ed25519_keypair() }
61 }
62
63 #[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 #[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 #[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#[must_use]
110pub struct Ed25519Signature {
111 sig: [u8; ED25519_SIGNATURE_LEN],
112}
113
114impl_debug!(Ed25519Signature, "Ed25519Signature");
115
116impl Ed25519Signature {
117 #[must_use]
119 pub fn from_bytes(bytes: [u8; ED25519_SIGNATURE_LEN]) -> Ed25519Signature {
120 Ed25519Signature { sig: bytes }
121 }
122
123 #[must_use]
125 pub fn bytes(&self) -> &[u8; ED25519_SIGNATURE_LEN] {
126 &self.sig
127 }
128
129 #[must_use]
139 pub fn sign_ed25519(key: &Ed25519PrivKey, message: &[u8]) -> Ed25519Signature {
140 Ed25519Signature {
141 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 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 fn to_bytes(sig: &Ed25519Signature) -> &[u8] {
204 &sig.bytes()[..]
205 }
206 test_signature_smoke(&key, from_bytes, to_bytes);
207 }
208}