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);
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());
}
}