Lucas Soriano del Pino
3 years ago
5 changed files with 142 additions and 90 deletions
@ -0,0 +1,78 @@ |
|||||
|
pub use secp256k1_zkp::*; |
||||
|
|
||||
|
use bdk::bitcoin::hashes::Hash; |
||||
|
use bip340_hash::Bip340Hash; |
||||
|
use rand::{CryptoRng, RngCore}; |
||||
|
use secp256k1_zkp::bitcoin_hashes::sha256; |
||||
|
use secp256k1_zkp::{schnorrsig, SecretKey}; |
||||
|
|
||||
|
mod bip340_hash; |
||||
|
mod secp_utils; |
||||
|
|
||||
|
/// Sign `msg` with the oracle's `key_pair` and a pre-computed `nonce`
|
||||
|
/// whose corresponding public key was included in a previous
|
||||
|
/// announcement.
|
||||
|
pub fn attest( |
||||
|
key_pair: &schnorrsig::KeyPair, |
||||
|
nonce: &SecretKey, |
||||
|
msg: &[u8], |
||||
|
) -> schnorrsig::Signature { |
||||
|
let msg = secp256k1_zkp::Message::from_hashed_data::<sha256::Hash>(msg); |
||||
|
secp_utils::schnorr_sign_with_nonce(&msg, key_pair, nonce) |
||||
|
} |
||||
|
|
||||
|
pub fn nonce<R>(rng: &mut R) -> (SecretKey, schnorrsig::PublicKey) |
||||
|
where |
||||
|
R: RngCore + CryptoRng, |
||||
|
{ |
||||
|
let nonce = SecretKey::new(rng); |
||||
|
|
||||
|
let key_pair = schnorrsig::KeyPair::from_secret_key(SECP256K1, nonce); |
||||
|
let nonce_pk = schnorrsig::PublicKey::from_keypair(SECP256K1, &key_pair); |
||||
|
|
||||
|
(nonce, nonce_pk) |
||||
|
} |
||||
|
|
||||
|
pub fn msg_hash( |
||||
|
pk: &schnorrsig::PublicKey, |
||||
|
nonce_pk: &schnorrsig::PublicKey, |
||||
|
msg: &[u8], |
||||
|
) -> Vec<u8> { |
||||
|
let mut buf = Vec::<u8>::new(); |
||||
|
buf.extend(&nonce_pk.serialize()); |
||||
|
buf.extend(&pk.serialize()); |
||||
|
buf.extend( |
||||
|
secp256k1_zkp::Message::from_hashed_data::<sha256::Hash>(msg) |
||||
|
.as_ref() |
||||
|
.to_vec(), |
||||
|
); |
||||
|
|
||||
|
Bip340Hash::hash(&buf).into_inner().to_vec() |
||||
|
} |
||||
|
|
||||
|
#[cfg(test)] |
||||
|
mod tests { |
||||
|
use super::*; |
||||
|
use rand::thread_rng; |
||||
|
|
||||
|
fn verify(sig: &schnorrsig::Signature, msg: &[u8], pk: &schnorrsig::PublicKey) -> bool { |
||||
|
let msg = secp256k1_zkp::Message::from_hashed_data::<sha256::Hash>(msg); |
||||
|
SECP256K1.schnorrsig_verify(sig, &msg, pk).is_ok() |
||||
|
} |
||||
|
|
||||
|
#[test] |
||||
|
fn attest_and_verify() { |
||||
|
let mut rng = thread_rng(); |
||||
|
|
||||
|
let key_pair = schnorrsig::KeyPair::new(SECP256K1, &mut rng); |
||||
|
let pk = schnorrsig::PublicKey::from_keypair(SECP256K1, &key_pair); |
||||
|
|
||||
|
let (nonce, _nonce_pk) = nonce(&mut rng); |
||||
|
|
||||
|
let msg = b"hello world"; |
||||
|
|
||||
|
let sig = attest(&key_pair, &nonce, msg); |
||||
|
|
||||
|
assert!(verify(&sig, msg, &pk)); |
||||
|
} |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
use bdk::bitcoin::hashes::*; |
||||
|
|
||||
|
sha256t_hash_newtype!( |
||||
|
Bip340Hash, |
||||
|
Bip340HashTag, |
||||
|
BIP340_MIDSTATE, |
||||
|
64, |
||||
|
doc = "bip340 hash", |
||||
|
true |
||||
|
); |
||||
|
|
||||
|
const BIP340_MIDSTATE: [u8; 32] = [ |
||||
|
0x9c, 0xec, 0xba, 0x11, 0x23, 0x92, 0x53, 0x81, 0x11, 0x67, 0x91, 0x12, 0xd1, 0x62, 0x7e, 0x0f, |
||||
|
0x97, 0xc8, 0x75, 0x50, 0x00, 0x3c, 0xc7, 0x65, 0x90, 0xf6, 0x11, 0x64, 0x33, 0xe9, 0xb6, 0x6a, |
||||
|
]; |
@ -0,0 +1,43 @@ |
|||||
|
use secp256k1_zkp::secp256k1_zkp_sys::types::c_void; |
||||
|
use secp256k1_zkp::secp256k1_zkp_sys::CPtr; |
||||
|
use secp256k1_zkp::{schnorrsig, SecretKey, SECP256K1}; |
||||
|
use std::os::raw::{c_int, c_uchar}; |
||||
|
use std::ptr; |
||||
|
|
||||
|
/// Create a Schnorr signature using the provided nonce instead of generating one.
|
||||
|
pub fn schnorr_sign_with_nonce( |
||||
|
msg: &secp256k1_zkp::Message, |
||||
|
keypair: &schnorrsig::KeyPair, |
||||
|
nonce: &SecretKey, |
||||
|
) -> schnorrsig::Signature { |
||||
|
unsafe { |
||||
|
let mut sig = [0u8; secp256k1_zkp::constants::SCHNORRSIG_SIGNATURE_SIZE]; |
||||
|
assert_eq!( |
||||
|
1, |
||||
|
secp256k1_zkp::ffi::secp256k1_schnorrsig_sign( |
||||
|
*SECP256K1.ctx(), |
||||
|
sig.as_mut_c_ptr(), |
||||
|
msg.as_c_ptr(), |
||||
|
keypair.as_ptr(), |
||||
|
Some(constant_nonce_fn), |
||||
|
nonce.as_c_ptr() as *const c_void |
||||
|
) |
||||
|
); |
||||
|
|
||||
|
schnorrsig::Signature::from_slice(&sig).unwrap() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
extern "C" fn constant_nonce_fn( |
||||
|
nonce32: *mut c_uchar, |
||||
|
_msg32: *const c_uchar, |
||||
|
_key32: *const c_uchar, |
||||
|
_xonly_pk32: *const c_uchar, |
||||
|
_algo16: *const c_uchar, |
||||
|
data: *mut c_void, |
||||
|
) -> c_int { |
||||
|
unsafe { |
||||
|
ptr::copy_nonoverlapping(data as *const c_uchar, nonce32, 32); |
||||
|
} |
||||
|
1 |
||||
|
} |
Loading…
Reference in new issue