darkbio_crypto/eddsa/
mod.rs1use crate::pem;
12use base64::Engine;
13use base64::engine::general_purpose::STANDARD as BASE64;
14use der::asn1::OctetString;
15use der::{Decode, Encode};
16use ed25519_dalek::ed25519::signature::rand_core::OsRng;
17use ed25519_dalek::pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePublicKey};
18use ed25519_dalek::{SignatureError, Signer, Verifier};
19use pkcs8::PrivateKeyInfo;
20use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
21use sha2::Digest;
22use spki::der::AnyRef;
23use spki::der::asn1::BitStringRef;
24use spki::{AlgorithmIdentifier, ObjectIdentifier, SubjectPublicKeyInfo};
25use std::error::Error;
26
27pub const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.101.112");
29
30pub const SECRET_KEY_SIZE: usize = 32;
32
33pub const PUBLIC_KEY_SIZE: usize = 32;
35
36pub const SIGNATURE_SIZE: usize = 64;
38
39pub const FINGERPRINT_SIZE: usize = 32;
41
42#[derive(Clone)]
44pub struct SecretKey {
45 inner: ed25519_dalek::SigningKey,
46}
47
48impl SecretKey {
49 pub fn generate() -> SecretKey {
51 let mut rng = OsRng;
52
53 let key = ed25519_dalek::SigningKey::generate(&mut rng);
54 Self { inner: key }
55 }
56
57 pub fn from_bytes(bin: &[u8; SECRET_KEY_SIZE]) -> Self {
59 let key = ed25519_dalek::SecretKey::from(*bin);
60 let sig = ed25519_dalek::SigningKey::from(&key);
61 Self { inner: sig }
62 }
63
64 pub fn from_der(der: &[u8]) -> Result<Self, Box<dyn Error>> {
66 let info = PrivateKeyInfo::try_from(der)?;
67
68 if info.encoded_len()?.try_into() != Ok(der.len()) {
70 return Err("trailing data in private key".into());
71 }
72 if info.public_key.is_some() {
73 return Err("embedded public key not supported".into());
74 }
75 let inner = ed25519_dalek::SigningKey::from_pkcs8_der(der)?;
76 Ok(Self { inner })
77 }
78
79 pub fn from_pem(pem_str: &str) -> Result<Self, Box<dyn Error>> {
81 let (kind, data) = pem::decode(pem_str.as_bytes())?;
82 if kind != "PRIVATE KEY" {
83 return Err(format!("invalid PEM tag {}", kind).into());
84 }
85 Self::from_der(&data)
86 }
87
88 pub fn to_bytes(&self) -> [u8; SECRET_KEY_SIZE] {
90 self.inner.to_bytes()
91 }
92
93 pub fn to_der(&self) -> Vec<u8> {
95 let seed = OctetString::new(self.inner.to_bytes()).unwrap();
97 let inner = seed.to_der().unwrap();
98
99 let alg = pkcs8::AlgorithmIdentifierRef {
100 oid: OID,
101 parameters: None::<AnyRef>,
102 };
103 let info = PrivateKeyInfo {
104 algorithm: alg,
105 private_key: &inner,
106 public_key: None,
107 };
108 info.to_der().unwrap()
109 }
110
111 pub fn to_pem(&self) -> String {
113 pem::encode("PRIVATE KEY", &self.to_der())
114 }
115
116 pub fn public_key(&self) -> PublicKey {
118 PublicKey {
119 inner: self.inner.verifying_key(),
120 }
121 }
122
123 pub fn fingerprint(&self) -> Fingerprint {
126 self.public_key().fingerprint()
127 }
128
129 pub fn sign(&self, message: &[u8]) -> Signature {
131 Signature(self.inner.sign(message).to_bytes())
132 }
133}
134
135#[derive(Debug, Clone)]
137pub struct PublicKey {
138 inner: ed25519_dalek::VerifyingKey,
139}
140
141impl PublicKey {
142 pub fn from_bytes(bin: &[u8; PUBLIC_KEY_SIZE]) -> Result<Self, Box<dyn Error>> {
144 let inner = ed25519_dalek::VerifyingKey::from_bytes(bin)?;
145 Ok(Self { inner })
146 }
147
148 pub fn from_der(der: &[u8]) -> Result<Self, Box<dyn Error>> {
150 let info: SubjectPublicKeyInfo<AlgorithmIdentifier<AnyRef>, BitStringRef> =
152 SubjectPublicKeyInfo::from_der(der)?;
153 if info.encoded_len()?.try_into() != Ok(der.len()) {
154 return Err("trailing data in public key".into());
155 }
156 let inner = ed25519_dalek::VerifyingKey::from_public_key_der(der)?;
157 Ok(Self { inner })
158 }
159
160 pub fn from_pem(pem_str: &str) -> Result<Self, Box<dyn Error>> {
162 let (kind, data) = pem::decode(pem_str.as_bytes())?;
163 if kind != "PUBLIC KEY" {
164 return Err(format!("invalid PEM tag {}", kind).into());
165 }
166 Self::from_der(&data)
167 }
168
169 pub fn to_bytes(&self) -> [u8; PUBLIC_KEY_SIZE] {
171 self.inner.to_bytes()
172 }
173
174 pub fn to_der(&self) -> Vec<u8> {
176 self.inner.to_public_key_der().unwrap().as_bytes().to_vec()
177 }
178
179 pub fn to_pem(&self) -> String {
181 pem::encode("PUBLIC KEY", &self.to_der())
182 }
183
184 pub fn fingerprint(&self) -> Fingerprint {
187 let mut hasher = sha2::Sha256::new();
188 hasher.update(self.to_bytes());
189 Fingerprint(hasher.finalize().into())
190 }
191
192 pub fn verify(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError> {
194 let sig = ed25519_dalek::Signature::from_bytes(&signature.to_bytes());
195 self.inner.verify(message, &sig)
196 }
197}
198
199impl Serialize for PublicKey {
200 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
201 serializer.serialize_str(&BASE64.encode(self.to_bytes()))
202 }
203}
204
205impl<'de> Deserialize<'de> for PublicKey {
206 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
207 let s = String::deserialize(deserializer)?;
208 let bytes = BASE64.decode(&s).map_err(de::Error::custom)?;
209 let arr: [u8; PUBLIC_KEY_SIZE] = bytes
210 .try_into()
211 .map_err(|_| de::Error::custom("invalid public key length"))?;
212 PublicKey::from_bytes(&arr).map_err(de::Error::custom)
213 }
214}
215
216#[cfg(feature = "cbor")]
217impl crate::cbor::Encode for PublicKey {
218 fn encode_cbor(&self) -> Vec<u8> {
219 self.to_bytes().encode_cbor()
220 }
221}
222
223#[cfg(feature = "cbor")]
224impl crate::cbor::Decode for PublicKey {
225 fn decode_cbor(data: &[u8]) -> Result<Self, crate::cbor::Error> {
226 let bytes = <[u8; PUBLIC_KEY_SIZE]>::decode_cbor(data)?;
227 Self::from_bytes(&bytes).map_err(|e| crate::cbor::Error::DecodeFailed(e.to_string()))
228 }
229
230 fn decode_cbor_notrail(
231 decoder: &mut crate::cbor::Decoder<'_>,
232 ) -> Result<Self, crate::cbor::Error> {
233 let bytes = decoder.decode_bytes_fixed::<PUBLIC_KEY_SIZE>()?;
234 Self::from_bytes(&bytes).map_err(|e| crate::cbor::Error::DecodeFailed(e.to_string()))
235 }
236}
237
238#[derive(Debug, Clone, Copy, PartialEq, Eq)]
240pub struct Signature([u8; SIGNATURE_SIZE]);
241
242impl Signature {
243 pub fn from_bytes(bytes: &[u8; SIGNATURE_SIZE]) -> Self {
245 Self(*bytes)
246 }
247
248 pub fn to_bytes(&self) -> [u8; SIGNATURE_SIZE] {
250 self.0
251 }
252}
253
254impl Serialize for Signature {
255 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
256 serializer.serialize_str(&BASE64.encode(self.to_bytes()))
257 }
258}
259
260impl<'de> Deserialize<'de> for Signature {
261 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
262 let s = String::deserialize(deserializer)?;
263 let bytes = BASE64.decode(&s).map_err(de::Error::custom)?;
264 let arr: [u8; SIGNATURE_SIZE] = bytes
265 .try_into()
266 .map_err(|_| de::Error::custom("invalid signature length"))?;
267 Ok(Signature::from_bytes(&arr))
268 }
269}
270
271#[cfg(feature = "cbor")]
272impl crate::cbor::Encode for Signature {
273 fn encode_cbor(&self) -> Vec<u8> {
274 self.to_bytes().encode_cbor()
275 }
276}
277
278#[cfg(feature = "cbor")]
279impl crate::cbor::Decode for Signature {
280 fn decode_cbor(data: &[u8]) -> Result<Self, crate::cbor::Error> {
281 let bytes = <[u8; SIGNATURE_SIZE]>::decode_cbor(data)?;
282 Ok(Self::from_bytes(&bytes))
283 }
284
285 fn decode_cbor_notrail(
286 decoder: &mut crate::cbor::Decoder<'_>,
287 ) -> Result<Self, crate::cbor::Error> {
288 let bytes = decoder.decode_bytes_fixed::<SIGNATURE_SIZE>()?;
289 Ok(Self::from_bytes(&bytes))
290 }
291}
292
293#[derive(Debug, Clone, Copy, PartialEq, Eq)]
295pub struct Fingerprint([u8; FINGERPRINT_SIZE]);
296
297impl Fingerprint {
298 pub fn from_bytes(bytes: &[u8; FINGERPRINT_SIZE]) -> Self {
300 Self(*bytes)
301 }
302
303 pub fn to_bytes(&self) -> [u8; FINGERPRINT_SIZE] {
305 self.0
306 }
307}
308
309impl Serialize for Fingerprint {
310 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
311 serializer.serialize_str(&BASE64.encode(self.to_bytes()))
312 }
313}
314
315impl<'de> Deserialize<'de> for Fingerprint {
316 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
317 let s = String::deserialize(deserializer)?;
318 let bytes = BASE64.decode(&s).map_err(de::Error::custom)?;
319 let arr: [u8; FINGERPRINT_SIZE] = bytes
320 .try_into()
321 .map_err(|_| de::Error::custom("invalid fingerprint length"))?;
322 Ok(Fingerprint::from_bytes(&arr))
323 }
324}
325
326#[cfg(feature = "cbor")]
327impl crate::cbor::Encode for Fingerprint {
328 fn encode_cbor(&self) -> Vec<u8> {
329 self.to_bytes().encode_cbor()
330 }
331}
332
333#[cfg(feature = "cbor")]
334impl crate::cbor::Decode for Fingerprint {
335 fn decode_cbor(data: &[u8]) -> Result<Self, crate::cbor::Error> {
336 let bytes = <[u8; FINGERPRINT_SIZE]>::decode_cbor(data)?;
337 Ok(Self::from_bytes(&bytes))
338 }
339
340 fn decode_cbor_notrail(
341 decoder: &mut crate::cbor::Decoder<'_>,
342 ) -> Result<Self, crate::cbor::Error> {
343 let bytes = decoder.decode_bytes_fixed::<FINGERPRINT_SIZE>()?;
344 Ok(Self::from_bytes(&bytes))
345 }
346}
347
348#[cfg(test)]
349mod tests {
350 use super::*;
351
352 #[test]
358 fn test_sign_verify() {
359 let secret = SecretKey::generate();
361 let public = secret.public_key();
362
363 struct TestCase<'a> {
365 message: &'a [u8],
366 }
367 let tests = [TestCase {
368 message: b"message to authenticate",
369 }];
370
371 for tt in &tests {
372 let signature = secret.sign(tt.message);
374
375 public
377 .verify(tt.message, &signature)
378 .unwrap_or_else(|e| panic!("failed to verify message: {}", e));
379 }
380 }
381}