use crate::cesr::{mtr_dex, BaseMatter, Parsable};
use crate::errors::MatterError;
use crate::Matter;
use sodiumoxide::crypto::sign::ed25519;
use std::any::Any;
use p256::ecdsa::{signature::Verifier, Signature as p256Signature, VerifyingKey};
use secp256k1::ecdsa::Signature;
use secp256k1::{Message, PublicKey, Secp256k1};
use sha2::{Digest, Sha256};
#[derive(Debug, Clone)]
pub struct Verfer {
base: BaseMatter,
}
impl Verfer {
pub fn from_qb64(qb64: &str) -> Result<Self, MatterError> {
let base = BaseMatter::from_qb64(qb64)?;
if ![
mtr_dex::ED25519N,
mtr_dex::ED25519,
mtr_dex::ECDSA_256R1N,
mtr_dex::ECDSA_256R1,
mtr_dex::ECDSA_256K1N,
mtr_dex::ECDSA_256K1,
]
.contains(&base.code())
{
return Err(MatterError::UnsupportedCodeError(String::from(base.code())));
}
Ok(Verfer { base })
}
pub fn new(code: Option<&[u8]>, raw: Option<&str>) -> Result<Self, MatterError> {
let verfer = Self {
base: BaseMatter::new(code, raw, None, None)?,
};
if ![
mtr_dex::ED25519N,
mtr_dex::ED25519,
mtr_dex::ECDSA_256R1N,
mtr_dex::ECDSA_256R1,
mtr_dex::ECDSA_256K1N,
mtr_dex::ECDSA_256K1,
]
.contains(&verfer.code())
{
return Err(MatterError::UnsupportedCodeError(String::from(
verfer.code(),
)));
}
Ok(verfer)
}
pub fn verify(&self, sig: &[u8], ser: &[u8]) -> Result<bool, MatterError> {
match self.code() {
code if code == mtr_dex::ED25519N || code == mtr_dex::ED25519 => {
self.ed25519_verify(sig, ser)
}
code if code == mtr_dex::ECDSA_256R1N || code == mtr_dex::ECDSA_256R1 => {
self.secp256r1_verify(sig, ser)
}
code if code == mtr_dex::ECDSA_256K1N || code == mtr_dex::ECDSA_256K1 => {
self.secp256k1_verify(sig, ser)
}
_ => Err(MatterError::UnsupportedCodeError(String::from(self.code()))),
}
}
fn ed25519_verify(&self, sig: &[u8], ser: &[u8]) -> Result<bool, MatterError> {
if self.raw().len() != ed25519::PUBLICKEYBYTES {
return Err(MatterError::InvalidKeyLength {
expected: ed25519::PUBLICKEYBYTES,
actual: self.raw().len(),
});
}
if sig.len() != ed25519::SIGNATUREBYTES {
return Err(MatterError::InvalidSignatureLength {
expected: ed25519::SIGNATUREBYTES,
actual: sig.len(),
});
}
let pk = match ed25519::PublicKey::from_slice(&self.raw()) {
Some(key) => key,
None => {
return Err(MatterError::VerificationError(
"Invalid public key format".to_string(),
))
}
};
let signature = match ed25519::Signature::from_bytes(sig) {
Ok(sig) => sig,
Err(_) => {
return Err(MatterError::VerificationError(
"Invalid signature format".to_string(),
))
}
};
let result = ed25519::verify_detached(&signature, ser, &pk);
Ok(result)
}
fn secp256r1_verify(&self, sig: &[u8], ser: &[u8]) -> Result<bool, MatterError> {
if self.raw().len() != 33 && self.raw().len() != 65 {
return Err(MatterError::InvalidKeyLength {
expected: 33, actual: self.raw().len(),
});
}
let verifying_key = VerifyingKey::from_sec1_bytes(&self.raw())
.map_err(|e| MatterError::Secp256r1Error(format!("Invalid public key: {}", e)))?;
let signature_result = p256Signature::from_bytes(sig.into());
let signature = match signature_result {
Ok(sig) => sig,
Err(_) => {
p256Signature::try_from(sig).map_err(|e| {
MatterError::Secp256r1Error(format!("Invalid signature format: {}", e))
})?
}
};
match verifying_key.verify(ser, &signature) {
Ok(_) => Ok(true),
Err(_) => Ok(false), }
}
fn secp256k1_verify(&self, sig: &[u8], ser: &[u8]) -> Result<bool, MatterError> {
let secp = Secp256k1::verification_only();
if self.raw().len() != 33 && self.raw().len() != 65 {
return Err(MatterError::InvalidKeyLength {
expected: 33, actual: self.raw().len(),
});
}
let public_key = PublicKey::from_slice(&self.raw())
.map_err(|e| MatterError::Secp256k1Error(format!("Invalid public key: {}", e)))?;
let signature = if sig.len() == 64 {
Signature::from_compact(sig).map_err(|e| {
MatterError::Secp256k1Error(format!("Invalid compact signature: {}", e))
})?
} else {
Signature::from_der(sig)
.map_err(|e| MatterError::Secp256k1Error(format!("Invalid DER signature: {}", e)))?
};
let mut hasher = Sha256::new();
hasher.update(ser);
let result = hasher.finalize();
let message_hash: [u8; 32] = result.into();
let message = Message::from_digest(message_hash);
match secp.verify_ecdsa(&message, &signature, &public_key) {
Ok(_) => Ok(true),
Err(_) => Ok(false), }
}
}
impl Parsable for Verfer {
fn from_qb64b(data: &mut Vec<u8>, strip: Option<bool>) -> Result<Self, MatterError> {
let base = BaseMatter::from_qb64b(data, strip)?;
if ![
mtr_dex::ED25519N,
mtr_dex::ED25519,
mtr_dex::ECDSA_256R1N,
mtr_dex::ECDSA_256R1,
mtr_dex::ECDSA_256K1N,
mtr_dex::ECDSA_256K1,
]
.contains(&base.code())
{
return Err(MatterError::UnsupportedCodeError(String::from(base.code())));
}
Ok(Verfer { base })
}
fn from_qb2(data: &mut Vec<u8>, strip: Option<bool>) -> Result<Self, MatterError> {
let base = BaseMatter::from_qb2(data, strip)?;
if ![
mtr_dex::ED25519N,
mtr_dex::ED25519,
mtr_dex::ECDSA_256R1N,
mtr_dex::ECDSA_256R1,
mtr_dex::ECDSA_256K1N,
mtr_dex::ECDSA_256K1,
]
.contains(&base.code())
{
return Err(MatterError::UnsupportedCodeError(String::from(base.code())));
}
Ok(Verfer { base })
}
}
impl Matter for Verfer {
fn code(&self) -> &str {
self.base.code()
}
fn raw(&self) -> &[u8] {
self.base.raw()
}
fn qb64(&self) -> String {
self.base.qb64()
}
fn qb64b(&self) -> Vec<u8> {
self.base.qb64b()
}
fn qb2(&self) -> Vec<u8> {
self.base.qb2()
}
fn soft(&self) -> &str {
self.base.soft()
}
fn full_size(&self) -> usize {
self.base.full_size()
}
fn size(&self) -> usize {
self.base.size()
}
fn is_transferable(&self) -> bool {
self.base.is_transferable()
}
fn is_digestive(&self) -> bool {
self.base.is_digestive()
}
fn is_prefixive(&self) -> bool {
self.base.is_prefixive()
}
fn is_special(&self) -> bool {
self.base.is_special()
}
fn as_any(&self) -> &dyn Any {
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use p256::ecdsa::{signature::Signer, SigningKey};
use rand_core::OsRng;
use secp256k1::{rand, PublicKey, Secp256k1, SecretKey};
use sha2::{Digest, Sha256};
use sodiumoxide::crypto::sign::ed25519;
#[test]
fn test_verfer_ed25519() {
sodiumoxide::init().expect("Sodium initialization failed");
let (public_key, secret_key) = ed25519::gen_keypair();
let verkey = public_key.as_ref();
let empty_result = Verfer::new(None, Some(mtr_dex::ED25519N));
assert!(matches!(empty_result, Err(MatterError::TypeError(_))));
let verfer = Verfer::new(Some(verkey), Some(mtr_dex::ED25519N)).unwrap();
assert_eq!(verfer.raw(), verkey);
assert_eq!(verfer.code(), mtr_dex::ED25519N);
let ser = b"abcdefghijklmnopqrstuvwxyz0123456789";
let sig = ed25519::sign_detached(ser, &secret_key);
let result = verfer.verify(sig.as_ref(), ser).unwrap();
assert!(result);
let verfer = Verfer::new(Some(verkey), Some(mtr_dex::ED25519)).unwrap();
assert_eq!(verfer.raw(), verkey);
assert_eq!(verfer.code(), mtr_dex::ED25519);
let result = verfer.verify(sig.as_ref(), ser).unwrap();
assert!(result);
let blake_result = Verfer::new(Some(verkey), Some(mtr_dex::BLAKE3_256));
assert!(matches!(
blake_result,
Err(MatterError::UnsupportedCodeError(_))
));
}
#[test]
fn test_secp256r1_verfer() {
sodiumoxide::init().expect("Sodium initialization failed");
let signing_key = SigningKey::random(&mut OsRng);
let p256_public_key = signing_key.verifying_key();
let verkey = p256_public_key.to_encoded_point(true).as_bytes().to_vec();
let verfer = Verfer::new(Some(&verkey), Some(mtr_dex::ECDSA_256R1))
.expect("Failed to create verfer");
assert_eq!(verfer.raw(), &(*verkey));
assert_eq!(verfer.code(), mtr_dex::ECDSA_256R1);
let ser = b"abcdefghijklmnopqrstuvwxyz0123456789";
let signature: p256Signature = signing_key.sign(ser);
let result = match p256_public_key.verify(ser, &signature) {
Ok(_) => true,
Err(_) => false,
};
assert!(result);
let der_bytes = signature.to_bytes();
let r = signature.r().to_bytes();
let s = signature.s().to_bytes();
let mut raw_sig = Vec::with_capacity(64);
raw_sig.extend_from_slice(&r);
raw_sig.extend_from_slice(&s);
let result = verfer
.verify(&raw_sig, ser)
.expect("Verification failed with error");
assert!(result);
let result = verfer
.verify(&der_bytes, b"ABC")
.expect("Verification failed with error");
assert!(!result);
let verfer = Verfer::new(Some(&verkey), Some(mtr_dex::ECDSA_256R1N))
.expect("Failed to create verfer");
assert_eq!(verfer.raw(), &(*verkey));
assert_eq!(verfer.code(), mtr_dex::ECDSA_256R1N);
}
#[test]
fn test_verfer_secp256k1() {
let secp = Secp256k1::new();
let mut rng = rand::thread_rng();
let secret_key = SecretKey::new(&mut rng);
let public_key = PublicKey::from_secret_key(&secp, &secret_key);
let verkey = public_key.serialize();
let verfer = Verfer::new(Some(&verkey.to_vec()), Some(mtr_dex::ECDSA_256K1)).unwrap();
assert_eq!(verfer.raw(), verkey.to_vec());
assert_eq!(verfer.code(), mtr_dex::ECDSA_256K1);
let ser = b"abcdefghijklmnopqrstuvwxyz0123456789";
let mut hasher = Sha256::new();
hasher.update(ser);
let digest = hasher.finalize();
let digest: [u8; 32] = digest.into();
let message = Message::from_digest(digest);
let signature = secp.sign_ecdsa(&message, &secret_key);
let der_sig = signature.serialize_der();
let ser_sig = signature.serialize_compact();
let result = verfer.verify(&ser_sig, ser).unwrap();
assert!(result);
let wrong_message = b"ABC";
let result = verfer.verify(&der_sig, wrong_message);
assert!(result.is_err() || !result.unwrap());
let secret_key = SecretKey::new(&mut rng);
let public_key = PublicKey::from_secret_key(&secp, &secret_key);
let verkey = public_key.serialize();
let verfer = Verfer::new(Some(&verkey.to_vec()), Some(mtr_dex::ECDSA_256K1N)).unwrap();
assert_eq!(verfer.raw(), verkey.to_vec());
assert_eq!(verfer.code(), mtr_dex::ECDSA_256K1N);
let mut hasher = Sha256::new();
hasher.update(ser);
let digest = hasher.finalize();
let digest: [u8; 32] = digest.into();
let message = Message::from_digest(digest);
let signature = secp.sign_ecdsa(&message, &secret_key);
let der_sig = signature.serialize_der();
let ser_sig = signature.serialize_compact();
let result = verfer.verify(&ser_sig, ser).unwrap();
assert!(result);
let wrong_message = b"ABC";
let result = verfer.verify(&der_sig, wrong_message);
assert!(result.is_err() || !result.unwrap());
}
}