signer-core 0.3.2

Signer core package.
Documentation
use base64::{prelude::BASE64_URL_SAFE, Engine};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use sha3::Digest;

use crate::Result;

use crate::SignerUser;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SignerSigned<T> {
    pub sig: String,
    pub msg: String,
    pub pubkey: String,
    #[serde(skip)]
    pub _marker: std::marker::PhantomData<T>,
}

impl<T> SignerSigned<T>
where
    T: Serialize + DeserializeOwned,
{
    pub fn from_value(user: &SignerUser, value: &T) -> Result<Self> {
        let msg = serde_json::to_string(value)?;
        let msg = msg.as_bytes();

        let mut hasher = sha3::Sha3_256::new();
        hasher.update(&msg);
        let hash = hasher.finalize();

        let keypair = user.to_keypair()?;
        let sig = keypair.sign_simple(b"", hash.as_slice());

        Ok(SignerSigned {
            sig: BASE64_URL_SAFE.encode(sig.to_bytes()),
            msg: BASE64_URL_SAFE.encode(msg),
            pubkey: user.public.pub_key.clone(),
            _marker: std::marker::PhantomData,
        })
    }

    pub fn from_field(pubkey: &str, msg: &str, sig: &str) -> Result<Self> {
        Ok(SignerSigned {
            sig: sig.to_string(),
            msg: msg.to_string(),
            pubkey: pubkey.to_string(),
            _marker: std::marker::PhantomData,
        })
    }

    pub fn verify_to_value(&self) -> Result<T> {
        let msg = BASE64_URL_SAFE.decode(&self.msg)?;
        let sig = BASE64_URL_SAFE.decode(&self.sig)?;

        let mut hasher = sha3::Sha3_256::new();
        hasher.update(&msg);
        let hash = hasher.finalize();

        let sig = schnorrkel::Signature::from_bytes(&sig)
            .map_err(|e| crate::SignerError::Msg(format!("decode signature failed: {}", e)))?;
        let pub_key = schnorrkel::PublicKey::from_bytes(&BASE64_URL_SAFE.decode(&self.pubkey)?)
            .map_err(|e| crate::SignerError::Msg(format!("decode public key failed: {}", e)))?;
        pub_key
            .verify_simple(b"", hash.as_slice(), &sig)
            .map_err(|e| crate::SignerError::Msg(format!("verify signature failed: {}", e)))?;

        let value = serde_json::from_str(&String::from_utf8(msg)?)?;
        Ok(value)
    }
}