1use std::ops::Deref;
4
5use bitcoin::hashes::sha256::Hash as Sha256Hash;
6use bitcoin::hashes::Hash;
7use bitcoin::secp256k1::{
8 Parity, PublicKey as NormalizedPublicKey, Scalar, Secp256k1, XOnlyPublicKey,
9};
10use thiserror::Error;
11
12use crate::nuts::nut01::{PublicKey, SecretKey};
13use crate::nuts::nut12::ProofDleq;
14use crate::nuts::{BlindSignature, Keys, Proof, Proofs};
15use crate::secret::Secret;
16use crate::util::hex;
17use crate::SECP256K1;
18
19const DOMAIN_SEPARATOR: &[u8; 28] = b"Secp256k1_HashToCurve_Cashu_";
20
21#[derive(Debug, Error)]
23pub enum Error {
24 #[error("Token not verified")]
26 TokenNotVerified,
27 #[error("No valid point found")]
29 NoValidPoint,
30 #[error(transparent)]
32 Secp256k1(#[from] bitcoin::secp256k1::Error),
33 #[error("`{0}`")]
36 Custom(String),
37}
38
39pub fn hash_to_curve(message: &[u8]) -> Result<PublicKey, Error> {
44 let msg_to_hash: Vec<u8> = [DOMAIN_SEPARATOR, message].concat();
45
46 let msg_hash: [u8; 32] = Sha256Hash::hash(&msg_to_hash).to_byte_array();
47
48 let mut counter: u32 = 0;
49 while counter < 2_u32.pow(16) {
50 let mut bytes_to_hash: Vec<u8> = Vec::with_capacity(36);
51 bytes_to_hash.extend_from_slice(&msg_hash);
52 bytes_to_hash.extend_from_slice(&counter.to_le_bytes());
53 let hash: [u8; 32] = Sha256Hash::hash(&bytes_to_hash).to_byte_array();
54
55 match XOnlyPublicKey::from_slice(&hash) {
57 Ok(pk) => {
58 return Ok(NormalizedPublicKey::from_x_only_public_key(pk, Parity::Even).into())
59 }
60 Err(_) => {
61 counter += 1;
62 }
63 }
64 }
65
66 Err(Error::NoValidPoint)
67}
68
69pub fn hash_e<I>(public_keys: I) -> [u8; 32]
71where
72 I: IntoIterator<Item = PublicKey>,
73{
74 let mut e: String = String::new();
75
76 for public_key in public_keys.into_iter() {
77 let uncompressed: [u8; 65] = public_key.to_uncompressed_bytes();
78 e.push_str(&hex::encode(uncompressed));
79 }
80
81 Sha256Hash::hash(e.as_bytes()).to_byte_array()
82}
83
84pub fn blind_message(
88 secret: &[u8],
89 blinding_factor: Option<SecretKey>,
90) -> Result<(PublicKey, SecretKey), Error> {
91 let y: PublicKey = hash_to_curve(secret)?;
92 let r: SecretKey = blinding_factor.unwrap_or_else(SecretKey::generate);
93 Ok((y.combine(&r.public_key())?.into(), r))
94}
95
96pub fn unblind_message(
100 blinded_key: &PublicKey,
102 r: &SecretKey,
103 mint_pubkey: &PublicKey,
105) -> Result<PublicKey, Error> {
106 let r: Scalar = Scalar::from(r.deref().to_owned());
107
108 let a: PublicKey = mint_pubkey.mul_tweak(&SECP256K1, &r)?.into();
110
111 let a: PublicKey = a.negate(&SECP256K1).into();
113 Ok(blinded_key.combine(&a)?.into()) }
115
116pub fn construct_proofs(
118 promises: Vec<BlindSignature>,
119 rs: Vec<SecretKey>,
120 secrets: Vec<Secret>,
121 keys: &Keys,
122) -> Result<Proofs, Error> {
123 if (promises.len() != rs.len()) || (promises.len() != secrets.len()) {
124 tracing::error!(
125 "Promises: {}, RS: {}, secrets:{}",
126 promises.len(),
127 rs.len(),
128 secrets.len()
129 );
130 return Err(Error::Custom(
131 "Lengths of promises, rs, and secrets must be equal".to_string(),
132 ));
133 }
134 let mut proofs = vec![];
135 for ((blinded_signature, r), secret) in promises.into_iter().zip(rs).zip(secrets) {
136 let blinded_c: PublicKey = blinded_signature.c;
137 let a: PublicKey = keys
138 .amount_key(blinded_signature.amount)
139 .ok_or(Error::Custom("Could not get proofs".to_string()))?;
140
141 let unblinded_signature: PublicKey = unblind_message(&blinded_c, &r, &a)?;
142
143 let dleq = blinded_signature.dleq.map(|d| ProofDleq::new(d.e, d.s, r));
144
145 let proof = Proof {
146 amount: blinded_signature.amount,
147 keyset_id: blinded_signature.keyset_id,
148 secret,
149 c: unblinded_signature,
150 witness: None,
151 dleq,
152 p2pk_e: None,
153 };
154
155 proofs.push(proof);
156 }
157
158 Ok(proofs)
159}
160
161#[inline]
167pub fn sign_message(k: &SecretKey, blinded_message: &PublicKey) -> Result<PublicKey, Error> {
168 let k: Scalar = Scalar::from(k.deref().to_owned());
169 Ok(blinded_message.mul_tweak(&SECP256K1, &k)?.into())
170}
171
172pub fn verify_message(
174 a: &SecretKey,
175 unblinded_message: PublicKey,
176 msg: &[u8],
177) -> Result<(), Error> {
178 let y: PublicKey = hash_to_curve(msg)?;
180
181 let expected_unblinded_message: PublicKey = y
183 .mul_tweak(&Secp256k1::new(), &Scalar::from(*a.deref()))?
184 .into();
185
186 if unblinded_message == expected_unblinded_message {
188 return Ok(());
189 }
190
191 Err(Error::TokenNotVerified)
192}
193
194#[cfg(test)]
195mod tests {
196 use std::str::FromStr;
197
198 use super::*;
199
200 #[test]
201 fn test_hash_to_curve() {
202 let secret = "0000000000000000000000000000000000000000000000000000000000000000";
203 let sec_hex = hex::decode(secret).unwrap();
204
205 let y = hash_to_curve(&sec_hex).unwrap();
206 let expected_y = PublicKey::from_hex(
207 "024cce997d3b518f739663b757deaec95bcd9473c30a14ac2fd04023a739d1a725",
208 )
209 .unwrap();
210 assert_eq!(y, expected_y);
211
212 let secret = "0000000000000000000000000000000000000000000000000000000000000001";
213 let sec_hex = hex::decode(secret).unwrap();
214 let y = hash_to_curve(&sec_hex).unwrap();
215 let expected_y = PublicKey::from_hex(
216 "022e7158e11c9506f1aa4248bf531298daa7febd6194f003edcd9b93ade6253acf",
217 )
218 .unwrap();
219 assert_eq!(y, expected_y);
220 let secret = "0000000000000000000000000000000000000000000000000000000000000002";
223 let sec_hex = hex::decode(secret).unwrap();
224 let y = hash_to_curve(&sec_hex).unwrap();
225 let expected_y = PublicKey::from_hex(
226 "026cdbe15362df59cd1dd3c9c11de8aedac2106eca69236ecd9fbe117af897be4f",
227 )
228 .unwrap();
229 assert_eq!(y, expected_y);
230 }
231
232 #[test]
233 fn test_hash_e() {
234 let c = PublicKey::from_str(
235 "02a9acc1e48c25eeeb9289b5031cc57da9fe72f3fe2861d264bdc074209b107ba2",
236 )
237 .unwrap();
238
239 let k = PublicKey::from_str(
240 "020000000000000000000000000000000000000000000000000000000000000001",
241 )
242 .unwrap();
243
244 let r1 = PublicKey::from_str(
245 "020000000000000000000000000000000000000000000000000000000000000001",
246 )
247 .unwrap();
248
249 let r2 = PublicKey::from_str(
250 "020000000000000000000000000000000000000000000000000000000000000001",
251 )
252 .unwrap();
253
254 let e = hash_e(vec![r1, r2, k, c]);
255 let e_hex = hex::encode(e);
256
257 assert_eq!(
258 "a4dc034b74338c28c6bc3ea49731f2a24440fc7c4affc08b31a93fc9fbe6401e",
259 e_hex
260 )
261 }
262
263 #[test]
264 fn test_blind_message() {
265 let message =
266 hex::decode("d341ee4871f1f889041e63cf0d3823c713eea6aff01e80f1719f08f9e5be98f6")
267 .unwrap();
268 let sec: SecretKey =
269 SecretKey::from_hex("99fce58439fc37412ab3468b73db0569322588f62fb3a49182d67e23d877824a")
270 .unwrap();
271
272 let (b, r) = blind_message(&message, Some(sec.clone())).unwrap();
273
274 assert_eq!(sec, r);
275 assert_eq!(
276 b,
277 PublicKey::from_hex(
278 "033b1a9737a40cc3fd9b6af4b723632b76a67a36782596304612a6c2bfb5197e6d"
279 )
280 .unwrap()
281 );
282
283 let message =
284 hex::decode("f1aaf16c2239746f369572c0784d9dd3d032d952c2d992175873fb58fae31a60")
285 .unwrap();
286 let sec: SecretKey =
287 SecretKey::from_hex("f78476ea7cc9ade20f9e05e58a804cf19533f03ea805ece5fee88c8e2874ba50")
288 .unwrap();
289
290 let (b, r) = blind_message(&message, Some(sec.clone())).unwrap();
291
292 assert_eq!(sec, r);
293 assert_eq!(
294 b,
295 PublicKey::from_hex(
296 "029bdf2d716ee366eddf599ba252786c1033f47e230248a4612a5670ab931f1763"
297 )
298 .unwrap()
299 );
300 }
301
302 #[test]
303 fn test_unblind_message() {
304 let blinded_key = PublicKey::from_hex(
305 "02a9acc1e48c25eeeb9289b5031cc57da9fe72f3fe2861d264bdc074209b107ba2",
306 )
307 .unwrap();
308
309 let r =
310 SecretKey::from_hex("0000000000000000000000000000000000000000000000000000000000000001")
311 .unwrap();
312 let a = PublicKey::from_hex(
313 "020000000000000000000000000000000000000000000000000000000000000001",
314 )
315 .unwrap();
316
317 let unblinded = unblind_message(&blinded_key, &r, &a).unwrap();
318
319 assert_eq!(
320 PublicKey::from_hex(
321 "03c724d7e6a5443b39ac8acf11f40420adc4f99a02e7cc1b57703d9391f6d129cd"
322 )
323 .unwrap(),
324 unblinded
325 );
326 }
327
328 #[test]
329 fn test_sign_message() {
330 use super::*;
331 let message = "test_message";
332 let sec =
333 SecretKey::from_hex("0000000000000000000000000000000000000000000000000000000000000001")
334 .unwrap();
335
336 let (blinded_message, _r) = blind_message(message.as_bytes(), Some(sec)).unwrap();
337 let bob_sec =
339 SecretKey::from_hex("0000000000000000000000000000000000000000000000000000000000000001")
340 .unwrap();
341
342 let signed = sign_message(&bob_sec, &blinded_message).unwrap();
344
345 assert_eq!(
346 signed,
347 PublicKey::from_hex(
348 "025cc16fe33b953e2ace39653efb3e7a7049711ae1d8a2f7a9108753f1cdea742b"
349 )
350 .unwrap()
351 );
352
353 let bob_sec =
355 SecretKey::from_hex("7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f")
356 .unwrap();
357
358 let signed = sign_message(&bob_sec, &blinded_message).unwrap();
360
361 assert_eq!(
362 signed,
363 PublicKey::from_hex(
364 "027726f0e5757b4202a27198369a3477a17bc275b7529da518fc7cb4a1d927cc0d"
365 )
366 .unwrap()
367 );
368 }
369
370 #[test]
371 fn test_full_bhke() {
372 let message =
373 hex::decode("d341ee4871f1f889041e63cf0d3823c713eea6aff01e80f1719f08f9e5be98f6")
374 .unwrap();
375 let alice_sec: SecretKey =
376 SecretKey::from_hex("99fce58439fc37412ab3468b73db0569322588f62fb3a49182d67e23d877824a")
377 .unwrap();
378
379 let (b, r) = blind_message(&message, Some(alice_sec.clone())).unwrap();
380
381 let bob_sec =
382 SecretKey::from_hex("0000000000000000000000000000000000000000000000000000000000000001")
383 .unwrap();
384
385 let signed = sign_message(&bob_sec, &b).unwrap();
387
388 let unblinded = unblind_message(&signed, &r, &bob_sec.public_key()).unwrap();
389
390 assert!(verify_message(&bob_sec, unblinded, &message).is_ok());
391 }
392
393 #[test]
402 fn test_verify_message_wrong_key() {
403 let message = b"test message";
405 let correct_key =
406 SecretKey::from_hex("0000000000000000000000000000000000000000000000000000000000000001")
407 .unwrap();
408 let wrong_key =
409 SecretKey::from_hex("0000000000000000000000000000000000000000000000000000000000000002")
410 .unwrap();
411
412 let (blinded, r) = blind_message(message, None).unwrap();
413 let signed = sign_message(&correct_key, &blinded).unwrap();
414 let unblinded = unblind_message(&signed, &r, &correct_key.public_key()).unwrap();
415
416 assert!(verify_message(&wrong_key, unblinded, message).is_err());
418 }
419
420 #[test]
430 fn test_verify_message_wrong_message() {
431 let message = b"test message";
433 let wrong_message = b"wrong message";
434 let key =
435 SecretKey::from_hex("0000000000000000000000000000000000000000000000000000000000000001")
436 .unwrap();
437
438 let (blinded, r) = blind_message(message, None).unwrap();
439 let signed = sign_message(&key, &blinded).unwrap();
440 let unblinded = unblind_message(&signed, &r, &key.public_key()).unwrap();
441
442 assert!(verify_message(&key, unblinded, wrong_message).is_err());
444 }
445
446 #[test]
457 fn test_construct_proofs_length_mismatch() {
458 use std::collections::BTreeMap;
459
460 use crate::nuts::nut02::Id;
461 use crate::Amount;
462
463 let mut keys_map = BTreeMap::new();
465 keys_map.insert(Amount::from(1), SecretKey::generate().public_key());
466 let keys = Keys::new(keys_map);
467
468 let promise = BlindSignature {
470 amount: Amount::from(1),
471 c: SecretKey::generate().public_key(),
472 keyset_id: Id::from_str("00deadbeef123456").unwrap(),
473 dleq: None,
474 };
475 let promises = vec![promise];
476 let rs = vec![SecretKey::generate(), SecretKey::generate()]; let secrets = vec![Secret::from_str("test").unwrap()];
478
479 let result = construct_proofs(promises, rs, secrets, &keys);
480 assert!(result.is_err());
481 }
482
483 #[test]
495 fn test_construct_proofs_returns_correct_count() {
496 use std::collections::BTreeMap;
497
498 use crate::nuts::nut02::Id;
499 use crate::Amount;
500
501 let secret_key = SecretKey::generate();
503 let mut keys_map = BTreeMap::new();
504 keys_map.insert(Amount::from(1), secret_key.public_key());
505 let keys = Keys::new(keys_map);
506
507 let secret = Secret::from_str("test").unwrap();
508 let (blinded_message, r) = blind_message(secret.as_bytes(), None).unwrap();
509 let signature = sign_message(&secret_key, &blinded_message).unwrap();
510
511 let promise = BlindSignature {
512 amount: Amount::from(1),
513 c: signature,
514 keyset_id: Id::from_str("00deadbeef123456").unwrap(),
515 dleq: None,
516 };
517
518 let promises = vec![promise.clone(), promise.clone()];
519 let rs = vec![r.clone(), r];
520 let secrets = vec![secret.clone(), secret];
521
522 let proofs = construct_proofs(promises, rs, secrets, &keys).unwrap();
523
524 assert_eq!(proofs.len(), 2);
526 }
527
528 #[test]
540 fn test_hash_to_curve_counter_increments() {
541 let secret = "0000000000000000000000000000000000000000000000000000000000000002";
544 let sec_hex = hex::decode(secret).unwrap();
545
546 let result = hash_to_curve(&sec_hex);
547 assert!(result.is_ok(), "hash_to_curve should find a valid point");
548
549 let y = result.unwrap();
550 let expected_y = PublicKey::from_hex(
551 "026cdbe15362df59cd1dd3c9c11de8aedac2106eca69236ecd9fbe117af897be4f",
552 )
553 .unwrap();
554 assert_eq!(y, expected_y);
555 }
556}