scicrypt_traits/cryptosystems.rs
1use crate::randomness::GeneralRng;
2use crate::randomness::SecureRng;
3use crate::security::BitsOfSecurity;
4use std::fmt::Debug;
5
6/// An asymmetric cryptosystem is a system of methods to encrypt plaintexts into ciphertexts, and
7/// decrypt those ciphertexts back into plaintexts. Anyone who has access to the public key can
8/// perform encryptions, but only those with the secret key can decrypt.
9///
10/// The struct that implements an `AsymmetricCryptosystem` will hold the general parameters of that
11/// cryptosystem. Depending on the cryptosystem, those parameters could play an important role in
12/// deciding the level of security. As such, each cryptosystem should clearly indicate these.
13pub trait AsymmetricCryptosystem {
14 /// The public key, used for encrypting plaintexts.
15 type PublicKey: EncryptionKey;
16 /// The secret key, used for decrypting ciphertexts.
17 type SecretKey: DecryptionKey<Self::PublicKey>;
18
19 /// Sets up an instance of this cryptosystem with parameters satisfying the security parameter.
20 fn setup(security_parameter: &BitsOfSecurity) -> Self;
21
22 /// Generate a public and private key pair using a cryptographic RNG. The level of security is
23 /// determined by the computational `security_parameter`.
24 fn generate_keys<R: SecureRng>(
25 &self,
26 rng: &mut GeneralRng<R>,
27 ) -> (Self::PublicKey, Self::SecretKey);
28}
29
30/// The encryption key.
31pub trait EncryptionKey: Sized + Debug + PartialEq {
32 /// Input is the type used to multiply additive ciphertexts or exponentiate multiplicative ciphertexts.
33 type Input;
34
35 /// The type of the plaintext to be encrypted.
36 type Plaintext;
37
38 /// The type of an encrypted plaintext, i.e. a ciphertext.
39 type Ciphertext: Associable<Self>;
40
41 /// The type of the randomness used.
42 type Randomness;
43
44 /// Encrypt the plaintext using the public key and a cryptographic RNG and immediately associate it with the public key.
45 fn encrypt<'pk, R: SecureRng>(
46 &'pk self,
47 plaintext: &Self::Plaintext,
48 rng: &mut GeneralRng<R>,
49 ) -> AssociatedCiphertext<'pk, Self::Ciphertext, Self> {
50 self.encrypt_raw(plaintext, rng).associate(self)
51 }
52
53 /// Encrypt the plaintext using the public key and a cryptographic RNG.
54 fn encrypt_raw<R: SecureRng>(
55 &self,
56 plaintext: &Self::Plaintext,
57 rng: &mut GeneralRng<R>,
58 ) -> Self::Ciphertext {
59 let message = self.encrypt_without_randomness(plaintext);
60
61 self.randomize(message, rng)
62 }
63
64 /// **WARNING: This is not a full encryption. The resulting ciphertext is completely insecure.** 'Encrypts' the plaintext using the public key deterministically, essentially creating a trivial ciphertext. The encryption is not secure until you call `randomize` or `randomize_with` with suitable randomness.
65 fn encrypt_without_randomness(&self, plaintext: &Self::Plaintext) -> Self::Ciphertext;
66
67 /// Randomizes the ciphertext with the supplied rng.
68 fn randomize<R: SecureRng>(
69 &self,
70 ciphertext: Self::Ciphertext,
71 rng: &mut GeneralRng<R>,
72 ) -> Self::Ciphertext;
73
74 /// Randomizes the ciphertext with the user supplied randomness.
75 fn randomize_with(
76 &self,
77 ciphertext: Self::Ciphertext,
78 randomness: &Self::Randomness,
79 ) -> Self::Ciphertext;
80}
81
82/// The decryption key.
83pub trait DecryptionKey<PK: EncryptionKey> {
84 /// Decrypt the associated ciphertext using the secret key.
85 fn decrypt<'pk>(
86 &self,
87 ciphertext: &AssociatedCiphertext<'pk, PK::Ciphertext, PK>,
88 ) -> PK::Plaintext {
89 self.decrypt_raw(ciphertext.public_key, &ciphertext.ciphertext)
90 }
91
92 /// Returns true if the associated ciphertext encrypts the identity. This is typically faster than a full decryption.
93 fn decrypt_identity<'pk>(
94 &self,
95 ciphertext: &AssociatedCiphertext<'pk, PK::Ciphertext, PK>,
96 ) -> bool {
97 self.decrypt_identity_raw(ciphertext.public_key, &ciphertext.ciphertext)
98 }
99
100 /// Decrypt the ciphertext using the secret key and its related public key.
101 fn decrypt_raw(&self, public_key: &PK, ciphertext: &PK::Ciphertext) -> PK::Plaintext;
102
103 /// Returns true if the encrypted value equals the identity. This is typically faster than a full decryption.
104 fn decrypt_identity_raw(&self, public_key: &PK, ciphertext: &PK::Ciphertext) -> bool;
105}
106
107#[derive(PartialEq, Eq, Debug)]
108/// An AssociatedCiphertext associates a ciphertext with a reference to the corresponding public key to make homomorphic operations and decrypting more ergonomic.
109pub struct AssociatedCiphertext<'pk, C: Associable<PK>, PK: EncryptionKey<Ciphertext = C>> {
110 /// A potentially homomorphic ciphertext
111 pub ciphertext: C,
112 /// The related public key
113 pub public_key: &'pk PK,
114}
115
116/// Functionality to easily turn a ciphertext into an associated ciphertext
117pub trait Associable<PK: EncryptionKey<Ciphertext = Self>>: Sized {
118 /// 'Enriches' a ciphertext by associating it with a corresponding public key. This allows to overlead operators for homomorphic operations.
119 fn associate(self, public_key: &PK) -> AssociatedCiphertext<'_, Self, PK> {
120 AssociatedCiphertext {
121 ciphertext: self,
122 public_key,
123 }
124 }
125}
126
127/// The Verification key.
128pub trait VerificationKey {
129 /// The type of the plaintext to be signed.
130 type Plaintext;
131
132 /// The type of a signature.
133 type Signature;
134
135 /// Verify the Signature on the plaintext message using the (public) Verification key.
136 fn verify(&self, signature: &Self::Signature, plaintext: &Self::Plaintext) -> bool;
137}
138
139/// The Signing key.
140pub trait SigningKey<VK: VerificationKey> {
141 /// Sign the plaintext message using the (secret) Signing key.
142 fn sign<R: SecureRng>(
143 &self,
144 plaintext: &VK::Plaintext,
145 public_key: &VK,
146 rng: &mut GeneralRng<R>,
147 ) -> VK::Signature;
148}