ruc 10.0.0

Rust Util Collections
Documentation
use super::origin;
use crate::{ende::base64, *};
use ed25519_dalek::{Signer, Verifier};
use std::fmt;

pub use ed25519_dalek::SigningKey as RawSignKey;
pub use ed25519_dalek::VerifyingKey as RawVerifyKey;

fn decode_bytes<const N: usize>(b64: &str) -> Result<[u8; N]> {
    let bytes = base64::decode(b64).c(d!())?;
    bytes
        .try_into()
        .map_err(|_| eg!("invalid length, expected {}", N))
}

#[derive(serde::Deserialize, serde::Serialize)]
pub struct SignKey(String);

#[derive(serde::Deserialize, serde::Serialize)]
pub struct VerifyKey(String);

#[derive(serde::Deserialize, serde::Serialize)]
pub struct Sig(String);

// <signing key + verify key> in base64 format
pub fn create_keypair() -> (SignKey, VerifyKey) {
    let (sk, vk) = origin::create_keypair();
    (sk.into(), vk.into())
}

impl SignKey {
    pub fn sign(&self, msg: &[u8]) -> Result<Sig> {
        let sk_bytes: [u8; 32] = decode_bytes(&self.0).c(d!())?;
        let sk = RawSignKey::from_bytes(&sk_bytes);
        let sig = base64::encode(sk.sign(msg).to_bytes());
        Ok(Sig(sig))
    }

    pub fn into_string(self) -> String {
        self.0
    }
}

impl fmt::Display for SignKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl TryFrom<String> for SignKey {
    type Error = Box<dyn RucError>;
    fn try_from(s: String) -> Result<Self> {
        decode_bytes::<32>(&s).c(d!())?;
        Ok(Self(s))
    }
}

impl TryFrom<&str> for SignKey {
    type Error = Box<dyn RucError>;
    fn try_from(s: &str) -> Result<Self> {
        decode_bytes::<32>(s).c(d!())?;
        Ok(Self(s.to_owned()))
    }
}

impl TryFrom<&SignKey> for RawSignKey {
    type Error = Box<dyn RucError>;
    fn try_from(k: &SignKey) -> Result<Self> {
        let bytes: [u8; 32] = decode_bytes(&k.0).c(d!())?;
        Ok(RawSignKey::from_bytes(&bytes))
    }
}

impl TryFrom<SignKey> for RawSignKey {
    type Error = Box<dyn RucError>;
    fn try_from(k: SignKey) -> Result<Self> {
        Self::try_from(&k)
    }
}

impl From<&RawSignKey> for SignKey {
    fn from(sk: &RawSignKey) -> SignKey {
        SignKey(base64::encode(sk.to_bytes()))
    }
}

impl From<RawSignKey> for SignKey {
    fn from(sk: RawSignKey) -> SignKey {
        SignKey::from(&sk)
    }
}

impl VerifyKey {
    pub fn verify(&self, sig: &Sig, msg: &[u8]) -> Result<()> {
        let vk_bytes: [u8; 32] = decode_bytes(&self.0).c(d!())?;
        let vk = RawVerifyKey::from_bytes(&vk_bytes)
            .map_err(|e| eg!(e))
            .c(d!())?;
        verify_by_raw_vk(&vk, sig, msg).c(d!())
    }

    pub fn into_string(self) -> String {
        self.0
    }
}

impl fmt::Display for VerifyKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl TryFrom<String> for VerifyKey {
    type Error = Box<dyn RucError>;
    fn try_from(s: String) -> Result<Self> {
        let bytes: [u8; 32] = decode_bytes(&s).c(d!())?;
        RawVerifyKey::from_bytes(&bytes)
            .map_err(|e| eg!(e))
            .c(d!())?;
        Ok(Self(s))
    }
}

impl TryFrom<&str> for VerifyKey {
    type Error = Box<dyn RucError>;
    fn try_from(s: &str) -> Result<Self> {
        let bytes: [u8; 32] = decode_bytes(s).c(d!())?;
        RawVerifyKey::from_bytes(&bytes)
            .map_err(|e| eg!(e))
            .c(d!())?;
        Ok(Self(s.to_owned()))
    }
}

impl TryFrom<&VerifyKey> for RawVerifyKey {
    type Error = Box<dyn RucError>;
    fn try_from(k: &VerifyKey) -> Result<Self> {
        let bytes: [u8; 32] = decode_bytes(&k.0).c(d!())?;
        RawVerifyKey::from_bytes(&bytes).map_err(|e| eg!(e)).c(d!())
    }
}

impl TryFrom<VerifyKey> for RawVerifyKey {
    type Error = Box<dyn RucError>;
    fn try_from(k: VerifyKey) -> Result<Self> {
        Self::try_from(&k)
    }
}

impl From<&RawVerifyKey> for VerifyKey {
    fn from(vk: &RawVerifyKey) -> VerifyKey {
        VerifyKey(base64::encode(vk.as_bytes()))
    }
}

impl From<RawVerifyKey> for VerifyKey {
    fn from(vk: RawVerifyKey) -> VerifyKey {
        VerifyKey::from(&vk)
    }
}

pub fn verify_by_raw_vk(
    vk: &RawVerifyKey,
    sig: &Sig,
    msg: &[u8],
) -> Result<()> {
    let sig_bytes: [u8; 64] = decode_bytes(&sig.0).c(d!())?;
    let sig = ed25519_dalek::Signature::from_bytes(&sig_bytes);
    vk.verify(msg, &sig).map_err(|e| eg!(e)).c(d!())
}

impl Sig {
    pub fn into_string(self) -> String {
        self.0
    }
}

impl fmt::Display for Sig {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl TryFrom<String> for Sig {
    type Error = Box<dyn RucError>;
    fn try_from(s: String) -> Result<Self> {
        decode_bytes::<64>(&s).c(d!())?;
        Ok(Self(s))
    }
}

impl TryFrom<&str> for Sig {
    type Error = Box<dyn RucError>;
    fn try_from(s: &str) -> Result<Self> {
        decode_bytes::<64>(s).c(d!())?;
        Ok(Self(s.to_owned()))
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn sign_verify() {
        let msg = b"aljflajfljaljfl";
        let (sk, vk) = create_keypair();

        let sig = sk.sign(msg).unwrap();
        let sig = sig.into_string();
        let sig = Sig::try_from(sig).unwrap();

        assert!(vk.verify(&sig, msg).is_ok());

        let msg_fake = b"00000000000000000";
        assert!(vk.verify(&sig, msg_fake).is_err());
    }

    #[test]
    fn parse_key() {
        assert!(SignKey::try_from(";akjflkjafj".to_owned()).is_err());
        assert!(VerifyKey::try_from(";akjflkjafj".to_owned()).is_err());

        let (sk, vk) = create_keypair();
        assert!(SignKey::try_from(sk.to_string()).is_ok());
        assert!(VerifyKey::try_from(vk.to_string()).is_ok());
    }
}