scicrypt_he/cryptosystems/
rsa.rs1use scicrypt_bigint::UnsignedInteger;
2use scicrypt_numbertheory::gen_rsa_modulus;
3use scicrypt_traits::cryptosystems::{
4 Associable, AsymmetricCryptosystem, DecryptionKey, EncryptionKey, SigningKey, VerificationKey,
5};
6use scicrypt_traits::homomorphic::HomomorphicMultiplication;
7use scicrypt_traits::randomness::GeneralRng;
8use scicrypt_traits::randomness::SecureRng;
9use scicrypt_traits::security::BitsOfSecurity;
10use serde::{Deserialize, Serialize};
11
12#[derive(Copy, Clone)]
14pub struct Rsa {
15 modulus_size: u32,
16}
17
18#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)]
20pub struct RsaPK {
21 pub n: UnsignedInteger,
23 pub e: UnsignedInteger,
25}
26
27pub struct RsaSK {
29 d: UnsignedInteger,
30}
31
32#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)]
34pub struct RsaCiphertext {
35 pub c: UnsignedInteger,
37}
38
39impl Associable<RsaPK> for RsaCiphertext {}
40
41impl AsymmetricCryptosystem for Rsa {
42 type PublicKey = RsaPK;
43 type SecretKey = RsaSK;
44
45 fn setup(security_param: &BitsOfSecurity) -> Self {
46 Rsa {
47 modulus_size: security_param.to_public_key_bit_length(),
48 }
49 }
50
51 fn generate_keys<R: SecureRng>(&self, rng: &mut GeneralRng<R>) -> (RsaPK, RsaSK) {
52 let (n, lambda) = gen_rsa_modulus(self.modulus_size, rng);
53
54 let e = UnsignedInteger::new(65537, 17);
55 let d = e
56 .clone()
57 .invert_leaky(&lambda)
58 .expect("e should always be invertible mod lambda.");
59
60 (RsaPK { n, e }, RsaSK { d })
61 }
62}
63
64impl EncryptionKey for RsaPK {
65 type Input = UnsignedInteger;
66 type Plaintext = UnsignedInteger;
67 type Ciphertext = RsaCiphertext;
68 type Randomness = UnsignedInteger;
69
70 fn encrypt_raw<R: SecureRng>(
71 &self,
72 plaintext: &UnsignedInteger,
73 _rng: &mut GeneralRng<R>,
74 ) -> Self::Ciphertext {
75 self.encrypt_without_randomness(plaintext)
76 }
77
78 fn encrypt_without_randomness(&self, plaintext: &Self::Plaintext) -> Self::Ciphertext {
79 RsaCiphertext {
80 c: plaintext.pow_mod(&self.e, &self.n),
81 }
82 }
83
84 fn randomize<R: SecureRng>(
85 &self,
86 _ciphertext: Self::Ciphertext,
87 _rng: &mut GeneralRng<R>,
88 ) -> Self::Ciphertext {
89 panic!("Not possible to randomize Rsa ciphertext")
90 }
91
92 fn randomize_with(
93 &self,
94 _ciphertext: Self::Ciphertext,
95 _randomness: &Self::Randomness,
96 ) -> Self::Ciphertext {
97 panic!("Not possible to randomize Rsa ciphertext")
98 }
99}
100
101impl DecryptionKey<RsaPK> for RsaSK {
102 fn decrypt_raw(&self, public_key: &RsaPK, ciphertext: &RsaCiphertext) -> UnsignedInteger {
103 ciphertext.c.pow_mod(&self.d, &public_key.n)
104 }
105
106 fn decrypt_identity_raw(
107 &self,
108 public_key: &RsaPK,
109 ciphertext: &<RsaPK as EncryptionKey>::Ciphertext,
110 ) -> bool {
111 self.decrypt_raw(public_key, ciphertext) == UnsignedInteger::from(1u64)
113 }
114}
115
116impl HomomorphicMultiplication for RsaPK {
117 fn mul(
118 &self,
119 ciphertext_a: &Self::Ciphertext,
120 ciphertext_b: &Self::Ciphertext,
121 ) -> Self::Ciphertext {
122 RsaCiphertext {
123 c: (&ciphertext_a.c * &ciphertext_b.c) % &self.n,
124 }
125 }
126
127 fn pow(&self, ciphertext: &Self::Ciphertext, input: &Self::Input) -> Self::Ciphertext {
128 RsaCiphertext {
129 c: ciphertext.c.pow_mod(input, &self.n),
130 }
131 }
132}
133#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)]
135pub struct RsaSignature {
136 pub s: UnsignedInteger,
138}
139
140impl VerificationKey for RsaPK {
141 type Plaintext = UnsignedInteger;
142 type Signature = RsaSignature;
143
144 fn verify(&self, signature: &Self::Signature, plaintext: &Self::Plaintext) -> bool {
145 signature.s.pow_mod(&self.e, &self.n) == *plaintext
146 }
147}
148
149impl SigningKey<RsaPK> for RsaSK {
150 fn sign<R: SecureRng>(
151 &self,
152 plaintext: &<RsaPK as VerificationKey>::Plaintext,
153 public_key: &RsaPK,
154 _rng: &mut GeneralRng<R>,
155 ) -> RsaSignature {
156 RsaSignature {
157 s: plaintext.pow_mod(&self.d, &public_key.n),
158 }
159 }
160}
161
162#[cfg(test)]
163mod tests {
164 use crate::cryptosystems::rsa::Rsa;
165 use rand_core::OsRng;
166 use scicrypt_bigint::UnsignedInteger;
167 use scicrypt_traits::cryptosystems::{
168 AsymmetricCryptosystem, DecryptionKey, EncryptionKey, SigningKey, VerificationKey,
169 };
170 use scicrypt_traits::randomness::GeneralRng;
171 use scicrypt_traits::security::BitsOfSecurity;
172
173 #[test]
174 fn test_encrypt_decrypt_generator() {
175 let mut rng = GeneralRng::new(OsRng);
176
177 let rsa = Rsa::setup(&BitsOfSecurity::ToyParameters);
178 let (pk, sk) = rsa.generate_keys(&mut rng);
179
180 let ciphertext = pk.encrypt(&UnsignedInteger::from(15u64), &mut rng);
181
182 assert_eq!(UnsignedInteger::from(15u64), sk.decrypt(&ciphertext));
183 }
184
185 #[test]
186 fn test_encrypt_decrypt_identity() {
187 let mut rng = GeneralRng::new(OsRng);
188
189 let rsa = Rsa::setup(&BitsOfSecurity::ToyParameters);
190 let (pk, sk) = rsa.generate_keys(&mut rng);
191
192 let ciphertext = pk.encrypt(&UnsignedInteger::from(1), &mut rng);
193
194 assert!(sk.decrypt_identity(&ciphertext));
195 }
196
197 #[test]
198 fn test_homomorphic_mul() {
199 let mut rng = GeneralRng::new(OsRng);
200
201 let rsa = Rsa::setup(&BitsOfSecurity::ToyParameters);
202 let (pk, sk) = rsa.generate_keys(&mut rng);
203
204 let ciphertext_a = pk.encrypt(&UnsignedInteger::from(7u64), &mut rng);
205 let ciphertext_b = pk.encrypt(&UnsignedInteger::from(7u64), &mut rng);
206 let ciphertext_twice = &ciphertext_a * &ciphertext_b;
207
208 assert_eq!(UnsignedInteger::from(49u64), sk.decrypt(&ciphertext_twice));
209 }
210
211 #[test]
212 fn test_homomorphic_scalar_pow() {
213 let mut rng = GeneralRng::new(OsRng);
214
215 let rsa = Rsa::setup(&BitsOfSecurity::ToyParameters);
216 let (pk, sk) = rsa.generate_keys(&mut rng);
217
218 let ciphertext = pk.encrypt(&UnsignedInteger::from(9u64), &mut rng);
219 let ciphertext_twice = ciphertext.pow(&UnsignedInteger::from(4u64));
220
221 assert_eq!(
222 UnsignedInteger::from(6561u64),
223 sk.decrypt(&ciphertext_twice)
224 );
225 }
226
227 #[test]
228 fn test_signature_verification() {
229 let mut rng = GeneralRng::new(OsRng);
230
231 let rsa = Rsa::setup(&BitsOfSecurity::ToyParameters);
232 let (pk, sk) = rsa.generate_keys(&mut rng);
233 let plaintext = UnsignedInteger::from(10u64);
234
235 let signature = sk.sign(&plaintext, &pk, &mut rng);
236
237 assert!(pk.verify(&signature, &plaintext));
238 }
239
240 #[test]
241 fn test_signature_verification_incorrect() {
242 let mut rng = GeneralRng::new(OsRng);
243
244 let rsa = Rsa::setup(&BitsOfSecurity::ToyParameters);
245 let (pk, sk) = rsa.generate_keys(&mut rng);
246 let plaintext = UnsignedInteger::from(10u64);
247
248 let signature = sk.sign(&plaintext, &pk, &mut rng);
249
250 assert!(!pk.verify(&signature, &UnsignedInteger::from(11u64)));
251 }
252}