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