mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-03-26 04:03:06 +00:00
initialize branch
This commit is contained in:
parent
be4f6c0c78
commit
6fec57605f
@ -8,8 +8,6 @@ license = { workspace = true }
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
secp256k1 = "0.31.1"
|
||||
|
||||
nssa.workspace = true
|
||||
nssa_core.workspace = true
|
||||
common.workspace = true
|
||||
|
||||
@ -39,7 +39,7 @@ impl KeyNode for ChildKeysPrivate {
|
||||
value: (
|
||||
KeyChain {
|
||||
secret_spending_key: ssk,
|
||||
nullifer_public_key: npk,
|
||||
nullifier_public_key: npk,
|
||||
viewing_public_key: vpk,
|
||||
private_key_holder: PrivateKeyHolder {
|
||||
nullifier_secret_key: nsk,
|
||||
@ -54,10 +54,7 @@ impl KeyNode for ChildKeysPrivate {
|
||||
}
|
||||
|
||||
fn nth_child(&self, cci: u32) -> Self {
|
||||
#[expect(
|
||||
clippy::arithmetic_side_effects,
|
||||
reason = "Multiplying finite field scalars gives no unexpected side effects"
|
||||
)]
|
||||
#[expect(clippy::arithmetic_side_effects, reason = "TODO: fix later")]
|
||||
let parent_pt =
|
||||
Scalar::from_repr(self.value.0.private_key_holder.nullifier_secret_key.into())
|
||||
.expect("Key generated as scalar, must be valid representation")
|
||||
@ -67,7 +64,8 @@ impl KeyNode for ChildKeysPrivate {
|
||||
|
||||
input.extend_from_slice(b"LEE_seed_priv");
|
||||
input.extend_from_slice(&parent_pt.to_bytes());
|
||||
input.extend_from_slice(&cci.to_le_bytes());
|
||||
#[expect(clippy::big_endian_bytes, reason = "BIP-032 uses big endian")]
|
||||
input.extend_from_slice(&cci.to_be_bytes());
|
||||
|
||||
let hash_value = hmac_sha512::HMAC::mac(input, self.ccc);
|
||||
|
||||
@ -90,7 +88,7 @@ impl KeyNode for ChildKeysPrivate {
|
||||
value: (
|
||||
KeyChain {
|
||||
secret_spending_key: ssk,
|
||||
nullifer_public_key: npk,
|
||||
nullifier_public_key: npk,
|
||||
viewing_public_key: vpk,
|
||||
private_key_holder: PrivateKeyHolder {
|
||||
nullifier_secret_key: nsk,
|
||||
@ -113,31 +111,39 @@ impl KeyNode for ChildKeysPrivate {
|
||||
}
|
||||
|
||||
fn account_id(&self) -> nssa::AccountId {
|
||||
nssa::AccountId::from(&self.value.0.nullifer_public_key)
|
||||
nssa::AccountId::from(&self.value.0.nullifier_public_key)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'keys> From<&'keys ChildKeysPrivate> for &'keys (KeyChain, nssa::Account) {
|
||||
fn from(value: &'keys ChildKeysPrivate) -> Self {
|
||||
#[expect(
|
||||
clippy::single_char_lifetime_names,
|
||||
reason = "TODO add meaningful name"
|
||||
)]
|
||||
impl<'a> From<&'a ChildKeysPrivate> for &'a (KeyChain, nssa::Account) {
|
||||
fn from(value: &'a ChildKeysPrivate) -> Self {
|
||||
&value.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<'keys> From<&'keys mut ChildKeysPrivate> for &'keys mut (KeyChain, nssa::Account) {
|
||||
fn from(value: &'keys mut ChildKeysPrivate) -> Self {
|
||||
#[expect(
|
||||
clippy::single_char_lifetime_names,
|
||||
reason = "TODO add meaningful name"
|
||||
)]
|
||||
impl<'a> From<&'a mut ChildKeysPrivate> for &'a mut (KeyChain, nssa::Account) {
|
||||
fn from(value: &'a mut ChildKeysPrivate) -> Self {
|
||||
&mut value.value
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use nssa_core::NullifierSecretKey;
|
||||
use nssa_core::{NullifierPublicKey, NullifierSecretKey};
|
||||
|
||||
use super::*;
|
||||
use crate::key_management::{self, secret_holders::ViewingSecretKey};
|
||||
|
||||
#[test]
|
||||
fn master_key_generation() {
|
||||
fn test_master_key_generation() {
|
||||
let seed: [u8; 64] = [
|
||||
252, 56, 204, 83, 232, 123, 209, 188, 187, 167, 39, 213, 71, 39, 58, 65, 125, 134, 255,
|
||||
49, 43, 108, 92, 53, 173, 164, 94, 142, 150, 74, 21, 163, 43, 144, 226, 87, 199, 18,
|
||||
@ -147,7 +153,7 @@ mod tests {
|
||||
|
||||
let keys = ChildKeysPrivate::root(seed);
|
||||
|
||||
let expected_ssk = key_management::secret_holders::SecretSpendingKey([
|
||||
let expected_ssk: SecretSpendingKey = key_management::secret_holders::SecretSpendingKey([
|
||||
246, 79, 26, 124, 135, 95, 52, 51, 201, 27, 48, 194, 2, 144, 51, 219, 245, 128, 139,
|
||||
222, 42, 195, 105, 33, 115, 97, 186, 0, 97, 14, 218, 191,
|
||||
]);
|
||||
@ -162,7 +168,7 @@ mod tests {
|
||||
34, 234, 19, 222, 2, 22, 12, 163, 252, 88, 11, 0, 163,
|
||||
];
|
||||
|
||||
let expected_npk = nssa_core::NullifierPublicKey([
|
||||
let expected_npk: NullifierPublicKey = nssa_core::NullifierPublicKey([
|
||||
7, 123, 125, 191, 233, 183, 201, 4, 20, 214, 155, 210, 45, 234, 27, 240, 194, 111, 97,
|
||||
247, 155, 113, 122, 246, 192, 0, 70, 61, 76, 71, 70, 2,
|
||||
]);
|
||||
@ -179,13 +185,13 @@ mod tests {
|
||||
assert!(expected_ssk == keys.value.0.secret_spending_key);
|
||||
assert!(expected_ccc == keys.ccc);
|
||||
assert!(expected_nsk == keys.value.0.private_key_holder.nullifier_secret_key);
|
||||
assert!(expected_npk == keys.value.0.nullifer_public_key);
|
||||
assert!(expected_npk == keys.value.0.nullifier_public_key);
|
||||
assert!(expected_vsk == keys.value.0.private_key_holder.viewing_secret_key);
|
||||
assert!(expected_vpk_as_bytes == keys.value.0.viewing_public_key.to_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn child_keys_generation() {
|
||||
fn test_child_keys_generation() {
|
||||
let seed: [u8; 64] = [
|
||||
252, 56, 204, 83, 232, 123, 209, 188, 187, 167, 39, 213, 71, 39, 58, 65, 125, 134, 255,
|
||||
49, 43, 108, 92, 53, 173, 164, 94, 142, 150, 74, 21, 163, 43, 144, 226, 87, 199, 18,
|
||||
@ -197,31 +203,31 @@ mod tests {
|
||||
let child_node = ChildKeysPrivate::nth_child(&root_node, 42_u32);
|
||||
|
||||
let expected_ccc: [u8; 32] = [
|
||||
145, 59, 225, 32, 54, 168, 14, 45, 60, 253, 57, 202, 31, 86, 142, 234, 51, 57, 154, 88,
|
||||
132, 200, 92, 191, 220, 144, 42, 184, 108, 35, 226, 146,
|
||||
27, 73, 133, 213, 214, 63, 217, 184, 164, 17, 172, 140, 223, 95, 255, 157, 11, 0, 58,
|
||||
53, 82, 147, 121, 120, 199, 50, 30, 28, 103, 24, 121, 187,
|
||||
];
|
||||
|
||||
let expected_nsk: NullifierSecretKey = [
|
||||
19, 100, 119, 73, 191, 225, 234, 219, 129, 88, 40, 229, 63, 225, 189, 136, 69, 172,
|
||||
221, 186, 147, 83, 150, 207, 70, 17, 228, 70, 113, 87, 227, 31,
|
||||
124, 61, 40, 92, 33, 135, 3, 41, 200, 234, 3, 69, 102, 184, 57, 191, 106, 151, 194,
|
||||
192, 103, 132, 141, 112, 249, 108, 192, 117, 24, 48, 70, 216,
|
||||
];
|
||||
let expected_npk = nssa_core::NullifierPublicKey([
|
||||
133, 235, 223, 151, 12, 69, 26, 222, 60, 125, 235, 125, 167, 212, 201, 168, 101, 242,
|
||||
111, 239, 1, 228, 12, 252, 146, 53, 75, 17, 187, 255, 122, 181,
|
||||
let expected_npk: NullifierPublicKey = nssa_core::NullifierPublicKey([
|
||||
116, 231, 246, 189, 145, 240, 37, 59, 219, 223, 216, 246, 116, 171, 223, 55, 197, 200,
|
||||
134, 192, 221, 40, 218, 167, 239, 5, 11, 95, 147, 247, 162, 226,
|
||||
]);
|
||||
|
||||
let expected_vsk: ViewingSecretKey = [
|
||||
218, 219, 193, 132, 160, 6, 178, 194, 139, 248, 199, 81, 17, 133, 37, 201, 58, 104, 49,
|
||||
222, 187, 46, 156, 93, 14, 118, 209, 243, 38, 101, 77, 45,
|
||||
33, 155, 68, 60, 102, 70, 47, 105, 194, 129, 44, 26, 143, 198, 44, 244, 185, 31, 236,
|
||||
252, 205, 89, 138, 107, 39, 38, 154, 73, 109, 166, 41, 114,
|
||||
];
|
||||
let expected_vpk_as_bytes: [u8; 33] = [
|
||||
3, 164, 65, 167, 88, 167, 179, 51, 159, 27, 241, 174, 77, 174, 142, 106, 128, 96, 69,
|
||||
74, 117, 231, 42, 193, 235, 153, 206, 116, 102, 7, 101, 192, 45,
|
||||
2, 78, 213, 113, 117, 105, 162, 248, 175, 68, 128, 232, 106, 204, 208, 159, 11, 78, 48,
|
||||
244, 127, 112, 46, 0, 93, 184, 1, 77, 132, 160, 75, 152, 88,
|
||||
];
|
||||
|
||||
assert!(expected_ccc == child_node.ccc);
|
||||
assert!(expected_nsk == child_node.value.0.private_key_holder.nullifier_secret_key);
|
||||
assert!(expected_npk == child_node.value.0.nullifer_public_key);
|
||||
assert!(expected_npk == child_node.value.0.nullifier_public_key);
|
||||
assert!(expected_vsk == child_node.value.0.private_key_holder.viewing_secret_key);
|
||||
assert!(expected_vpk_as_bytes == child_node.value.0.viewing_public_key.to_bytes());
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use secp256k1::Scalar;
|
||||
use k256::elliptic_curve::{PrimeField as _, sec1::ToEncodedPoint as _};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::key_management::key_tree::traits::KeyNode;
|
||||
@ -16,14 +16,21 @@ impl ChildKeysPublic {
|
||||
fn compute_hash_value(&self, cci: u32) -> [u8; 64] {
|
||||
let mut hash_input = vec![];
|
||||
|
||||
if 2_u32.pow(31) > cci {
|
||||
// Non-harden
|
||||
hash_input.extend_from_slice(self.cpk.value());
|
||||
if ((2_u32).pow(31)).cmp(&cci) == std::cmp::Ordering::Greater {
|
||||
// Non-harden.
|
||||
// BIP-032 compatibility requires 1-byte header from the public_key;
|
||||
// Not stored in `self.cpk.value()`.
|
||||
let sk = k256::SecretKey::from_bytes(self.csk.value().into())
|
||||
.expect("32 bytes, within curve order");
|
||||
let pk = sk.public_key();
|
||||
hash_input.extend_from_slice(&pk.to_encoded_point(true).as_bytes());
|
||||
} else {
|
||||
// Harden
|
||||
// Harden.
|
||||
hash_input.extend_from_slice(&[0_u8]);
|
||||
hash_input.extend_from_slice(self.csk.value());
|
||||
}
|
||||
hash_input.extend_from_slice(&cci.to_le_bytes());
|
||||
|
||||
hash_input.extend_from_slice(&cci.to_be_bytes());
|
||||
|
||||
hmac_sha512::HMAC::mac(hash_input, self.ccc)
|
||||
}
|
||||
@ -33,7 +40,12 @@ impl KeyNode for ChildKeysPublic {
|
||||
fn root(seed: [u8; 64]) -> Self {
|
||||
let hash_value = hmac_sha512::HMAC::mac(seed, "LEE_master_pub");
|
||||
|
||||
let csk = nssa::PrivateKey::try_new(*hash_value.first_chunk::<32>().unwrap()).unwrap();
|
||||
let csk = nssa::PrivateKey::try_new(
|
||||
*hash_value
|
||||
.first_chunk::<32>()
|
||||
.expect("hash_value is 64 bytes, must be safe to get first 32"),
|
||||
)
|
||||
.unwrap();
|
||||
let ccc = *hash_value.last_chunk::<32>().unwrap();
|
||||
let cpk = nssa::PublicKey::new_from_private_key(&csk);
|
||||
|
||||
@ -48,24 +60,20 @@ impl KeyNode for ChildKeysPublic {
|
||||
fn nth_child(&self, cci: u32) -> Self {
|
||||
let hash_value = self.compute_hash_value(cci);
|
||||
|
||||
let csk = secp256k1::SecretKey::from_byte_array(
|
||||
*hash_value
|
||||
let csk = nssa::PrivateKey::try_new({
|
||||
let hash_value = hash_value
|
||||
.first_chunk::<32>()
|
||||
.expect("hash_value is 64 bytes, must be safe to get first 32"),
|
||||
)
|
||||
.unwrap();
|
||||
.expect("hash_value is 64 bytes, must be safe to get first 32");
|
||||
|
||||
let csk = nssa::PrivateKey::try_new(
|
||||
csk.add_tweak(&Scalar::from_le_bytes(*self.csk.value()).unwrap())
|
||||
.expect("Expect a valid Scalar")
|
||||
.secret_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
let value_1 =
|
||||
k256::Scalar::from_repr((*hash_value).into()).expect("Expect a valid k256 scalar");
|
||||
let value_2 = k256::Scalar::from_repr((*self.csk.value()).into())
|
||||
.expect("Expect a valid k256 scalar");
|
||||
|
||||
assert!(
|
||||
secp256k1::constants::CURVE_ORDER >= *csk.value(),
|
||||
"Secret key cannot exceed curve order"
|
||||
);
|
||||
let sum = value_1.add(&value_2);
|
||||
sum.to_bytes().into()
|
||||
})
|
||||
.expect("Expect a valid private key");
|
||||
|
||||
let ccc = *hash_value
|
||||
.last_chunk::<32>()
|
||||
@ -94,8 +102,12 @@ impl KeyNode for ChildKeysPublic {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'keys> From<&'keys ChildKeysPublic> for &'keys nssa::PrivateKey {
|
||||
fn from(value: &'keys ChildKeysPublic) -> Self {
|
||||
#[expect(
|
||||
clippy::single_char_lifetime_names,
|
||||
reason = "TODO add meaningful name"
|
||||
)]
|
||||
impl<'a> From<&'a ChildKeysPublic> for &'a nssa::PrivateKey {
|
||||
fn from(value: &'a ChildKeysPublic) -> Self {
|
||||
&value.csk
|
||||
}
|
||||
}
|
||||
@ -107,7 +119,7 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn master_keys_generation() {
|
||||
fn test_master_keys_generation() {
|
||||
let seed = [
|
||||
88, 189, 37, 237, 199, 125, 151, 226, 69, 153, 165, 113, 191, 69, 188, 221, 9, 34, 173,
|
||||
134, 61, 109, 34, 103, 121, 39, 237, 14, 107, 194, 24, 194, 191, 14, 237, 185, 12, 87,
|
||||
@ -126,6 +138,7 @@ mod tests {
|
||||
202, 148, 181, 228, 35, 222, 58, 84, 156, 24, 146, 86,
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
let expected_cpk: PublicKey = PublicKey::try_new([
|
||||
219, 141, 130, 105, 11, 203, 187, 124, 112, 75, 223, 22, 11, 164, 153, 127, 59, 247,
|
||||
244, 166, 75, 66, 242, 224, 35, 156, 161, 75, 41, 51, 76, 245,
|
||||
@ -138,7 +151,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn harden_child_keys_generation() {
|
||||
fn test_harden_child_keys_generation() {
|
||||
let seed = [
|
||||
88, 189, 37, 237, 199, 125, 151, 226, 69, 153, 165, 113, 191, 69, 188, 221, 9, 34, 173,
|
||||
134, 61, 109, 34, 103, 121, 39, 237, 14, 107, 194, 24, 194, 191, 14, 237, 185, 12, 87,
|
||||
@ -149,26 +162,20 @@ mod tests {
|
||||
let cci = (2_u32).pow(31) + 13;
|
||||
let child_keys = ChildKeysPublic::nth_child(&root_keys, cci);
|
||||
|
||||
print!(
|
||||
"{} {}",
|
||||
child_keys.csk.value()[0],
|
||||
child_keys.csk.value()[1]
|
||||
);
|
||||
|
||||
let expected_ccc = [
|
||||
126, 175, 244, 41, 41, 173, 134, 103, 139, 140, 195, 86, 194, 147, 116, 48, 71, 107,
|
||||
253, 235, 114, 139, 60, 115, 226, 205, 215, 248, 240, 190, 196, 6,
|
||||
149, 226, 13, 4, 194, 12, 69, 29, 9, 234, 209, 119, 98, 4, 128, 91, 37, 103, 192, 31,
|
||||
130, 126, 123, 20, 90, 34, 173, 209, 101, 248, 155, 36,
|
||||
];
|
||||
|
||||
let expected_csk: PrivateKey = PrivateKey::try_new([
|
||||
128, 148, 53, 165, 222, 155, 163, 108, 186, 182, 124, 67, 90, 86, 59, 123, 95, 224,
|
||||
171, 4, 51, 131, 254, 57, 241, 178, 82, 161, 204, 206, 79, 107,
|
||||
9, 65, 33, 228, 25, 82, 219, 117, 91, 217, 11, 223, 144, 85, 246, 26, 123, 216, 107,
|
||||
213, 33, 52, 188, 22, 198, 246, 71, 46, 245, 174, 16, 47,
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
let expected_cpk: PublicKey = PublicKey::try_new([
|
||||
149, 240, 55, 15, 178, 67, 245, 254, 44, 141, 95, 223, 238, 62, 85, 11, 248, 9, 11, 40,
|
||||
69, 211, 116, 13, 189, 35, 8, 95, 233, 154, 129, 58,
|
||||
142, 143, 238, 159, 105, 165, 224, 252, 108, 62, 53, 209, 176, 219, 249, 38, 90, 241,
|
||||
201, 81, 194, 146, 236, 5, 83, 152, 238, 243, 138, 16, 229, 15,
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
@ -178,7 +185,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nonharden_child_keys_generation() {
|
||||
fn test_nonharden_child_keys_generation() {
|
||||
let seed = [
|
||||
88, 189, 37, 237, 199, 125, 151, 226, 69, 153, 165, 113, 191, 69, 188, 221, 9, 34, 173,
|
||||
134, 61, 109, 34, 103, 121, 39, 237, 14, 107, 194, 24, 194, 191, 14, 237, 185, 12, 87,
|
||||
@ -189,26 +196,20 @@ mod tests {
|
||||
let cci = 13;
|
||||
let child_keys = ChildKeysPublic::nth_child(&root_keys, cci);
|
||||
|
||||
print!(
|
||||
"{} {}",
|
||||
child_keys.csk.value()[0],
|
||||
child_keys.csk.value()[1]
|
||||
);
|
||||
|
||||
let expected_ccc = [
|
||||
50, 29, 113, 102, 49, 130, 64, 0, 247, 95, 135, 187, 118, 162, 65, 65, 194, 53, 189,
|
||||
242, 66, 178, 168, 2, 51, 193, 155, 72, 209, 2, 207, 251,
|
||||
79, 228, 242, 119, 211, 203, 198, 175, 95, 36, 4, 234, 139, 45, 137, 138, 54, 211, 187,
|
||||
16, 28, 79, 80, 232, 216, 101, 145, 19, 101, 220, 217, 141,
|
||||
];
|
||||
|
||||
let expected_csk: PrivateKey = PrivateKey::try_new([
|
||||
162, 32, 211, 190, 180, 74, 151, 246, 189, 93, 8, 57, 182, 239, 125, 245, 192, 255, 24,
|
||||
186, 251, 23, 194, 186, 252, 121, 190, 54, 147, 199, 1, 109,
|
||||
185, 147, 32, 242, 145, 91, 123, 77, 42, 33, 134, 84, 12, 165, 117, 70, 158, 201, 95,
|
||||
153, 14, 12, 92, 235, 128, 156, 194, 169, 68, 35, 165, 127,
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
let expected_cpk: PublicKey = PublicKey::try_new([
|
||||
183, 48, 207, 170, 221, 111, 118, 9, 40, 67, 123, 162, 159, 169, 34, 157, 23, 37, 232,
|
||||
102, 231, 187, 199, 191, 205, 146, 159, 22, 79, 100, 10, 223,
|
||||
119, 16, 145, 121, 97, 244, 186, 35, 136, 34, 140, 171, 206, 139, 11, 208, 207, 121,
|
||||
158, 45, 28, 22, 140, 98, 161, 179, 212, 173, 238, 220, 2, 34,
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
@ -218,7 +219,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn edge_case_child_keys_generation_2_power_31() {
|
||||
fn test_edge_case_child_keys_generation_2_power_31() {
|
||||
let seed = [
|
||||
88, 189, 37, 237, 199, 125, 151, 226, 69, 153, 165, 113, 191, 69, 188, 221, 9, 34, 173,
|
||||
134, 61, 109, 34, 103, 121, 39, 237, 14, 107, 194, 24, 194, 191, 14, 237, 185, 12, 87,
|
||||
@ -230,19 +231,19 @@ mod tests {
|
||||
let child_keys = ChildKeysPublic::nth_child(&root_keys, cci);
|
||||
|
||||
let expected_ccc = [
|
||||
101, 15, 69, 152, 144, 22, 105, 89, 175, 21, 13, 50, 160, 167, 93, 80, 94, 99, 192,
|
||||
252, 1, 126, 196, 217, 149, 164, 60, 75, 237, 90, 104, 83,
|
||||
221, 208, 47, 189, 174, 152, 33, 25, 151, 114, 233, 191, 57, 15, 40, 140, 46, 87, 126,
|
||||
58, 215, 40, 246, 111, 166, 113, 183, 145, 173, 11, 27, 182,
|
||||
];
|
||||
|
||||
let expected_csk: PrivateKey = PrivateKey::try_new([
|
||||
46, 196, 131, 199, 190, 180, 250, 222, 41, 188, 221, 156, 255, 239, 251, 207, 239, 202,
|
||||
166, 216, 107, 236, 195, 48, 167, 69, 97, 13, 132, 117, 76, 89,
|
||||
223, 29, 87, 189, 126, 24, 117, 225, 190, 57, 0, 143, 207, 168, 231, 139, 170, 192, 81,
|
||||
254, 126, 10, 115, 42, 141, 157, 70, 171, 199, 231, 198, 132,
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
let expected_cpk: PublicKey = PublicKey::try_new([
|
||||
93, 151, 154, 238, 175, 198, 53, 146, 255, 43, 37, 52, 214, 165, 69, 161, 38, 20, 68,
|
||||
166, 143, 80, 149, 216, 124, 203, 240, 114, 168, 111, 33, 83,
|
||||
96, 123, 245, 51, 214, 216, 215, 205, 70, 145, 105, 221, 166, 169, 122, 27, 94, 112,
|
||||
228, 110, 249, 177, 85, 173, 180, 248, 185, 199, 112, 246, 83, 33,
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ pub type PublicAccountSigningKey = [u8; 32];
|
||||
pub struct KeyChain {
|
||||
pub secret_spending_key: SecretSpendingKey,
|
||||
pub private_key_holder: PrivateKeyHolder,
|
||||
pub nullifer_public_key: NullifierPublicKey,
|
||||
pub nullifier_public_key: NullifierPublicKey,
|
||||
pub viewing_public_key: ViewingPublicKey,
|
||||
}
|
||||
|
||||
@ -30,13 +30,13 @@ impl KeyChain {
|
||||
|
||||
let private_key_holder = secret_spending_key.produce_private_key_holder(None);
|
||||
|
||||
let nullifer_public_key = private_key_holder.generate_nullifier_public_key();
|
||||
let nullifier_public_key = private_key_holder.generate_nullifier_public_key();
|
||||
let viewing_public_key = private_key_holder.generate_viewing_public_key();
|
||||
|
||||
Self {
|
||||
secret_spending_key,
|
||||
private_key_holder,
|
||||
nullifer_public_key,
|
||||
nullifier_public_key,
|
||||
viewing_public_key,
|
||||
}
|
||||
}
|
||||
@ -50,13 +50,13 @@ impl KeyChain {
|
||||
|
||||
let private_key_holder = secret_spending_key.produce_private_key_holder(None);
|
||||
|
||||
let nullifer_public_key = private_key_holder.generate_nullifier_public_key();
|
||||
let nullifier_public_key = private_key_holder.generate_nullifier_public_key();
|
||||
let viewing_public_key = private_key_holder.generate_viewing_public_key();
|
||||
|
||||
Self {
|
||||
secret_spending_key,
|
||||
private_key_holder,
|
||||
nullifer_public_key,
|
||||
nullifier_public_key,
|
||||
viewing_public_key,
|
||||
}
|
||||
}
|
||||
@ -93,7 +93,7 @@ mod tests {
|
||||
|
||||
// Check that key holder fields are initialized with expected types
|
||||
assert_ne!(
|
||||
account_id_key_holder.nullifer_public_key.as_ref(),
|
||||
account_id_key_holder.nullifier_public_key.as_ref(),
|
||||
&[0_u8; 32]
|
||||
);
|
||||
}
|
||||
@ -119,7 +119,7 @@ mod tests {
|
||||
|
||||
let utxo_secret_key_holder = top_secret_key_holder.produce_private_key_holder(None);
|
||||
|
||||
let nullifer_public_key = utxo_secret_key_holder.generate_nullifier_public_key();
|
||||
let nullifier_public_key = utxo_secret_key_holder.generate_nullifier_public_key();
|
||||
let viewing_public_key = utxo_secret_key_holder.generate_viewing_public_key();
|
||||
|
||||
let pub_account_signing_key = nssa::PrivateKey::new_os_random();
|
||||
@ -150,7 +150,7 @@ mod tests {
|
||||
println!("Account {:?}", account.value().to_base58());
|
||||
println!(
|
||||
"Nulifier public key {:?}",
|
||||
hex::encode(nullifer_public_key.to_byte_array())
|
||||
hex::encode(nullifier_public_key.to_byte_array())
|
||||
);
|
||||
println!(
|
||||
"Viewing public key {:?}",
|
||||
@ -183,7 +183,7 @@ mod tests {
|
||||
fn non_trivial_chain_index() {
|
||||
let keys = account_with_chain_index_2_for_tests();
|
||||
|
||||
let eph_key_holder = EphemeralKeyHolder::new(&keys.nullifer_public_key);
|
||||
let eph_key_holder = EphemeralKeyHolder::new(&keys.nullifier_public_key);
|
||||
|
||||
let key_sender = eph_key_holder.calculate_shared_secret_sender(&keys.viewing_public_key);
|
||||
let key_receiver = keys.calculate_shared_secret_receiver(
|
||||
|
||||
@ -79,6 +79,7 @@ impl SeedHolder {
|
||||
|
||||
impl SecretSpendingKey {
|
||||
#[must_use]
|
||||
#[expect(clippy::big_endian_bytes, reason = "BIP-032 uses big endian")]
|
||||
pub fn generate_nullifier_secret_key(&self, index: Option<u32>) -> NullifierSecretKey {
|
||||
const PREFIX: &[u8; 8] = b"LEE/keys";
|
||||
const SUFFIX_1: &[u8; 1] = &[1];
|
||||
@ -93,13 +94,14 @@ impl SecretSpendingKey {
|
||||
hasher.update(PREFIX);
|
||||
hasher.update(self.0);
|
||||
hasher.update(SUFFIX_1);
|
||||
hasher.update(index.to_le_bytes());
|
||||
hasher.update(index.to_be_bytes());
|
||||
hasher.update(SUFFIX_2);
|
||||
|
||||
<NullifierSecretKey>::from(hasher.finalize_fixed())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[expect(clippy::big_endian_bytes, reason = "BIP-032 uses big endian")]
|
||||
pub fn generate_viewing_secret_key(&self, index: Option<u32>) -> ViewingSecretKey {
|
||||
const PREFIX: &[u8; 8] = b"LEE/keys";
|
||||
const SUFFIX_1: &[u8; 1] = &[2];
|
||||
@ -114,7 +116,7 @@ impl SecretSpendingKey {
|
||||
hasher.update(PREFIX);
|
||||
hasher.update(self.0);
|
||||
hasher.update(SUFFIX_1);
|
||||
hasher.update(index.to_le_bytes());
|
||||
hasher.update(index.to_be_bytes());
|
||||
hasher.update(SUFFIX_2);
|
||||
|
||||
hasher.finalize_fixed().into()
|
||||
|
||||
@ -46,7 +46,7 @@ impl NSSAUserData {
|
||||
) -> bool {
|
||||
let mut check_res = true;
|
||||
for (account_id, (key, _)) in accounts_keys_map {
|
||||
let expected_account_id = nssa::AccountId::from(&key.nullifer_public_key);
|
||||
let expected_account_id = nssa::AccountId::from(&key.nullifier_public_key);
|
||||
if expected_account_id != *account_id {
|
||||
println!("{expected_account_id}, {account_id}");
|
||||
check_res = false;
|
||||
|
||||
@ -18,6 +18,7 @@ sha2.workspace = true
|
||||
rand.workspace = true
|
||||
borsh.workspace = true
|
||||
hex.workspace = true
|
||||
k256.workspace = true
|
||||
secp256k1 = "0.31.1"
|
||||
risc0-binfmt = "3.0.2"
|
||||
log.workspace = true
|
||||
|
||||
@ -29,7 +29,7 @@ pub enum NssaError {
|
||||
Io(#[from] io::Error),
|
||||
|
||||
#[error("Invalid Public Key")]
|
||||
InvalidPublicKey(#[source] secp256k1::Error),
|
||||
InvalidPublicKey(#[source] k256::schnorr::Error),
|
||||
|
||||
#[error("Risc0 error: {0}")]
|
||||
ProgramWriteInputFailed(String),
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
use borsh::{BorshDeserialize, BorshSerialize};
|
||||
use k256::ecdsa::signature::RandomizedSigner;
|
||||
//use k256::schnorr::signature::Verifier;
|
||||
pub use private_key::PrivateKey;
|
||||
pub use public_key::PublicKey;
|
||||
use rand::{RngCore as _, rngs::OsRng};
|
||||
@ -25,6 +27,31 @@ impl Signature {
|
||||
Self::new_with_aux_random(key, message, aux_random)
|
||||
}
|
||||
|
||||
pub(crate) fn new_with_aux_random(
|
||||
key: &PrivateKey,
|
||||
message: &[u8],
|
||||
mut aux_random: [u8; 32],
|
||||
) -> Self {
|
||||
let value = {
|
||||
// Create signing key from raw bytes
|
||||
let signing_key = k256::schnorr::SigningKey::from_bytes(key.value()).unwrap();
|
||||
|
||||
// k256 expects a 32-byte message digest for Schnorr (BIP-340)
|
||||
let msg: &[u8; 32] = message.try_into().expect("message must be 32 bytes");
|
||||
|
||||
// Convert aux_random into the expected type
|
||||
let aux: k256::elliptic_curve::FieldBytes = aux_random.into();
|
||||
|
||||
// Sign with auxiliary randomness
|
||||
let signature: k256::schnorr::Signature = signing_key.sign_with_aux_rng(&aux, msg);
|
||||
|
||||
signature.to_bytes()
|
||||
};
|
||||
|
||||
Self { value }
|
||||
}
|
||||
|
||||
/*
|
||||
pub(crate) fn new_with_aux_random(
|
||||
key: &PrivateKey,
|
||||
message: &[u8],
|
||||
@ -39,14 +66,47 @@ impl Signature {
|
||||
};
|
||||
Self { value }
|
||||
}
|
||||
|
||||
*/
|
||||
#[must_use]
|
||||
pub fn is_valid_for(&self, bytes: &[u8], public_key: &PublicKey) -> bool {
|
||||
pub fn is_valid_for(&self, bytes: &[u8], public_key: &PublicKey) -> bool /*{
|
||||
// Convert signature bytes into Signature object
|
||||
let sig_slice: &[u8] = &self.value;
|
||||
let sig = match k256::schnorr::Signature::try_from(sig_slice) {
|
||||
Ok(s) => s,
|
||||
Err(_) => {panic!("TEST"); //return false
|
||||
},
|
||||
};
|
||||
|
||||
// Convert x-only public key to VerifyingKey
|
||||
let vk = match k256::schnorr::VerifyingKey::from_bytes(public_key.value()) {
|
||||
Ok(vk) => vk,
|
||||
Err(_) => {panic!("TEST"); //return false
|
||||
},
|
||||
};
|
||||
|
||||
// Verify the signature
|
||||
// vk.verify(bytes, &sig).is_ok()
|
||||
|
||||
// let msg = hex32(&v.message);
|
||||
// let sig_bytes = hex64(&v.signature);
|
||||
// let sig = Signature::try_from(&sig_bytes[..]).unwrap();
|
||||
|
||||
// let vk_bytes = hex32(&v.public_key);
|
||||
// let vk = VerifyingKey::from_bytes(&vk_bytes).unwrap();
|
||||
|
||||
// --- VERIFY ---
|
||||
// let verify_ok = vk.verify_prehash(&msg, &sig).is_ok();
|
||||
|
||||
|
||||
}*/{
|
||||
|
||||
let pk = secp256k1::XOnlyPublicKey::from_byte_array(*public_key.value()).unwrap();
|
||||
let secp = secp256k1::Secp256k1::new();
|
||||
let sig = secp256k1::schnorr::Signature::from_byte_array(self.value);
|
||||
secp.verify_schnorr(&sig, bytes, &pk).is_ok()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -21,7 +21,7 @@ impl PrivateKey {
|
||||
}
|
||||
|
||||
fn is_valid_key(value: [u8; 32]) -> bool {
|
||||
secp256k1::SecretKey::from_byte_array(value).is_ok()
|
||||
k256::SecretKey::from_bytes(&value.into()).is_ok()
|
||||
}
|
||||
|
||||
pub fn try_new(value: [u8; 32]) -> Result<Self, NssaError> {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use borsh::{BorshDeserialize, BorshSerialize};
|
||||
use k256::elliptic_curve::sec1::ToEncodedPoint as _;
|
||||
use nssa_core::account::AccountId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest as _, Sha256};
|
||||
@ -27,19 +28,24 @@ impl PublicKey {
|
||||
#[must_use]
|
||||
pub fn new_from_private_key(key: &PrivateKey) -> Self {
|
||||
let value = {
|
||||
let secret_key = secp256k1::SecretKey::from_byte_array(*key.value()).unwrap();
|
||||
let public_key =
|
||||
secp256k1::PublicKey::from_secret_key(&secp256k1::Secp256k1::new(), &secret_key);
|
||||
let (x_only, _) = public_key.x_only_public_key();
|
||||
x_only.serialize()
|
||||
let secret_key = k256::SecretKey::from_bytes(&(*key.value()).into())
|
||||
.expect("Expect a valid private key");
|
||||
|
||||
let encoded = secret_key.public_key().to_encoded_point(false);
|
||||
let x_only = encoded
|
||||
.x()
|
||||
.expect("Expect k256 point to have a x-coordinate");
|
||||
|
||||
*x_only.first_chunk().expect("x_only is exactly 32 bytes")
|
||||
};
|
||||
Self(value)
|
||||
}
|
||||
|
||||
pub fn try_new(value: [u8; 32]) -> Result<Self, NssaError> {
|
||||
// Check point is valid
|
||||
let _ = secp256k1::XOnlyPublicKey::from_byte_array(value)
|
||||
.map_err(NssaError::InvalidPublicKey)?;
|
||||
// Check point is a valid x-only public key
|
||||
let _ =
|
||||
k256::schnorr::VerifyingKey::from_bytes(&value).map_err(NssaError::InvalidPublicKey)?;
|
||||
|
||||
Ok(Self(value))
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user