use std::ops::Deref;
use edcert::certificate::Certificate;
use edcert::fingerprint::Fingerprint;
use edcert::signature::Signature;
use edcert::validator::Validatable;
use edcert::validator::Validator;
use edcert::validator::ValidationError;
use edcert::revoker::RevokeError;
use edcert::revoker::Revoker;
use edcert::revoker::Revokable;
#[derive(PartialEq, Debug)]
pub struct Letter<T: Fingerprint> {
content: T,
signature: Signature,
}
impl<T: Fingerprint> Letter<T> {
pub fn new(content: T, signature: Signature) -> Letter<T> {
Letter {
content: content,
signature: signature,
}
}
pub fn with_private_key(content: T, private_key: &[u8]) -> Letter<T> {
use edcert::ed25519;
let signature = Signature::new(ed25519::sign(&content.fingerprint(), private_key));
Letter::new(content, signature)
}
pub fn with_certificate(content: T, cert: &Certificate) -> Result<Letter<T>, ()> {
let res = cert.sign(&content.fingerprint());
match res {
Some(hash) => {
let signature = Signature::with_parent(Box::new(cert.clone()), hash);
Ok(Letter::new(content, signature))
},
None => {
Err(())
}
}
}
pub fn get(&self) -> &T {
&self.content
}
}
impl<T: Fingerprint> Validatable for Letter<T> {
fn self_validate<V: Validator>(&self, cv: &V) -> Result<(), ValidationError> {
let sig = &self.signature;
let bytes = self.content.fingerprint();
if sig.is_signed_by_master() {
if cv.is_signature_valid(&bytes, sig.hash()) {
Ok(())
} else {
Err(ValidationError::SignatureInvalid)
}
} else {
let parent = sig.parent().unwrap();
if cv.is_valid(parent).is_ok() {
if parent.verify(&bytes, sig.hash()) {
Ok(())
} else {
Err(ValidationError::SignatureInvalid)
}
} else {
Err(ValidationError::ParentInvalid)
}
}
}
}
impl<T: Fingerprint> Fingerprint for Letter<T> {
fn fingerprint(&self) -> Vec<u8> {
self.content.fingerprint()
}
}
impl<T: Fingerprint> Deref for Letter<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.get()
}
}
impl<T: Fingerprint> Revokable for Letter<T> {
fn self_check_revoked<R: Revoker>(&self, _: &R) -> Result<(), RevokeError> {
Ok(())
}
}
#[test]
fn test_simple() {
use edcert::ed25519;
use edcert::root_validator::RootValidator;
use edcert::revoker::NoRevoker;
let (mpk, msk) = ed25519::generate_keypair();
let test_str = "hello world";
let mut letter = Letter::with_private_key(test_str, &msk);
let cv = RootValidator::new(&mpk, NoRevoker);
assert_eq!(true, cv.is_valid(&letter).is_ok());
letter.content = "world hello";
assert_eq!(false, cv.is_valid(&letter).is_ok());
}
#[test]
fn test_certificate() {
use edcert::ed25519;
use edcert::meta::Meta;
use edcert::root_validator::RootValidator;
use edcert::revoker::NoRevoker;
use chrono::Timelike;
use chrono::UTC;
use chrono::Duration;
let (mpk, msk) = ed25519::generate_keypair();
let meta = Meta::new_empty();
let expires = UTC::now()
.checked_add(Duration::days(90))
.expect("Failed to add a day to expiration date.")
.with_nanosecond(0)
.unwrap();
let mut cert = Certificate::generate_random(meta, expires);
cert.sign_with_master(&msk);
let test_str = "hello world";
let cv = RootValidator::new(&mpk, NoRevoker);
let mut letter = Letter::with_certificate(test_str, &cert).expect("This fails only if the Certificate has no private key.");
assert_eq!(true, cv.is_valid(&letter).is_ok());
letter.content = "world hello";
assert_eq!(false, cv.is_valid(&letter).is_ok());
}
#[test]
fn test_deref() {
use edcert::ed25519;
let (_, msk) = ed25519::generate_keypair();
let test_str = "hello world";
let letter = Letter::with_private_key(test_str, &msk);
let deref_str: &str = *letter;
assert_eq!(deref_str, test_str);
}