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}