sdk_common/src/signature.rs
2025-08-27 13:57:34 +02:00

69 lines
1.8 KiB
Rust

use anyhow::Result;
use rand::{thread_rng, RngCore};
use serde::{Serialize, Deserialize};
use sp_client::bitcoin::key::Secp256k1;
use sp_client::bitcoin::secp256k1::schnorr::Signature;
use sp_client::bitcoin::secp256k1::{Keypair, Message, SecretKey, XOnlyPublicKey};
use sp_client::bitcoin::hashes::{sha256t_hash_newtype, Hash, HashEngine};
sha256t_hash_newtype! {
pub struct AnkMessageTag = hash_str("4nk/Message");
#[hash_newtype(forward)]
pub struct AnkMessageHash(_);
}
impl AnkMessageHash {
pub fn from_message(message: &[u8]) -> Self {
let mut eng = AnkMessageHash::engine();
eng.input(&message);
AnkMessageHash::from_engine(eng)
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct Proof {
signature: Signature,
message: AnkMessageHash,
key: XOnlyPublicKey
}
impl Proof {
pub fn new(message: &[u8], signing_key: SecretKey) -> Self {
let message_hash = AnkMessageHash::from_message(message);
let secp = Secp256k1::signing_only();
let keypair = Keypair::from_secret_key(&secp, &signing_key);
let mut aux_rand = [0u8; 32];
thread_rng().fill_bytes(&mut aux_rand);
let sig = secp.sign_schnorr_with_aux_rand(&Message::from_digest(message_hash.to_byte_array()), &keypair, &aux_rand);
Self {
signature: sig,
message: message_hash,
key: keypair.x_only_public_key().0
}
}
pub fn get_key(&self) -> XOnlyPublicKey {
self.key
}
pub fn verify(&self) -> Result<()> {
let secp = Secp256k1::verification_only();
secp.verify_schnorr(&self.signature, &Message::from_digest(self.message.to_byte_array()), &self.key)?;
Ok(())
}
pub fn to_string(&self) -> String {
serde_json::to_string(self).unwrap()
}
}