use crate::nuts::nut01::SecretKey;
use crate::nuts::nut02::KeySetVersion;
use crate::nuts::nut28::{blind_public_key, derive_signing_key_bip340, ecdh_kdf};
#[test]
fn test_ecdh_kdf() {
let sender_key = SecretKey::generate();
let receiver_key = SecretKey::generate();
let receiver_pubkey = receiver_key.public_key();
let _keyset_bytes = [KeySetVersion::Version01.to_byte()]
.into_iter()
.chain([1u8; 32])
.collect::<Vec<_>>();
let blinding_scalar = ecdh_kdf(&sender_key, &receiver_pubkey, 0).unwrap();
assert_ne!(blinding_scalar.to_secret_bytes(), [0u8; 32]);
let result = ecdh_kdf(&sender_key, &receiver_pubkey, 11);
assert!(result.is_err());
for slot in 0..=10 {
let result = ecdh_kdf(&sender_key, &receiver_pubkey, slot);
assert!(result.is_ok());
if slot > 0 {
let previous = ecdh_kdf(&sender_key, &receiver_pubkey, slot - 1).unwrap();
let current = result.unwrap();
assert_ne!(previous.to_secret_bytes(), current.to_secret_bytes());
}
}
}
#[test]
fn test_blind_public_key() {
let privkey = SecretKey::generate();
let pubkey = privkey.public_key();
let blinding_scalar = SecretKey::generate();
let blinded_pubkey = blind_public_key(&pubkey, &blinding_scalar).unwrap();
assert_ne!(pubkey.to_string(), blinded_pubkey.to_string());
let blinded_again = blind_public_key(&pubkey, &blinding_scalar).unwrap();
assert_eq!(blinded_pubkey.to_string(), blinded_again.to_string());
let r_pubkey = blinding_scalar.public_key();
let combined = pubkey.combine(&r_pubkey).unwrap();
assert_eq!(blinded_pubkey.to_string(), combined.to_string());
}
#[test]
fn test_signing_key_derivation() {
let privkey = SecretKey::generate();
let pubkey = privkey.public_key();
let blinding_scalar = SecretKey::generate();
let blinded_pubkey = blind_public_key(&pubkey, &blinding_scalar).unwrap();
let signing_key_bip340 =
derive_signing_key_bip340(&privkey, &blinding_scalar, &blinded_pubkey).unwrap();
let signing_pubkey_bip340 = signing_key_bip340.public_key();
assert_eq!(
signing_pubkey_bip340.x_only_public_key(),
blinded_pubkey.x_only_public_key()
);
}
#[test]
fn test_multi_key_blinding() {
let primary_key = SecretKey::generate();
let primary_pubkey = primary_key.public_key();
let additional_key1 = SecretKey::generate();
let additional_key2 = SecretKey::generate();
let additional_pubkey1 = additional_key1.public_key();
let additional_pubkey2 = additional_key2.public_key();
let refund_key1 = SecretKey::generate();
let refund_key2 = SecretKey::generate();
let refund_pubkey1 = refund_key1.public_key();
let refund_pubkey2 = refund_key2.public_key();
let ephemeral_key = SecretKey::generate();
let _keyset_bytes = [KeySetVersion::Version01.to_byte()]
.into_iter()
.chain([2u8; 32])
.collect::<Vec<_>>();
let primary_blinding = ecdh_kdf(&ephemeral_key, &primary_pubkey, 0).unwrap();
let blinded_primary = blind_public_key(&primary_pubkey, &primary_blinding).unwrap();
let add_blinding1 = ecdh_kdf(&ephemeral_key, &additional_pubkey1, 1).unwrap();
let add_blinding2 = ecdh_kdf(&ephemeral_key, &additional_pubkey2, 2).unwrap();
let blinded_add1 = blind_public_key(&additional_pubkey1, &add_blinding1).unwrap();
let blinded_add2 = blind_public_key(&additional_pubkey2, &add_blinding2).unwrap();
let refund_blinding1 = ecdh_kdf(&ephemeral_key, &refund_pubkey1, 3).unwrap();
let refund_blinding2 = ecdh_kdf(&ephemeral_key, &refund_pubkey2, 4).unwrap();
let blinded_refund1 = blind_public_key(&refund_pubkey1, &refund_blinding1).unwrap();
let blinded_refund2 = blind_public_key(&refund_pubkey2, &refund_blinding2).unwrap();
assert_ne!(primary_pubkey.to_string(), blinded_primary.to_string());
assert_ne!(additional_pubkey1.to_string(), blinded_add1.to_string());
assert_ne!(additional_pubkey2.to_string(), blinded_add2.to_string());
assert_ne!(refund_pubkey1.to_string(), blinded_refund1.to_string());
assert_ne!(refund_pubkey2.to_string(), blinded_refund2.to_string());
let ephemeral_pubkey = ephemeral_key.public_key();
let receiver_primary_blinding = ecdh_kdf(&primary_key, &ephemeral_pubkey, 0).unwrap();
assert_eq!(
primary_blinding.to_secret_bytes(),
receiver_primary_blinding.to_secret_bytes()
);
let receiver_add_blinding1 = ecdh_kdf(&additional_key1, &ephemeral_pubkey, 1).unwrap();
assert_eq!(
add_blinding1.to_secret_bytes(),
receiver_add_blinding1.to_secret_bytes()
);
let receiver_add_blinding2 = ecdh_kdf(&additional_key2, &ephemeral_pubkey, 2).unwrap();
assert_eq!(
add_blinding2.to_secret_bytes(),
receiver_add_blinding2.to_secret_bytes()
);
let receiver_refund_blinding1 = ecdh_kdf(&refund_key1, &ephemeral_pubkey, 3).unwrap();
assert_eq!(
refund_blinding1.to_secret_bytes(),
receiver_refund_blinding1.to_secret_bytes()
);
let receiver_refund_blinding2 = ecdh_kdf(&refund_key2, &ephemeral_pubkey, 4).unwrap();
assert_eq!(
refund_blinding2.to_secret_bytes(),
receiver_refund_blinding2.to_secret_bytes()
);
}