From a73c82d00f5a94f4230700b14f8e9418ec3f3fd9 Mon Sep 17 00:00:00 2001 From: ngutech21 Date: Fri, 16 Feb 2024 17:48:04 +0100 Subject: [PATCH] chore: add h2c domain separated --- moksha-core/src/dhke.rs | 52 ++++++++++++++++++++++++++++++++++++++++ moksha-core/src/error.rs | 3 +++ 2 files changed, 55 insertions(+) diff --git a/moksha-core/src/dhke.rs b/moksha-core/src/dhke.rs index 71ec4a58..4fca85b2 100644 --- a/moksha-core/src/dhke.rs +++ b/moksha-core/src/dhke.rs @@ -81,6 +81,32 @@ impl Dhke { point.unwrap() } + /// The point is generated by hashing the message with a domain separator and then + /// iteratively trying to compute a point from the hash. An increasing uint32 counter + /// (byte order little endian) is appended to the hash until a point is found that lies on the curve. + + /// The chance of finding a valid point is 50% for every iteration. The maximum number of iterations + /// is 2**16. If no valid point is found after 2**16 iterations, a ValueError is raised (this should + /// never happen in practice). + + /// The domain separator is b"Secp256k1_HashToCurve_Cashu_" or + /// bytes.fromhex("536563703235366b315f48617368546f43757276655f43617368755f"). + fn hash_to_curve_domain_separated(message: &[u8]) -> Result { + let msg_to_hash = sha256::Hash::hash(&[b"Secp256k1_HashToCurve_Cashu_", message].concat()); + (0..2u32.pow(16)) + .map(|counter| sha256::Hash::hash(&[&msg_to_hash[..], &counter.to_le_bytes()].concat())) + .find_map(|hash| { + PublicKey::from_slice( + &once(&0x02) + .chain(hash.to_byte_array().iter()) + .cloned() + .collect::>(), + ) + .ok() + }) + .ok_or(MokshaCoreError::NoValidPointFound) + } + pub fn step1_alice( &self, secret_msg: impl Into, @@ -283,4 +309,30 @@ mod tests { Ok(()) } + + #[test] + fn test_hash_to_curve_domain_separated_zero() -> anyhow::Result<()> { + let input_str = + hex_to_string("0000000000000000000000000000000000000000000000000000000000000000"); + let expected_result = "024cce997d3b518f739663b757deaec95bcd9473c30a14ac2fd04023a739d1a725"; + + let pk = Dhke::hash_to_curve_domain_separated(input_str.as_bytes()) + .unwrap() + .to_string(); + assert_eq!(pk, expected_result); + Ok(()) + } + + #[test] + fn test_hash_to_curve_domain_separated_one() -> anyhow::Result<()> { + let input_str = + hex_to_string("0000000000000000000000000000000000000000000000000000000000000001"); + let expected_result = "022e7158e11c9506f1aa4248bf531298daa7febd6194f003edcd9b93ade6253acf"; + + let pk = Dhke::hash_to_curve_domain_separated(input_str.as_bytes()) + .unwrap() + .to_string(); + assert_eq!(pk, expected_result); + Ok(()) + } } diff --git a/moksha-core/src/error.rs b/moksha-core/src/error.rs index 1931f4cc..afac6335 100644 --- a/moksha-core/src/error.rs +++ b/moksha-core/src/error.rs @@ -28,4 +28,7 @@ pub enum MokshaCoreError { #[error("Invalid token")] InvalidToken, + + #[error("No valid point on curve secp256k1 found")] + NoValidPointFound, }