polysig_driver/signers/
ecdsa.rsuse crate::{recoverable_signature::RecoverableSignature, Result};
use k256::ecdsa::{
signature::{hazmat::PrehashVerifier, Signer, Verifier},
RecoveryId, SigningKey, VerifyingKey,
};
use rand::rngs::OsRng;
use sha3::{Digest, Keccak256};
use std::borrow::Cow;
pub use k256::ecdsa::Signature;
pub struct EcdsaSigner<'a> {
signing_key: Cow<'a, SigningKey>,
}
impl<'a> EcdsaSigner<'a> {
pub fn new(signing_key: Cow<'a, SigningKey>) -> Self {
Self { signing_key }
}
pub fn from_slice(signing_key: &[u8]) -> Result<SigningKey> {
Ok(SigningKey::from_slice(signing_key)?)
}
pub fn random() -> SigningKey {
SigningKey::random(&mut OsRng)
}
pub fn sign_recoverable(
&self,
message: &[u8],
) -> Result<(Signature, RecoveryId)> {
Ok(self.signing_key.sign_recoverable(message)?)
}
pub fn sign_prehash_recoverable(
&self,
prehash: &[u8],
) -> Result<(Signature, RecoveryId)> {
Ok(self.signing_key.sign_prehash_recoverable(prehash)?)
}
pub fn sign(&self, message: &[u8]) -> Signature {
self.signing_key.sign(message)
}
pub fn verifying_key(&self) -> &VerifyingKey {
self.signing_key.verifying_key()
}
pub fn verify(
&self,
message: &[u8],
signature: &Signature,
) -> Result<()> {
Ok(self.verifying_key().verify(message, signature)?)
}
pub fn verify_prehash(
&self,
prehash: &[u8],
signature: &Signature,
) -> Result<()> {
Ok(self.verifying_key().verify_prehash(prehash, signature)?)
}
pub fn sign_eth(
&self,
message: &[u8],
) -> Result<(Signature, RecoveryId)> {
let digest = Keccak256::new_with_prefix(message);
Ok(self.signing_key.sign_digest_recoverable(digest)?)
}
pub fn sign_eth_message<B: AsRef<[u8]>>(
&self,
message: B,
) -> Result<(Signature, RecoveryId)> {
let digest = Self::hash_message(message);
Ok(self.signing_key.sign_digest_recoverable(digest)?)
}
pub fn recover(
message: &[u8],
signature: RecoverableSignature,
) -> Result<VerifyingKey> {
let recid = RecoveryId::try_from(signature.recovery_id)?;
let signature = Signature::from_slice(&signature.bytes)?;
Ok(VerifyingKey::recover_from_digest(
Keccak256::new_with_prefix(message),
&signature,
recid,
)?)
}
pub fn hash_message<T: AsRef<[u8]>>(message: T) -> impl Digest {
const PREFIX: &str = "\x19Ethereum Signed Message:\n";
let message = message.as_ref();
let len = message.len();
let len_string = len.to_string();
let mut eth_message =
Vec::with_capacity(PREFIX.len() + len_string.len() + len);
eth_message.extend_from_slice(PREFIX.as_bytes());
eth_message.extend_from_slice(len_string.as_bytes());
eth_message.extend_from_slice(message);
Keccak256::new_with_prefix(eth_message)
}
}