primitives/signing/
mod.rs1pub use ed25519_dalek::{Signature, SigningKey, VerifyingKey};
2use ed25519_dalek::{Signer as DalekSigner, Verifier as DalekVerifier};
3use itertools::chain;
4
5use crate::{errors::PrimitiveError, types::SessionId};
6
7pub type MessageId = (SessionId, u8, &'static [u8]);
9
10pub trait Signer: UCSigner<Signature> {}
13impl<SR: UCSigner<Signature>> Signer for SR {}
14
15pub trait Verifier: UCVerifier<Signature> + Sync + Send {}
16impl<VR: UCVerifier<Signature>> Verifier for VR {}
17
18pub trait UCSigner<S>: DalekSigner<S> + Sync + Send {
22 fn sign_with(&self, message: &[u8], id: &MessageId) -> Result<S, PrimitiveError> {
25 let round = id.1.to_le_bytes();
26 let message_with_id: Vec<u8> = chain!(message, &id.0, &round, id.2).copied().collect();
27 let signature = self
28 .try_sign(&message_with_id)
29 .map_err(|e| PrimitiveError::WrongSignature(e.to_string()))?;
30 Ok(signature)
31 }
32}
33
34pub trait UCVerifier<S>: DalekVerifier<S> + Sync + Send {
37 fn verify_with(
40 &self,
41 message: &[u8],
42 signature: &S,
43 &id: &MessageId,
44 ) -> Result<(), PrimitiveError> {
45 let round = id.1.to_le_bytes();
46 let message_with_id: Vec<u8> = chain!(message, &id.0, &round, id.2).copied().collect();
47 self.verify(&message_with_id, signature)
48 .map_err(|e| PrimitiveError::WrongSignature(e.to_string()))?;
49 Ok(())
50 }
51}
52
53impl<S, T: DalekSigner<S> + Sync + Send> UCSigner<S> for T {}
54impl<S, T: DalekVerifier<S> + Sync + Send> UCVerifier<S> for T {}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59 use crate::{
60 random::{self, Random},
61 types::SessionId,
62 };
63
64 #[test]
65 fn test_sign_protocol_message() {
66 let mut rng = random::test_rng();
67 let signing_key = SigningKey::generate(&mut rng);
68 let message = b"Hello, protocol!";
69 let protocol_id: &'static [u8] = &[2, 1];
70 let message_id = (SessionId::random(&mut rng), 1, protocol_id);
71
72 let signature = signing_key.sign_with(message, &message_id).unwrap();
73 assert!(signing_key
74 .verify_with(message, &signature, &message_id)
75 .is_ok());
76 }
77}