1use crate::{
38 cbb_to_buffer, scoped, with_output_array, Buffer, FfiMutSlice, FfiSlice, InvalidSignatureError,
39};
40
41pub const PUBLIC_KEY_LEN: usize = bssl_sys::ED25519_PUBLIC_KEY_LEN as usize;
43
44pub const SEED_LEN: usize =
47 (bssl_sys::ED25519_PRIVATE_KEY_LEN - bssl_sys::ED25519_PUBLIC_KEY_LEN) as usize;
48
49pub const SIGNATURE_LEN: usize = bssl_sys::ED25519_SIGNATURE_LEN as usize;
51
52const KEYPAIR_LEN: usize = bssl_sys::ED25519_PRIVATE_KEY_LEN as usize;
55
56#[derive(Clone)]
58pub struct PrivateKey([u8; KEYPAIR_LEN]);
59
60pub struct PublicKey([u8; PUBLIC_KEY_LEN]);
62
63pub type Signature = [u8; SIGNATURE_LEN];
65
66impl PrivateKey {
67 pub fn generate() -> Self {
69 let mut public_key = [0u8; PUBLIC_KEY_LEN];
70 let mut private_key = [0u8; KEYPAIR_LEN];
71
72 unsafe {
75 bssl_sys::ED25519_keypair(public_key.as_mut_ffi_ptr(), private_key.as_mut_ffi_ptr())
76 }
77
78 PrivateKey(private_key)
79 }
80
81 pub fn to_seed(&self) -> [u8; SEED_LEN] {
83 #[allow(clippy::expect_used)]
86 self.0[..SEED_LEN]
87 .try_into()
88 .expect("A slice of length SEED_LEN will always fit into an array of length SEED_LEN")
89 }
90
91 pub fn from_seed(seed: &[u8; SEED_LEN]) -> Self {
94 let mut public_key = [0u8; PUBLIC_KEY_LEN];
95 let mut private_key = [0u8; KEYPAIR_LEN];
96
97 unsafe {
100 bssl_sys::ED25519_keypair_from_seed(
101 public_key.as_mut_ffi_ptr(),
102 private_key.as_mut_ffi_ptr(),
103 seed.as_ffi_ptr(),
104 )
105 }
106 PrivateKey(private_key)
107 }
108
109 pub fn sign(&self, msg: &[u8]) -> Signature {
111 let mut sig_bytes = [0u8; SIGNATURE_LEN];
112
113 let result = unsafe {
117 bssl_sys::ED25519_sign(
118 sig_bytes.as_mut_ffi_ptr(),
119 msg.as_ffi_ptr(),
120 msg.len(),
121 self.0.as_ffi_ptr(),
122 )
123 };
124 assert_eq!(result, 1, "allocation failure in bssl_sys::ED25519_sign");
125
126 sig_bytes
127 }
128
129 pub fn to_public(&self) -> PublicKey {
131 let keypair_bytes = &self.0;
132
133 #[allow(clippy::expect_used)]
136 PublicKey(
137 keypair_bytes[PUBLIC_KEY_LEN..]
138 .try_into()
139 .expect("The slice is always the correct size for a public key"),
140 )
141 }
142
143 pub(crate) unsafe fn from_evp_pkey(mut pkey: scoped::EvpPkey) -> Self {
145 let mut seed = [0; SEED_LEN];
146 let len = &mut { SEED_LEN };
147 let ret = unsafe {
149 bssl_sys::EVP_PKEY_get_raw_private_key(
150 pkey.as_ffi_ptr(),
151 seed.as_mut_ptr(),
152 len as *mut _,
153 )
154 };
155 assert_eq!(ret, 1);
157 assert_eq!(*len, SEED_LEN);
158 Self::from_seed(&seed)
159 }
160}
161
162impl PublicKey {
163 pub fn from_bytes(bytes: &[u8; PUBLIC_KEY_LEN]) -> Self {
165 PublicKey(*bytes)
166 }
167
168 pub fn as_bytes(&self) -> &[u8; PUBLIC_KEY_LEN] {
170 &self.0
171 }
172
173 pub fn from_der_subject_public_key_info(spki: &[u8]) -> Option<Self> {
175 let alg = unsafe { bssl_sys::EVP_pkey_ed25519() };
177 let mut pkey =
178 scoped::EvpPkey::from_der_subject_public_key_info(spki, core::slice::from_ref(&alg))?;
179 let raw_pkey: [u8; PUBLIC_KEY_LEN] = unsafe {
180 with_output_array(|out, mut out_len| {
181 assert_eq!(
185 1,
186 bssl_sys::EVP_PKEY_get_raw_public_key(pkey.as_ffi_ptr(), out, &mut out_len)
187 );
188 assert_eq!(out_len, PUBLIC_KEY_LEN);
189 })
190 };
191 Some(PublicKey(raw_pkey))
192 }
193
194 pub fn to_der_subject_public_key_info(&self) -> Buffer {
196 let mut pkey = scoped::EvpPkey::from_ptr(unsafe {
198 bssl_sys::EVP_PKEY_from_raw_public_key(
199 bssl_sys::EVP_pkey_ed25519(),
200 self.0.as_ffi_ptr(),
201 PUBLIC_KEY_LEN,
202 )
203 });
204 assert!(!pkey.as_ffi_ptr().is_null());
206
207 cbb_to_buffer(PUBLIC_KEY_LEN + 32, |cbb| unsafe {
208 assert_eq!(1, bssl_sys::EVP_marshal_public_key(cbb, pkey.as_ffi_ptr()));
211 })
212 }
213
214 pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), InvalidSignatureError> {
216 let ret = unsafe {
217 bssl_sys::ED25519_verify(
219 msg.as_ffi_ptr(),
220 msg.len(),
221 signature.as_ffi_ptr(),
222 self.0.as_ffi_ptr(),
223 )
224 };
225 if ret == 1 {
226 Ok(())
227 } else {
228 Err(InvalidSignatureError)
229 }
230 }
231}
232
233#[cfg(test)]
234mod test {
235 use super::*;
236 use crate::test_helpers;
237
238 #[test]
239 fn gen_roundtrip() {
240 let private_key = PrivateKey::generate();
241 assert_ne!([0u8; 64], private_key.0);
242 let seed = private_key.to_seed();
243 let new_private_key = PrivateKey::from_seed(&seed);
244 assert_eq!(private_key.0, new_private_key.0);
245 }
246
247 #[test]
248 fn der_subject_public_key_info() {
249 let priv_key = PrivateKey::generate();
250 let msg = [0u8; 0];
251 let sig = priv_key.sign(&msg);
252
253 let pub_key = priv_key.to_public();
254 assert!(pub_key.verify(&msg, &sig).is_ok());
255
256 let pub_key_der = pub_key.to_der_subject_public_key_info();
257 let pub_key_from_der =
258 PublicKey::from_der_subject_public_key_info(pub_key_der.as_ref()).unwrap();
259 assert_eq!(pub_key.as_bytes(), pub_key_from_der.as_bytes());
260 assert!(pub_key_from_der.verify(&msg, &sig).is_ok());
261
262 assert!(PublicKey::from_der_subject_public_key_info(
263 &pub_key_from_der.as_bytes()[0..PUBLIC_KEY_LEN / 2]
264 )
265 .is_none());
266
267 assert!(PublicKey::from_der_subject_public_key_info(b"").is_none());
268 }
269
270 #[test]
271 fn der_subject_public_key_info_wrong_type() {
272 let spki = test_helpers::decode_hex_into_vec("302a300506032b656e032100e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c");
274 assert!(PublicKey::from_der_subject_public_key_info(&spki).is_none());
276 }
277
278 #[test]
279 fn empty_msg() {
280 let pk = test_helpers::decode_hex(
282 "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a",
283 );
284 let seed = test_helpers::decode_hex(
285 "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
286 );
287 let msg = [0u8; 0];
288 let sig_expected = test_helpers::decode_hex("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b");
289 let kp = PrivateKey::from_seed(&seed);
290 let sig = kp.sign(&msg);
291 assert_eq!(sig_expected, sig);
292
293 let pub_key = PublicKey::from_bytes(&pk);
294 assert_eq!(pub_key.as_bytes(), kp.to_public().as_bytes());
295 assert!(pub_key.verify(&msg, &sig).is_ok());
296 }
297
298 #[test]
299 fn ed25519_sign_and_verify() {
300 let pk = test_helpers::decode_hex(
302 "cf3af898467a5b7a52d33d53bc037e2642a8da996903fc252217e9c033e2f291",
303 );
304 let sk = test_helpers::decode_hex(
305 "9acad959d216212d789a119252ebfe0c96512a23c73bd9f3b202292d6916a738",
306 );
307 let msg: [u8; 14] = test_helpers::decode_hex("55c7fa434f5ed8cdec2b7aeac173");
308 let sig_expected = test_helpers::decode_hex("6ee3fe81e23c60eb2312b2006b3b25e6838e02106623f844c44edb8dafd66ab0671087fd195df5b8f58a1d6e52af42908053d55c7321010092748795ef94cf06");
309 let kp = PrivateKey::from_seed(&sk);
310
311 let sig = kp.sign(&msg);
312 assert_eq!(sig_expected, sig);
313
314 let pub_key = PublicKey::from_bytes(&pk);
315 assert_eq!(pub_key.as_bytes(), kp.to_public().as_bytes());
316 assert!(pub_key.verify(&msg, &sig).is_ok());
317 }
318}