dhke.rs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. //! Diffie-Hellmann key exchange
  2. use std::ops::Mul;
  3. use bitcoin_hashes::sha256;
  4. use bitcoin_hashes::Hash;
  5. #[cfg(feature = "wallet")]
  6. use k256::ProjectivePoint;
  7. use k256::{Scalar, SecretKey};
  8. use crate::error;
  9. #[cfg(feature = "wallet")]
  10. use crate::nuts::nut00::{BlindedSignature, Proof, Proofs};
  11. #[cfg(feature = "wallet")]
  12. use crate::nuts::nut01::{Keys, PublicKey};
  13. #[cfg(feature = "wallet")]
  14. use crate::nuts::*;
  15. fn hash_to_curve(message: &[u8]) -> k256::PublicKey {
  16. let mut msg_to_hash = message.to_vec();
  17. loop {
  18. let hash = sha256::Hash::hash(&msg_to_hash);
  19. match k256::PublicKey::from_sec1_bytes(
  20. &[0x02u8]
  21. .iter()
  22. .chain(&hash.to_byte_array())
  23. .cloned()
  24. .collect::<Vec<u8>>(),
  25. ) {
  26. Ok(pubkey) => return pubkey,
  27. Err(_) => msg_to_hash = hash.to_byte_array().to_vec(),
  28. }
  29. }
  30. }
  31. #[cfg(feature = "wallet")]
  32. /// Blind Message Alice Step one
  33. pub fn blind_message(
  34. secret: &[u8],
  35. blinding_factor: Option<SecretKey>,
  36. ) -> Result<(PublicKey, SecretKey), error::wallet::Error> {
  37. let y = hash_to_curve(secret);
  38. let r: SecretKey = match blinding_factor {
  39. Some(sec_key) => sec_key,
  40. None => SecretKey::random(&mut rand::thread_rng()),
  41. };
  42. let b = ProjectivePoint::from(y) + ProjectivePoint::from(&r.public_key());
  43. Ok((k256::PublicKey::try_from(b)?.into(), r))
  44. }
  45. #[cfg(feature = "wallet")]
  46. /// Unblind Message (Alice Step 3)
  47. pub fn unblind_message(
  48. // C_
  49. blinded_key: PublicKey,
  50. r: SecretKey,
  51. // A
  52. mint_pubkey: PublicKey,
  53. ) -> Result<PublicKey, error::wallet::Error> {
  54. // C
  55. // Unblinded message
  56. let c = ProjectivePoint::from(Into::<k256::PublicKey>::into(blinded_key).as_affine())
  57. - Into::<k256::PublicKey>::into(mint_pubkey)
  58. .as_affine()
  59. .mul(Scalar::from(r.as_scalar_primitive()));
  60. Ok(k256::PublicKey::try_from(c)?.into())
  61. }
  62. #[cfg(feature = "wallet")]
  63. /// Construct Proof
  64. pub fn construct_proofs(
  65. promises: Vec<BlindedSignature>,
  66. rs: Vec<nut01::SecretKey>,
  67. secrets: Vec<String>,
  68. keys: &Keys,
  69. ) -> Result<Proofs, error::wallet::Error> {
  70. let mut proofs = vec![];
  71. for (i, promise) in promises.into_iter().enumerate() {
  72. let blinded_c = promise.c;
  73. let a: PublicKey = keys
  74. .amount_key(promise.amount)
  75. .ok_or(error::wallet::Error::CustomError(
  76. "Could not get proofs".to_string(),
  77. ))?
  78. .to_owned();
  79. let unblinded_signature = unblind_message(blinded_c, rs[i].clone().into(), a)?;
  80. let proof = Proof {
  81. id: Some(promise.id),
  82. amount: promise.amount,
  83. secret: secrets[i].clone(),
  84. c: unblinded_signature,
  85. };
  86. proofs.push(proof);
  87. }
  88. Ok(proofs)
  89. }
  90. #[cfg(feature = "mint")]
  91. /// Sign Blinded Message (Step2 bob)
  92. pub fn sign_message(
  93. a: SecretKey,
  94. blinded_message: k256::PublicKey,
  95. ) -> Result<k256::PublicKey, error::mint::Error> {
  96. Ok(k256::PublicKey::try_from(
  97. blinded_message
  98. .as_affine()
  99. .mul(Scalar::from(a.as_scalar_primitive())),
  100. )?)
  101. }
  102. #[cfg(feature = "mint")]
  103. /// Verify Message
  104. pub fn verify_message(
  105. a: SecretKey,
  106. unblinded_message: k256::PublicKey,
  107. msg: &str,
  108. ) -> Result<(), error::mint::Error> {
  109. // Y
  110. let y = hash_to_curve(msg.as_bytes());
  111. if unblinded_message
  112. == k256::PublicKey::try_from(*y.as_affine() * Scalar::from(a.as_scalar_primitive()))?
  113. {
  114. return Ok(());
  115. }
  116. Err(error::mint::Error::TokenNotVerifed)
  117. }
  118. #[cfg(test)]
  119. mod tests {
  120. use hex::decode;
  121. use k256::elliptic_curve::scalar::ScalarPrimitive;
  122. use super::*;
  123. use crate::utils::generate_secret;
  124. #[test]
  125. fn test_hash_to_curve() {
  126. let secret = "0000000000000000000000000000000000000000000000000000000000000000";
  127. let sec_hex = decode(secret).unwrap();
  128. let y = hash_to_curve(&sec_hex);
  129. let expected_y = k256::PublicKey::from_sec1_bytes(
  130. &hex::decode("0266687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925")
  131. .unwrap(),
  132. )
  133. .unwrap();
  134. assert_eq!(y, expected_y);
  135. let secret = "0000000000000000000000000000000000000000000000000000000000000001";
  136. let sec_hex = decode(secret).unwrap();
  137. let y = hash_to_curve(&sec_hex);
  138. let expected_y = k256::PublicKey::from_sec1_bytes(
  139. &hex::decode("02ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5")
  140. .unwrap(),
  141. )
  142. .unwrap();
  143. assert_eq!(y, expected_y);
  144. }
  145. #[test]
  146. fn test_blind_message() {
  147. let message = "test_message";
  148. let sec = SecretKey::new(ScalarPrimitive::ONE);
  149. let (b, r) = blind_message(message.as_bytes(), Some(sec.clone())).unwrap();
  150. assert_eq!(
  151. b,
  152. k256::PublicKey::from_sec1_bytes(
  153. &hex::decode("02a9acc1e48c25eeeb9289b5031cc57da9fe72f3fe2861d264bdc074209b107ba2")
  154. .unwrap()
  155. )
  156. .unwrap()
  157. .into()
  158. );
  159. assert_eq!(r, sec);
  160. }
  161. #[test]
  162. fn test_sign_message() {
  163. let message = "test_message";
  164. let sec = SecretKey::new(ScalarPrimitive::ONE);
  165. let (blinded_message, _r) = blind_message(message.as_bytes(), Some(sec)).unwrap();
  166. // A
  167. let bob_sec = SecretKey::new(ScalarPrimitive::ONE);
  168. // C_
  169. let signed = sign_message(bob_sec, blinded_message.into()).unwrap();
  170. assert_eq!(
  171. signed,
  172. k256::PublicKey::from_sec1_bytes(
  173. &hex::decode("02a9acc1e48c25eeeb9289b5031cc57da9fe72f3fe2861d264bdc074209b107ba2")
  174. .unwrap()
  175. )
  176. .unwrap()
  177. );
  178. }
  179. #[test]
  180. fn test_unblind_message() {
  181. let blinded_key = k256::PublicKey::from_sec1_bytes(
  182. &hex::decode("02a9acc1e48c25eeeb9289b5031cc57da9fe72f3fe2861d264bdc074209b107ba2")
  183. .unwrap(),
  184. )
  185. .unwrap();
  186. let r = SecretKey::new(ScalarPrimitive::ONE);
  187. let a = k256::PublicKey::from_sec1_bytes(
  188. &hex::decode("020000000000000000000000000000000000000000000000000000000000000001")
  189. .unwrap(),
  190. )
  191. .unwrap();
  192. let unblinded = unblind_message(blinded_key.into(), r, a.into()).unwrap();
  193. assert_eq!(
  194. Into::<PublicKey>::into(
  195. k256::PublicKey::from_sec1_bytes(
  196. &hex::decode(
  197. "03c724d7e6a5443b39ac8acf11f40420adc4f99a02e7cc1b57703d9391f6d129cd"
  198. )
  199. .unwrap()
  200. )
  201. .unwrap()
  202. ),
  203. unblinded
  204. );
  205. }
  206. #[ignore]
  207. #[test]
  208. fn test_blinded_dhke() {
  209. // a
  210. let bob_sec = SecretKey::random(&mut rand::thread_rng());
  211. // A
  212. let bob_pub = bob_sec.public_key();
  213. // let alice_sec = SecretKey::random(&mut rand::thread_rng());
  214. let x = generate_secret();
  215. // Y
  216. let y = hash_to_curve(x.as_bytes());
  217. // B_
  218. let blinded = blind_message(&y.to_sec1_bytes(), None).unwrap();
  219. // C_
  220. let signed = sign_message(bob_sec.clone(), blinded.0.into()).unwrap();
  221. // C
  222. let c = unblind_message(signed.into(), blinded.1, bob_pub.into()).unwrap();
  223. assert!(verify_message(bob_sec, c.into(), &x).is_ok());
  224. }
  225. }