use ed25519_dalek::{Signer as _, SigningKey};
use crate::crypto::{EventSignatureBytes, EventSigner, SignerId};
use crate::error::Result;
pub struct FileEd25519Signer {
signer_id: SignerId,
signing_key: SigningKey,
}
impl FileEd25519Signer {
pub(crate) fn from_seed(seed: [u8; 32]) -> Self {
let signing_key = SigningKey::from_bytes(&seed);
let signer_id = SignerId::from_ed25519_public_key(signing_key.verifying_key().to_bytes());
Self {
signer_id,
signing_key,
}
}
}
impl EventSigner for FileEd25519Signer {
fn signer_id(&self) -> &SignerId {
&self.signer_id
}
fn sign_event_message(&self, message: &[u8]) -> Result<EventSignatureBytes> {
let signature = self.signing_key.sign(message);
Ok(EventSignatureBytes::from_bytes(&signature.to_bytes()))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::crypto::{EventVerificationStatus, verify_ed25519_strict};
use crate::session::event::{EVENT_TO_BE_SIGNED_V1_PAYLOAD_TYPE, pre_authentication_encoding};
#[test]
fn file_signer_signs_dsse_pae_bytes_that_verify_valid() {
let signer = FileEd25519Signer::from_seed([9_u8; 32]);
let message = pre_authentication_encoding(
EVENT_TO_BE_SIGNED_V1_PAYLOAD_TYPE,
br#"{"schema":"shore.event","version":1}"#,
);
let sig = signer.sign_event_message(&message).unwrap();
assert!(sig.is_base64());
assert_eq!(
verify_ed25519_strict(signer.signer_id(), &message, sig.as_str()).unwrap(),
EventVerificationStatus::Valid
);
}
#[test]
fn file_signer_signer_id_is_the_derived_did_key() {
let signer = FileEd25519Signer::from_seed([9_u8; 32]);
let expected = crate::crypto::SignerId::from_ed25519_public_key(
ed25519_dalek::SigningKey::from_bytes(&[9_u8; 32])
.verifying_key()
.to_bytes(),
);
assert_eq!(signer.signer_id(), &expected);
}
#[test]
fn signing_the_same_message_twice_is_stable() {
let signer = FileEd25519Signer::from_seed([3_u8; 32]);
let message = b"DSSEv1 4 test 5 hello";
let a = signer.sign_event_message(message).unwrap();
let b = signer.sign_event_message(message).unwrap();
assert_eq!(a, b);
}
}