1use num_bigint::{BigInt, BigUint};
2use num_traits::{One, Signed, Zero};
3use rand::thread_rng;
4use rsa::traits::{PrivateKeyParts, PublicKeyParts};
5use rsa::{RsaPrivateKey, RsaPublicKey};
6use sha2::{Digest, Sha256};
7
8use crate::error::{EcashError, Result};
9
10pub struct BlindSigner {
11 private_key: RsaPrivateKey,
12 public_key: RsaPublicKey,
13}
14
15impl BlindSigner {
16 pub fn new(bits: usize) -> Result<Self> {
17 let mut rng = thread_rng();
18 let private_key =
19 RsaPrivateKey::new(&mut rng, bits).map_err(|_| EcashError::CryptoError)?;
20 let public_key = private_key.to_public_key();
21
22 Ok(Self {
23 private_key,
24 public_key,
25 })
26 }
27
28 pub fn from_keys(private_key: RsaPrivateKey) -> Self {
29 let public_key = private_key.to_public_key();
30 Self {
31 private_key,
32 public_key,
33 }
34 }
35
36 pub fn public_key(&self) -> &RsaPublicKey {
37 &self.public_key
38 }
39
40 pub fn sign_blinded(&self, blinded_message: &BigUint) -> Result<BigUint> {
41 let n = self.private_key.n();
42 let n_big = BigUint::from_bytes_be(&n.to_bytes_be());
43 let d = self.private_key.d();
44 let d_big = BigUint::from_bytes_be(&d.to_bytes_be());
45
46 Ok(blinded_message.modpow(&d_big, &n_big))
47 }
48}
49
50pub struct BlindUser {
51 public_key: RsaPublicKey,
52}
53
54impl BlindUser {
55 pub fn new(public_key: RsaPublicKey) -> Self {
56 Self { public_key }
57 }
58
59 pub fn blind_message(&self, message: &[u8]) -> Result<(BigUint, BigUint)> {
60 let n = self.public_key.n();
61 let n_big = BigUint::from_bytes_be(&n.to_bytes_be());
62 let e = self.public_key.e();
63 let e_big = BigUint::from_bytes_be(&e.to_bytes_be());
64
65 let mut hasher = Sha256::new();
66 hasher.update(message);
67 let m = BigUint::from_bytes_be(&hasher.finalize());
68
69 let r = loop {
70 let bytes: Vec<u8> = (0..n.to_bytes_be().len())
71 .map(|_| rand::random::<u8>())
72 .collect();
73 let candidate = BigUint::from_bytes_be(&bytes) % &n_big;
74 if candidate > BigUint::one() && Self::gcd(&candidate, &n_big) == BigUint::one() {
75 break candidate;
76 }
77 };
78
79 let r_e = r.modpow(&e_big, &n_big);
80 let blinded = (&m * &r_e) % &n_big;
81
82 Ok((blinded, r))
83 }
84
85 pub fn unblind_signature(
86 &self,
87 blind_signature: &BigUint,
88 blinding_factor: &BigUint,
89 ) -> Result<BigUint> {
90 let n = self.public_key.n();
91 let n_big = BigUint::from_bytes_be(&n.to_bytes_be());
92
93 let r_inv = Self::mod_inverse(blinding_factor, &n_big).ok_or(EcashError::BlindingFailed)?;
94
95 Ok((blind_signature * r_inv) % &n_big)
96 }
97
98 pub fn verify_signature(&self, message: &[u8], signature: &BigUint) -> bool {
99 let n = self.public_key.n();
100 let n_big = BigUint::from_bytes_be(&n.to_bytes_be());
101 let e = self.public_key.e();
102 let e_big = BigUint::from_bytes_be(&e.to_bytes_be());
103
104 let mut hasher = Sha256::new();
105 hasher.update(message);
106 let m = BigUint::from_bytes_be(&hasher.finalize());
107
108 let verified = signature.modpow(&e_big, &n_big);
109 verified == m
110 }
111
112 fn gcd(a: &BigUint, b: &BigUint) -> BigUint {
113 let mut a = a.clone();
114 let mut b = b.clone();
115 while b != BigUint::zero() {
116 let temp = b.clone();
117 b = &a % &b;
118 a = temp;
119 }
120 a
121 }
122
123 fn mod_inverse(a: &BigUint, n: &BigUint) -> Option<BigUint> {
124 let a_int = BigInt::from_bytes_be(num_bigint::Sign::Plus, &a.to_bytes_be());
125 let n_int = BigInt::from_bytes_be(num_bigint::Sign::Plus, &n.to_bytes_be());
126
127 let (g, x, _) = Self::extended_gcd(&a_int, &n_int);
128
129 if g != BigInt::one() {
130 return None;
131 }
132
133 let result = if x.is_negative() {
134 (x + &n_int) % &n_int
135 } else {
136 x % &n_int
137 };
138
139 Some(BigUint::from_bytes_be(&result.to_bytes_be().1))
140 }
141
142 fn extended_gcd(a: &BigInt, b: &BigInt) -> (BigInt, BigInt, BigInt) {
143 if b.is_zero() {
144 return (a.clone(), BigInt::one(), BigInt::zero());
145 }
146
147 let (g, x1, y1) = Self::extended_gcd(b, &(a % b));
148 let x = y1.clone();
149 let y = x1 - (a / b) * y1;
150
151 (g, x, y)
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158
159 #[test]
160 fn test_blind_signature_flow() {
161 let signer = BlindSigner::new(2048).unwrap();
162 let user = BlindUser::new(signer.public_key().clone());
163
164 let message = b"test message";
165
166 let (blinded, blinding_factor) = user.blind_message(message).unwrap();
167 let blind_sig = signer.sign_blinded(&blinded).unwrap();
168 let signature = user
169 .unblind_signature(&blind_sig, &blinding_factor)
170 .unwrap();
171
172 assert!(user.verify_signature(message, &signature));
173 }
174}