1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use crate::cryptosystems::{AssociatedCiphertext, EncryptionKey};
use crate::randomness::GeneralRng;
use crate::randomness::SecureRng;
use crate::security::BitsOfSecurity;
use crate::DecryptionError;

/// An asymmetric threshold cryptosystem is a system of methods to encrypt plaintexts into
/// ciphertexts, but instead of having a single secret key to decrypt them back into plaintexts, we
/// require a given number of parties to decrypt with their own partial key. If enough parties
/// partially decrypt, the resulting shares can be combined into the original plaintext. Still,
/// anyone who has access to the public key can perform encryptions.
///
/// We denote a threshold cryptosystem using a tuple like (t, n). This means that t parties can
/// collectively decrypt, and that there are in total n partial keys. In this special case, all n
/// keys must be used to decrypt.
///
/// The struct that implements an `NOfNCryptosystem` will hold the general parameters
/// of that cryptosystem. Depending on the cryptosystem, those parameters could play an important
/// role in deciding the level of security. As such, each cryptosystem should clearly indicate
/// these.
pub trait NOfNCryptosystem {
    /// The public key used to encrypt plaintexts.
    type PublicKey: EncryptionKey;
    /// The secret key used to partially decrypt ciphertexts.
    type SecretKey: PartialDecryptionKey<Self::PublicKey>;

    /// Sets up an instance of this cryptosystem with parameters satisfying the security parameter.
    fn setup(security_parameter: &BitsOfSecurity) -> Self;

    /// Generate a public key, and $n$ secret keys using a cryptographic RNG.
    fn generate_keys<R: SecureRng>(
        &self,
        key_count_n: usize,
        rng: &mut GeneralRng<R>,
    ) -> (Self::PublicKey, Vec<Self::SecretKey>);
}

/// A partial decryption key partially decrypts ciphertexts to return a decryption share. If enough decryption shares of different keys are combined, they output the correct decryption.
pub trait PartialDecryptionKey<PK: EncryptionKey> {
    /// The type of the decryption share. If enough decryption shares of different keys are combined, they output the correct decryption.
    type DecryptionShare: DecryptionShare<PK>;

    /// Partially decrypts a ciphertext, returning a valid decryption share.
    fn partial_decrypt<'pk>(
        &self,
        ciphertext: &AssociatedCiphertext<'pk, PK::Ciphertext, PK>,
    ) -> Self::DecryptionShare {
        self.partial_decrypt_raw(ciphertext.public_key, &ciphertext.ciphertext)
    }
    /// Partially decrypts a ciphertext, returning a valid decryption share.
    fn partial_decrypt_raw(
        &self,
        public_key: &PK,
        ciphertext: &PK::Ciphertext,
    ) -> Self::DecryptionShare;
}

/// A `DecryptionShare` is the result of decrypting with a partial key. When enough of these shares
/// are combined, they reveal the actual decryption.
pub trait DecryptionShare<PK: EncryptionKey>: Sized {
    /// Combine $t$ decryption shares belonging to distinct partial keys to finish decryption. It is
    /// the responsibility of the programmer to supply the right number of decryption shares to
    /// this function.
    fn combine(
        decryption_shares: &[Self],
        public_key: &PK,
    ) -> Result<PK::Plaintext, DecryptionError>;
}

/// An asymmetric threshold cryptosystem is a system of methods to encrypt plaintexts into
/// ciphertexts, but instead of having a single secret key to decrypt them back into plaintexts, we
/// require a given number of parties to decrypt with their own partial key. If enough parties
/// partially decrypt, the resulting shares can be combined into the original plaintext. Still,
/// anyone who has access to the public key can perform encryptions.
///
/// We denote a threshold cryptosystem using a tuple like (t, n). This means that t parties can
/// collectively decrypt, and that there are in total n partial keys.
///
/// The struct that implements an `TOfNCryptosystem` will hold the general parameters
/// of that cryptosystem. Depending on the cryptosystem, those parameters could play an important
/// role in deciding the level of security. As such, each cryptosystem should clearly indicate
/// these.
pub trait TOfNCryptosystem {
    /// The public key used to encrypt plaintexts.
    type PublicKey: EncryptionKey;
    /// The secret key used to partially decrypt ciphertexts.
    type SecretKey: PartialDecryptionKey<Self::PublicKey>;

    /// Sets up an instance of this cryptosystem with parameters satisfying the security parameter.
    fn setup(security_parameter: &BitsOfSecurity) -> Self;

    /// Generate a public and private key pair using a cryptographic RNG.
    fn generate_keys<R: SecureRng>(
        &self,
        threshold_t: usize,
        key_count_n: usize,
        rng: &mut GeneralRng<R>,
    ) -> (Self::PublicKey, Vec<Self::SecretKey>);
}