use secp::{MaybePoint, Scalar};
use crate::{AdaptorSignature, LiftedSignature};
use hmac::digest::FixedOutput as _;
use hmac::Mac as _;
use sha2::Digest as _;
fn hmac_sha256(key: &[u8; 32], msg: &[u8]) -> [u8; 32] {
hmac::Hmac::<sha2::Sha256>::new_from_slice(key.as_ref())
.expect("Hmac::new_from_slice never fails")
.chain_update(msg)
.finalize_fixed()
.into()
}
pub fn derive_nonce_rfc6979(seckey: impl Into<Scalar>, message: impl AsRef<[u8]>) -> Scalar {
let seckey = seckey.into();
let h1 = sha2::Sha256::new()
.chain_update(message.as_ref())
.finalize();
let mut V = [1u8; 32];
let mut K = [0u8; 32];
let mut buf = vec![0u8; 32 + 1 + 32 + 32];
buf[..32].copy_from_slice(&V);
buf[32] = 0;
buf[33..65].copy_from_slice(&seckey.serialize());
buf[65..].copy_from_slice(&h1);
K = hmac_sha256(&K, &buf);
V = hmac_sha256(&K, &V);
buf[..32].copy_from_slice(&V);
buf[32] = 1;
K = hmac_sha256(&K, &buf);
V = hmac_sha256(&K, &V);
loop {
V = hmac_sha256(&K, &V);
if let Ok(k) = Scalar::from_slice(&V) {
return k;
}
buf[..32].copy_from_slice(&V);
buf[32] = 0;
K = hmac_sha256(&K, &buf[..33]);
V = hmac_sha256(&K, &V);
}
}
pub mod adaptor {
use super::*;
pub fn sign_solo(
seckey: impl Into<Scalar>,
message: impl AsRef<[u8]>,
adaptor_point: impl Into<MaybePoint>,
) -> AdaptorSignature {
let seckey = seckey.into();
let aux = derive_nonce_rfc6979(seckey, &message).serialize();
crate::adaptor::sign_solo(seckey, message, aux, adaptor_point)
}
}
pub fn sign_solo<T>(seckey: impl Into<Scalar>, message: impl AsRef<[u8]>) -> T
where
T: From<LiftedSignature>,
{
let seckey = seckey.into();
let aux = derive_nonce_rfc6979(seckey, &message).serialize();
crate::sign_solo(seckey, message, aux)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_rfc6979_nonces() {
struct TestVector {
seckey: Scalar,
message: &'static str,
expected_nonce: &'static str,
}
let test_vectors = [
TestVector {
seckey: "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721"
.parse()
.unwrap(),
message: "sample",
expected_nonce: "A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60",
},
TestVector {
seckey: "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721"
.parse()
.unwrap(),
message: "test",
expected_nonce: "D16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0",
},
];
for test in test_vectors {
let nonce = derive_nonce_rfc6979(test.seckey, test.message);
assert_eq!(format!("{:X}", nonce), test.expected_nonce);
}
}
}