use sawtooth_sdk::signing::{secp256k1, Context};
use crate::hex;
use super::{error::Error, SignatureVerifier, SignatureVerifierFactory, Signer};
pub struct SawtoothSecp256k1RefSigner<'c> {
context: &'c secp256k1::Secp256k1Context,
private_key: secp256k1::Secp256k1PrivateKey,
public_key: Vec<u8>,
}
impl<'c> SawtoothSecp256k1RefSigner<'c> {
pub fn new(
context: &'c secp256k1::Secp256k1Context,
private_key: secp256k1::Secp256k1PrivateKey,
) -> Result<Self, Error> {
let public_key = context
.get_public_key(&private_key)
.map_err(|err| Error::SigningError(format!("Unable to extract public key: {}", err)))?
.as_slice()
.to_vec();
Ok(Self {
context,
private_key,
public_key,
})
}
}
impl<'c> Signer for SawtoothSecp256k1RefSigner<'c> {
fn sign(&self, message: &[u8]) -> Result<Vec<u8>, Error> {
self.context
.sign(message, &self.private_key)
.map_err(|err| Error::SigningError(format!("Failed to sign message: {}", err)))
.and_then(|signature| {
hex::parse_hex(&signature).map_err(|err| {
Error::SigningError(format!(
"Unable to parse sawtooth signature {} into bytes: {}",
signature, err
))
})
})
}
fn public_key(&self) -> &[u8] {
&self.public_key
}
}
pub struct SawtoothSecp256k1RefSignatureVerifier<'c> {
context: &'c secp256k1::Secp256k1Context,
}
impl<'c> SawtoothSecp256k1RefSignatureVerifier<'c> {
pub fn new(context: &'c secp256k1::Secp256k1Context) -> Self {
Self { context }
}
}
impl<'c> SignatureVerifier for SawtoothSecp256k1RefSignatureVerifier<'c> {
fn verify(&self, message: &[u8], signature: &[u8], public_key: &[u8]) -> Result<bool, Error> {
let public_key_hex = hex::to_hex(public_key);
let public_key =
secp256k1::Secp256k1PublicKey::from_hex(&public_key_hex).map_err(|err| {
Error::SignatureVerificationError(format!(
"Unable to read public key {}: {}",
public_key_hex, err
))
})?;
let signature_hex = hex::to_hex(signature);
self.context
.verify(&signature_hex, message, &public_key)
.map_err(|err| {
Error::SignatureVerificationError(format!(
"Unable to verify signature {}: {}",
signature_hex, err
))
})
}
}
#[derive(Default)]
pub struct SawtoothSecp256k1SignatureVerifier {
context: secp256k1::Secp256k1Context,
}
impl SawtoothSecp256k1SignatureVerifier {
pub fn new() -> Self {
SawtoothSecp256k1SignatureVerifier::default()
}
}
impl SignatureVerifier for SawtoothSecp256k1SignatureVerifier {
fn verify(&self, message: &[u8], signature: &[u8], public_key: &[u8]) -> Result<bool, Error> {
SawtoothSecp256k1RefSignatureVerifier::new(&self.context)
.verify(message, signature, public_key)
}
}
impl SignatureVerifierFactory for SawtoothSecp256k1SignatureVerifier {
fn create_verifier(&self) -> Box<dyn SignatureVerifier> {
Box::new(SawtoothSecp256k1SignatureVerifier::new())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::signing::tests::test_signer_implementation;
static KEY1_PRIV_HEX: &str = "2f1e7b7a130d7ba9da0068b3bb0ba1d79e7e77110302c9f746c3c2a63fe40088";
#[test]
fn test_sawtooth_secp256k1() {
let context = secp256k1::Secp256k1Context::new();
let private_key = secp256k1::Secp256k1PrivateKey::from_hex(KEY1_PRIV_HEX)
.expect("unable to read hex private key");
let sawtooth_signer = SawtoothSecp256k1RefSigner::new(&context, private_key)
.expect("Unable to create signer");
let sawtooth_verifier = SawtoothSecp256k1RefSignatureVerifier::new(&context);
test_signer_implementation(&sawtooth_signer, &sawtooth_verifier);
}
}