pub use ed25519_dalek::{Signature, SigningKey, VerifyingKey};
use ed25519_dalek::{Signer as DalekSigner, Verifier as DalekVerifier};
use itertools::chain;
use crate::{errors::PrimitiveError, types::SessionId};
pub type MessageId = (SessionId, u16, &'static [u8]);
pub trait Signer: UCSigner<Signature> {}
impl<SR: UCSigner<Signature>> Signer for SR {}
pub trait Verifier: UCVerifier<Signature> + Sync + Send {}
impl<VR: UCVerifier<Signature>> Verifier for VR {}
pub trait UCSigner<S>: DalekSigner<S> + Sync + Send {
fn sign_with(&self, message: &[u8], id: &MessageId) -> Result<S, PrimitiveError> {
let round = id.1.to_le_bytes();
let message_with_id: Vec<u8> = chain!(message, &id.0, &round, id.2).copied().collect();
let signature = self
.try_sign(&message_with_id)
.map_err(|e| PrimitiveError::WrongSignature(e.to_string()))?;
Ok(signature)
}
}
pub trait UCVerifier<S>: DalekVerifier<S> + Sync + Send {
fn verify_with(
&self,
message: &[u8],
signature: &S,
&id: &MessageId,
) -> Result<(), PrimitiveError> {
let round = id.1.to_le_bytes();
let message_with_id: Vec<u8> = chain!(message, &id.0, &round, id.2).copied().collect();
self.verify(&message_with_id, signature)
.map_err(|e| PrimitiveError::WrongSignature(e.to_string()))?;
Ok(())
}
}
impl<S, T: DalekSigner<S> + Sync + Send> UCSigner<S> for T {}
impl<S, T: DalekVerifier<S> + Sync + Send> UCVerifier<S> for T {}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
random::{self, Random},
types::SessionId,
};
#[test]
fn test_sign_protocol_message() {
let mut rng = random::test_rng();
let signing_key = SigningKey::generate(&mut rng);
let message = b"Hello, protocol!";
let protocol_id: &'static [u8] = &[2, 1];
let message_id = (SessionId::random(&mut rng), 1, protocol_id);
let signature = signing_key.sign_with(message, &message_id).unwrap();
assert!(signing_key
.verify_with(message, &signature, &message_id)
.is_ok());
}
}