use ed25519::signature::Signer;
use litl::{Litl, impl_debug_as_litl};
use rand07::rngs::OsRng;
use serde_derive::{Serialize, Deserialize};
use serde::{Serialize};
use std::{hash::Hash, ops::Deref, fmt::Debug};
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename = "Conundrum/Signature:Ed25519Dalek")]
pub struct RawSignature(
#[serde(with = "serde_bytes")]
ed25519::Signature
);
impl_debug_as_litl!(RawSignature);
#[allow(clippy::derive_hash_xor_eq)]
impl Hash for RawSignature {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.to_bytes().hash(state)
}
}
impl Ord for RawSignature {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.0.as_ref().cmp(other.0.as_ref())
}
}
impl PartialOrd for RawSignature {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[derive(PartialEq, Eq, Serialize, Deserialize, Hash, Clone, Ord, PartialOrd)]
pub struct Signed<T, S> {
pub verified: T,
pub signature: RawSignature,
pub purpose: S,
}
impl <T: Serialize, S: Serialize> Debug for Signed<T, S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Litl::from_se(self).fmt(f)
}
}
impl<T, S> Deref for Signed<T, S> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.verified
}
}
pub type SignatureError = ed25519_dalek::SignatureError;
impl<T: Clone + Serialize, S> Signed<T, S> {
pub fn ensure_signed_by(&self, id: &SignPublicKey<S>) -> Result<(), SignatureError> {
id.key
.0
.verify_strict(&Litl::write_from(self.verified.clone()), &self.signature.0)
}
}
#[derive(Copy, PartialEq, Eq, Clone, Serialize, Deserialize)]
#[serde(rename = "Conundrum/SignPubKey:Ed25519Dalek")]
struct RawSignPublicKey(ed25519_dalek::PublicKey);
#[allow(clippy::derive_hash_xor_eq)]
impl Hash for RawSignPublicKey {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.as_bytes().hash(state);
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct SignPublicKey<S> {
key: RawSignPublicKey,
purpose: S,
}
impl<S: Serialize> Debug for SignPublicKey<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Litl::from_se(self).fmt(f)
}
}
#[derive(Serialize, Deserialize)]
#[serde(rename = "Conundrum/SignKeyPair:Ed25519Dalek")]
pub struct RawSignKeyPair(ed25519_dalek::Keypair);
impl RawSignKeyPair {
pub fn new_random() -> Self {
RawSignKeyPair(ed25519_dalek::Keypair::generate(&mut OsRng {}))
}
}
impl Deref for RawSignKeyPair {
type Target = ed25519_dalek::Keypair;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Serialize, Deserialize)]
pub struct SignKeyPair<S> {
keypair: RawSignKeyPair,
purpose: S,
}
impl <S> Deref for SignKeyPair<S> {
type Target = RawSignKeyPair;
fn deref(&self) -> &Self::Target {
&self.keypair
}
}
impl<S: Clone + Default> SignKeyPair<S> {
pub fn new_random() -> Self {
SignKeyPair {
keypair: RawSignKeyPair::new_random(),
purpose: S::default(),
}
}
pub fn sign<T: Clone + Serialize>(&self, data: T) -> Signed<T, S> {
let signature = RawSignature(self.keypair.sign(&Litl::write_from(data.clone())));
Signed {
verified: data,
signature,
purpose: self.purpose.clone(),
}
}
pub fn public(&self) -> SignPublicKey<S> {
SignPublicKey {
key: RawSignPublicKey(self.keypair.public),
purpose: self.purpose.clone(),
}
}
}
#[cfg(test)]
mod test {
use litl::Litl;
use serde_derive::{Serialize, Deserialize};
use crate::{purpose, signing::SignKeyPair};
#[derive(Clone, Serialize, Deserialize)]
struct TestData {
bla: [u8; 4],
}
purpose!(TestPurpose);
#[test]
fn signing_and_verifying_works() {
let data = TestData { bla: [1, 2, 3, 4] };
let keypair = SignKeyPair::<TestPurpose>::new_random();
let signed = keypair.sign(data);
println!("{:?}", Litl::from_se(&signed));
assert!(signed.ensure_signed_by(&keypair.public()).is_ok());
}
}