use std::io::{self, Error, ErrorKind};
use ecdsa::signature::DigestVerifier;
use k256::ecdsa::{digest::Digest, VerifyingKey};
pub const LEN: usize = 65;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Sig(k256::ecdsa::recoverable::Signature);
impl Sig {
pub fn from_bytes(b: &[u8]) -> io::Result<Self> {
if b.len() != LEN {
return Err(Error::new(
ErrorKind::InvalidInput,
"invalid signature length",
));
}
let sig = k256::ecdsa::recoverable::Signature::try_from(b).map_err(|e| {
Error::new(
ErrorKind::Other,
format!("failed to load recoverable signature {}", e),
)
})?;
Ok(Self(sig))
}
pub fn to_bytes(&self) -> [u8; LEN] {
let mut b = [0u8; LEN];
b.copy_from_slice(self.0.as_ref());
b
}
pub fn recover_public_key(
&self,
digest: &[u8],
) -> io::Result<(crate::key::secp256k1::public_key::Key, VerifyingKey)> {
let prehash = sha2::Sha256::new_with_prefix(digest);
let vkey = self
.0
.recover_verifying_key_from_digest(prehash.clone())
.map_err(|e| {
Error::new(
ErrorKind::Other,
format!("failed recover_verifying_key {}", e),
)
})?;
assert!(vkey.verify_digest(prehash, &self.0).is_ok());
Ok((vkey.into(), vkey))
}
}
impl From<k256::ecdsa::recoverable::Signature> for Sig {
fn from(sig: k256::ecdsa::recoverable::Signature) -> Self {
Self(sig)
}
}
impl From<Sig> for k256::ecdsa::recoverable::Signature {
fn from(sig: Sig) -> Self {
sig.0
}
}
impl From<Sig> for [u8; LEN] {
fn from(sig: Sig) -> Self {
sig.to_bytes()
}
}
#[test]
fn test_signature() {
use ring::digest::{digest, SHA256};
let _ = env_logger::builder()
.filter_level(log::LevelFilter::Info)
.is_test(true)
.try_init();
let pk = crate::key::secp256k1::private_key::Key::generate().unwrap();
let _pubkey1 = pk.to_public_key();
let msg: Vec<u8> = random_manager::bytes(100).unwrap();
let hashed: Vec<u8> = digest(&SHA256, &msg).as_ref().into();
let sig = pk.sign_digest(&hashed).unwrap();
assert_eq!(sig.to_bytes().len(), crate::key::secp256k1::signature::LEN);
}