dhke.rs 8.6 KB

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