dhke.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. //! Diffie-Hellmann key exchange
  2. use bitcoin::hashes::{sha256, Hash};
  3. #[cfg(feature = "mint")]
  4. pub use mint::{sign_message, verify_message};
  5. #[cfg(feature = "wallet")]
  6. pub use wallet::{blind_message, construct_proofs, unblind_message};
  7. use crate::error::Error;
  8. const DOMAIN_SEPARATOR: &[u8; 28] = b"Secp256k1_HashToCurve_Cashu_";
  9. pub fn hash_to_curve(message: &[u8]) -> Result<k256::PublicKey, Error> {
  10. let msg_to_hash = [DOMAIN_SEPARATOR, message].concat();
  11. let msg_hash = sha256::Hash::hash(&msg_to_hash).to_byte_array();
  12. let mut counter = 0;
  13. while counter < 2_u32.pow(16) {
  14. let mut bytes_to_hash = Vec::with_capacity(36);
  15. bytes_to_hash.extend_from_slice(&msg_hash);
  16. bytes_to_hash.extend_from_slice(&counter.to_le_bytes());
  17. let hash = sha256::Hash::hash(&bytes_to_hash);
  18. match k256::PublicKey::from_sec1_bytes(
  19. &[0x02u8]
  20. .iter()
  21. .chain(&hash.to_byte_array())
  22. .cloned()
  23. .collect::<Vec<u8>>(),
  24. ) {
  25. Ok(pubkey) => return Ok(pubkey),
  26. Err(_) => {
  27. counter += 1;
  28. }
  29. }
  30. }
  31. Err(Error::NoValidPoint)
  32. }
  33. #[cfg(feature = "wallet")]
  34. mod wallet {
  35. use std::ops::Mul;
  36. use k256::{ProjectivePoint, Scalar, SecretKey};
  37. use super::hash_to_curve;
  38. use crate::error;
  39. use crate::nuts::{BlindedSignature, Keys, Proof, Proofs, PublicKey, *};
  40. use crate::secret::Secret;
  41. /// Blind Message Alice Step one
  42. pub fn blind_message(
  43. secret: &[u8],
  44. blinding_factor: Option<SecretKey>,
  45. ) -> Result<(PublicKey, SecretKey), error::wallet::Error> {
  46. let y = hash_to_curve(secret)?;
  47. let r: SecretKey = match blinding_factor {
  48. Some(sec_key) => sec_key,
  49. None => SecretKey::random(&mut rand::thread_rng()),
  50. };
  51. let b = ProjectivePoint::from(y) + ProjectivePoint::from(&r.public_key());
  52. Ok((k256::PublicKey::try_from(b)?.into(), r))
  53. }
  54. /// Unblind Message (Alice Step 3)
  55. pub fn unblind_message(
  56. // C_
  57. blinded_key: PublicKey,
  58. r: SecretKey,
  59. // A
  60. mint_pubkey: PublicKey,
  61. ) -> Result<PublicKey, error::wallet::Error> {
  62. // C
  63. // Unblinded message
  64. let c = ProjectivePoint::from(Into::<k256::PublicKey>::into(blinded_key).as_affine())
  65. - Into::<k256::PublicKey>::into(mint_pubkey)
  66. .as_affine()
  67. .mul(Scalar::from(r.as_scalar_primitive()));
  68. Ok(k256::PublicKey::try_from(c)?.into())
  69. }
  70. /// Construct Proof
  71. pub fn construct_proofs(
  72. promises: Vec<BlindedSignature>,
  73. rs: Vec<nut01::SecretKey>,
  74. secrets: Vec<Secret>,
  75. keys: &Keys,
  76. ) -> Result<Proofs, error::wallet::Error> {
  77. let mut proofs = vec![];
  78. for (i, promise) in promises.into_iter().enumerate() {
  79. let blinded_c = promise.c;
  80. let a: PublicKey = keys
  81. .amount_key(promise.amount)
  82. .ok_or(error::wallet::Error::CustomError(
  83. "Could not get proofs".to_string(),
  84. ))?
  85. .to_owned();
  86. let unblinded_signature = unblind_message(blinded_c, rs[i].clone().into(), a)?;
  87. let proof = Proof {
  88. keyset_id: promise.keyset_id,
  89. amount: promise.amount,
  90. secret: secrets[i].clone(),
  91. c: unblinded_signature,
  92. };
  93. proofs.push(proof);
  94. }
  95. Ok(proofs)
  96. }
  97. }
  98. #[cfg(feature = "mint")]
  99. mod mint {
  100. use std::ops::Mul;
  101. use k256::{Scalar, SecretKey};
  102. use super::hash_to_curve;
  103. use crate::error;
  104. use crate::secret::Secret;
  105. /// Sign Blinded Message (Step2 bob)
  106. pub fn sign_message(
  107. a: SecretKey,
  108. blinded_message: k256::PublicKey,
  109. ) -> Result<k256::PublicKey, error::mint::Error> {
  110. Ok(k256::PublicKey::try_from(
  111. blinded_message
  112. .as_affine()
  113. .mul(Scalar::from(a.as_scalar_primitive())),
  114. )?)
  115. }
  116. /// Verify Message
  117. pub fn verify_message(
  118. a: SecretKey,
  119. unblinded_message: k256::PublicKey,
  120. msg: &Secret,
  121. ) -> Result<(), error::mint::Error> {
  122. // Y
  123. let y = hash_to_curve(&msg.to_bytes()?)?;
  124. if unblinded_message
  125. == k256::PublicKey::try_from(*y.as_affine() * Scalar::from(a.as_scalar_primitive()))?
  126. {
  127. return Ok(());
  128. }
  129. Err(error::mint::Error::TokenNotVerifed)
  130. }
  131. }
  132. #[cfg(test)]
  133. mod tests {
  134. use hex::decode;
  135. use k256::elliptic_curve::scalar::ScalarPrimitive;
  136. use super::*;
  137. #[cfg(feature = "wallet")]
  138. mod wallet_tests {
  139. use k256::SecretKey;
  140. use super::*;
  141. use crate::nuts::PublicKey;
  142. #[test]
  143. fn test_hash_to_curve() {
  144. let secret = "0000000000000000000000000000000000000000000000000000000000000000";
  145. let sec_hex = decode(secret).unwrap();
  146. let y = hash_to_curve(&sec_hex).unwrap();
  147. let expected_y = k256::PublicKey::from_sec1_bytes(
  148. &hex::decode("024cce997d3b518f739663b757deaec95bcd9473c30a14ac2fd04023a739d1a725")
  149. .unwrap(),
  150. )
  151. .unwrap();
  152. println!("{}", hex::encode(y.to_sec1_bytes()));
  153. assert_eq!(y, expected_y);
  154. let secret = "0000000000000000000000000000000000000000000000000000000000000001";
  155. let sec_hex = decode(secret).unwrap();
  156. let y = hash_to_curve(&sec_hex).unwrap();
  157. let expected_y = k256::PublicKey::from_sec1_bytes(
  158. &hex::decode("022e7158e11c9506f1aa4248bf531298daa7febd6194f003edcd9b93ade6253acf")
  159. .unwrap(),
  160. )
  161. .unwrap();
  162. println!("{}", hex::encode(y.to_sec1_bytes()));
  163. assert_eq!(y, expected_y);
  164. // Note that this message will take a few iterations of the loop before finding
  165. // a valid point
  166. let secret = "0000000000000000000000000000000000000000000000000000000000000002";
  167. let sec_hex = decode(secret).unwrap();
  168. let y = hash_to_curve(&sec_hex).unwrap();
  169. let expected_y = k256::PublicKey::from_sec1_bytes(
  170. &hex::decode("026cdbe15362df59cd1dd3c9c11de8aedac2106eca69236ecd9fbe117af897be4f")
  171. .unwrap(),
  172. )
  173. .unwrap();
  174. println!("{}", hex::encode(y.to_sec1_bytes()));
  175. assert_eq!(y, expected_y);
  176. }
  177. #[test]
  178. fn test_blind_message() {
  179. let message = "d341ee4871f1f889041e63cf0d3823c713eea6aff01e80f1719f08f9e5be98f6";
  180. let sec: crate::nuts::SecretKey = crate::nuts::SecretKey::from_hex(
  181. "99fce58439fc37412ab3468b73db0569322588f62fb3a49182d67e23d877824a",
  182. )
  183. .unwrap();
  184. let (b, r) =
  185. blind_message(&hex::decode(message).unwrap(), Some(sec.clone().into())).unwrap();
  186. assert_eq!(sec, r.into());
  187. assert_eq!(
  188. b.to_hex(),
  189. PublicKey::from(
  190. k256::PublicKey::from_sec1_bytes(
  191. &hex::decode(
  192. "033b1a9737a40cc3fd9b6af4b723632b76a67a36782596304612a6c2bfb5197e6d"
  193. )
  194. .unwrap()
  195. )
  196. .unwrap()
  197. )
  198. .to_hex()
  199. );
  200. let message = "f1aaf16c2239746f369572c0784d9dd3d032d952c2d992175873fb58fae31a60";
  201. let sec: crate::nuts::SecretKey = crate::nuts::SecretKey::from_hex(
  202. "f78476ea7cc9ade20f9e05e58a804cf19533f03ea805ece5fee88c8e2874ba50",
  203. )
  204. .unwrap();
  205. let (b, r) =
  206. blind_message(&hex::decode(message).unwrap(), Some(sec.clone().into())).unwrap();
  207. assert_eq!(sec, r.into());
  208. assert_eq!(
  209. b.to_hex(),
  210. PublicKey::from(
  211. k256::PublicKey::from_sec1_bytes(
  212. &hex::decode(
  213. "029bdf2d716ee366eddf599ba252786c1033f47e230248a4612a5670ab931f1763"
  214. )
  215. .unwrap()
  216. )
  217. .unwrap()
  218. )
  219. .to_hex()
  220. );
  221. }
  222. #[test]
  223. fn test_unblind_message() {
  224. let blinded_key = k256::PublicKey::from_sec1_bytes(
  225. &hex::decode("02a9acc1e48c25eeeb9289b5031cc57da9fe72f3fe2861d264bdc074209b107ba2")
  226. .unwrap(),
  227. )
  228. .unwrap();
  229. let r = SecretKey::new(ScalarPrimitive::ONE);
  230. let a = k256::PublicKey::from_sec1_bytes(
  231. &hex::decode("020000000000000000000000000000000000000000000000000000000000000001")
  232. .unwrap(),
  233. )
  234. .unwrap();
  235. let unblinded = unblind_message(blinded_key.into(), r, a.into()).unwrap();
  236. assert_eq!(
  237. Into::<PublicKey>::into(
  238. k256::PublicKey::from_sec1_bytes(
  239. &hex::decode(
  240. "03c724d7e6a5443b39ac8acf11f40420adc4f99a02e7cc1b57703d9391f6d129cd"
  241. )
  242. .unwrap()
  243. )
  244. .unwrap()
  245. ),
  246. unblinded
  247. );
  248. }
  249. }
  250. #[cfg(feature = "mint")]
  251. mod mint_test {
  252. use k256::SecretKey;
  253. use super::{hash_to_curve, *};
  254. use crate::secret::Secret;
  255. #[test]
  256. fn test_sign_message() {
  257. use super::*;
  258. let message = "test_message";
  259. let sec = SecretKey::new(ScalarPrimitive::ONE);
  260. let (blinded_message, _r) = blind_message(message.as_bytes(), Some(sec)).unwrap();
  261. // A
  262. let bob_sec = SecretKey::new(ScalarPrimitive::ONE);
  263. // C_
  264. let signed = sign_message(bob_sec, blinded_message.clone().into()).unwrap();
  265. assert_eq!(
  266. signed,
  267. k256::PublicKey::from_sec1_bytes(
  268. &hex::decode(
  269. "025cc16fe33b953e2ace39653efb3e7a7049711ae1d8a2f7a9108753f1cdea742b"
  270. )
  271. .unwrap()
  272. )
  273. .unwrap()
  274. );
  275. // A
  276. let bob_sec = crate::nuts::SecretKey::from_hex(
  277. "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
  278. )
  279. .unwrap();
  280. // C_
  281. let signed = sign_message(bob_sec.into(), blinded_message.into()).unwrap();
  282. assert_eq!(
  283. signed,
  284. k256::PublicKey::from_sec1_bytes(
  285. &hex::decode(
  286. "027726f0e5757b4202a27198369a3477a17bc275b7529da518fc7cb4a1d927cc0d"
  287. )
  288. .unwrap()
  289. )
  290. .unwrap()
  291. );
  292. }
  293. #[ignore]
  294. #[test]
  295. fn test_blinded_dhke() {
  296. // a
  297. let bob_sec = SecretKey::random(&mut rand::thread_rng());
  298. // A
  299. let bob_pub = bob_sec.public_key();
  300. // let alice_sec = SecretKey::random(&mut rand::thread_rng());
  301. let x = Secret::new();
  302. // Y
  303. let y = hash_to_curve(&x.to_bytes().unwrap()).unwrap();
  304. // B_
  305. let blinded = blind_message(&y.to_sec1_bytes(), None).unwrap();
  306. // C_
  307. let signed = sign_message(bob_sec.clone(), blinded.0.into()).unwrap();
  308. // C
  309. let c = unblind_message(signed.into(), blinded.1, bob_pub.into()).unwrap();
  310. assert!(verify_message(bob_sec, c.into(), &x).is_ok());
  311. }
  312. }
  313. }