pailliers module
Minimal pure-Python implementation of Paillier’s additively homomorphic cryptosystem.
- class secret(bit_length: int)[source]
Bases:
Tuple[int,int,int,int]Wrapper class for a tuple of four integers that represents a secret key. The
bit_lengthargument specifies the bit length of each of the two prime integers found in the key. Furthermore, the product of these two primes (i.e., the modulus) is guaranteed to have a bit length that is exactly twice the value ofbit_length.>>> secret_key = secret(2048) >>> public_key = public(secret_key) >>> isinstance(secret_key, secret) True
Any attempt to supply an argument that is of the wrong type or outside the supported range raises an exception.
>>> secret('abc') Traceback (most recent call last): ... TypeError: bit length must be an integer >>> secret(0) Traceback (most recent call last): ... ValueError: bit length must be a positive integer
- class public(secret_key: secret)[source]
-
Wrapper class for a pair of integers that represents a public key.
>>> public_key = public(secret(2048)) >>> isinstance(public_key, public) True
Any attempt to supply an argument that is of the wrong type or outside the supported range raises an exception.
>>> public('abc') Traceback (most recent call last): ... TypeError: secret key required to create public key
- class plain[source]
Bases:
intWrapper class for an integer that represents a plaintext.
>>> isinstance(plain(123), plain) True
- class cipher(integer: int, public_key: Optional[public] = None)[source]
Bases:
intWrapper class for an integer that represents a ciphertext.
>>> secret_key = secret(2048) >>> public_key = public(secret_key) >>> c = encrypt(public_key, plain(123)) >>> isinstance(c, cipher) True
This class defines a number of special methods corresponding to arithmetic operations so that Python’s built-in operators can be used when working with instances of this class. These operators will only work on instances of this class that have been constructed with a public key (which is the default behavior of the
encryptfunction).>>> decrypt(secret_key, c + c) 246 >>> decrypt(secret_key, 2 * c) 246
To facilitate the use of instances that do not maintain internal copies of the same public key (e.g., in cases where memory constraints are an issue or ciphertexts are stored/communicated separately from key information), the
addandmulfunctions can be used.>>> c = cipher(int(c), public_key=public_key) >>> decrypt(secret_key, c + c) 246 >>> n = int(c) >>> c = cipher(n) # This instance has no internal copy of a public key. >>> c + c Traceback (most recent call last): ... ValueError: public key is required for addition >>> decrypt(secret_key, add(public_key, c, c)) 246 >>> decrypt(secret_key, mul(public_key, c, 2)) 246
Warning: When the true integer sum of two encrypted values — or the true product of an encrypted value and an integer scalar — exceeds the modulus within the public key, the decrypted result will not match the true result.
>>> secret_key = secret(8) >>> public_key = public(secret_key) >>> c = encrypt(public_key, 2 ** 7) >>> int(decrypt(secret_key, c)) == 2 ** 7 True >>> int(decrypt(secret_key, c * (2 ** 9))) == (2 ** 7) * (2 ** 9) False
Any attempt to invoke the constructor using arguments that do not have the expected types raises an exception.
>>> cipher('abc', public_key='abc') Traceback (most recent call last): ... ValueError: invalid literal for int() with base 10: 'abc' >>> cipher(123, public_key='abc') Traceback (most recent call last): ... TypeError: public key must be an instance of the public class
- __add__(other: cipher) cipher[source]
Perform addition of encrypted values to produce the encrypted result.
>>> secret_key = secret(2048) >>> public_key = public(secret_key) >>> c = encrypt(public_key, 22) >>> d = encrypt(public_key, 33) >>> r = c + d >>> int(decrypt(secret_key, r)) 55
At least one of the two arguments must have a public key.
>>> decrypt(secret_key, cipher(int(c)) + c) 44 >>> decrypt(secret_key, c + cipher(int(c))) 44 >>> cipher(int(c)) + cipher(int(c)) Traceback (most recent call last): ... ValueError: public key is required for addition
If public keys are specified in both ciphertexts, they must match.
>>> secret_key_a = secret(2048) >>> public_key_a = public(secret_key_a) >>> secret_key_b = secret(2048) >>> public_key_b = public(secret_key_b) >>> encrypt(public_key_a, 123) + encrypt(public_key_b, 456) Traceback (most recent call last): ... ValueError: public keys of ciphertexts must match
- __radd__(other: Union[int, cipher]) cipher[source]
This method makes it possible to use the built-in
sumfunction.>>> secret_key = secret(2048) >>> public_key = public(secret_key) >>> c = encrypt(public_key, 22) >>> decrypt(secret_key, sum([c, c, c, c])) 88
This method should not be invoked for any other reason.
>>> 123 + c Traceback (most recent call last): ... TypeError: can only add ciphertexts
- __iadd__(other: cipher) cipher[source]
Add an encrypted value to an existing encrypted value.
>>> secret_key = secret(2048) >>> public_key = public(secret_key) >>> c = encrypt(public_key, 22) >>> d = encrypt(public_key, 33) >>> c += d >>> int(decrypt(secret_key, c)) 55
At least one of the two arguments must have a public key.
>>> c += cipher(int(c)) >>> decrypt(secret_key, c) 110 >>> d = cipher(int(d)) >>> d += c >>> decrypt(secret_key, d) 143 >>> d = cipher(int(d)) >>> d += cipher(int(c)) Traceback (most recent call last): ... ValueError: public key is required for addition
An integer base value can be used when accumulating iteratively.
>>> b = 0 >>> b += encrypt(public_key, 1) >>> b += encrypt(public_key, 2) >>> b += encrypt(public_key, 3) >>> decrypt(secret_key, b) 6
- __mul__(scalar: int) cipher[source]
Perform multiplication of an encrypted value by a scalar to produce the encrypted result.
>>> secret_key = secret(2048) >>> public_key = public(secret_key) >>> c = encrypt(public_key, 22) >>> r = c * 3 >>> int(decrypt(secret_key, r)) 66
This instance must have a public key.
>>> c = cipher(int(c)) >>> c * 3 Traceback (most recent call last): ... ValueError: public key is required for scalar multiplication
- __rmul__(scalar: int) cipher[source]
Perform multiplication of an encrypted value by a scalar (that appears on the left side of the operator) to produce the encrypted result.
>>> secret_key = secret(2048) >>> public_key = public(secret_key) >>> c = encrypt(public_key, 22) >>> r = 3 * c >>> int(decrypt(secret_key, r)) 66
This instance must have a public key.
>>> c = cipher(int(c)) >>> c * 3 Traceback (most recent call last): ... ValueError: public key is required for scalar multiplication
- __imul__(scalar: int) cipher[source]
Perform multiplication of an encrypted value by a scalar.
>>> secret_key = secret(2048) >>> public_key = public(secret_key) >>> c = encrypt(public_key, 22) >>> c *= 3 >>> int(decrypt(secret_key, c)) 66
This instance must have a public key.
>>> c = cipher(int(c)) >>> c * 3 Traceback (most recent call last): ... ValueError: public key is required for scalar multiplication
- encrypt(public_key: public, plaintext: Union[plain, int]) cipher[source]
Encrypt the supplied plaintext using the supplied public key.
>>> secret_key = secret(2048) >>> public_key = public(secret_key) >>> c = encrypt(public_key, 123) >>> isinstance(c, cipher) True
Any attempt to invoke this function using arguments that do not have the expected types raises an exception.
>>> encrypt(secret_key, 123) Traceback (most recent call last): ... TypeError: can only encrypt using a public key
- decrypt(secret_key: secret, ciphertext: cipher) plain[source]
Decrypt the supplied plaintext using the supplied secret key.
>>> secret_key = secret(2048) >>> public_key = public(secret_key) >>> c = encrypt(public_key, 123) >>> decrypt(secret_key, c) 123
Any attempt to invoke this function using arguments that do not have the expected types raises an exception.
>>> decrypt(public_key, c) Traceback (most recent call last): ... TypeError: can only decrypt using a secret key >>> decrypt(secret_key, 123) Traceback (most recent call last): ... TypeError: can only decrypt a ciphertext
- add(public_key: public, *ciphertexts: cipher) cipher[source]
Perform addition of encrypted values to produce the encrypted result.
>>> secret_key = secret(2048) >>> public_key = public(secret_key) >>> c = encrypt(public_key, 22) >>> d = encrypt(public_key, 33) >>> r = add(public_key, c, d) >>> int(decrypt(secret_key, r)) 55
This function supports one or more ciphertexts. If only one ciphertext is supplied, that same ciphertext is returned.
>>> x = encrypt(public_key, 4) >>> y = encrypt(public_key, 5) >>> z = encrypt(public_key, 6) >>> r = add(public_key, x, y, z) >>> int(decrypt(secret_key, r)) 15 >>> r = add(public_key, x) >>> int(decrypt(secret_key, r)) 4
Iterables of ciphertexts can be provided with the help of unpacking via
*(thus allowing this function to be used in a manner that resembles the way that the built-insumfunction can be used).>>> r = add(public_key, *(c for c in [x, y, z])) >>> int(decrypt(secret_key, r)) 15
Any attempt to invoke this function using arguments that do not have the expected types raises an exception.
>>> add(secret_key, c, d) Traceback (most recent call last): ... TypeError: can only perform operation using a public key >>> add(public_key, c, 123) Traceback (most recent call last): ... TypeError: can only add ciphertexts >>> add(public_key) Traceback (most recent call last): ... ValueError: at least one ciphertext is required
- mul(public_key: public, ciphertext: cipher, scalar: int) cipher[source]
Perform multiplication of an encrypted value by a scalar to produce the encrypted result.
>>> secret_key = secret(2048) >>> public_key = public(secret_key) >>> c = encrypt(public_key, 22) >>> r = mul(public_key, c, 3) >>> int(decrypt(secret_key, r)) 66
Any attempt to invoke this function using arguments that do not have the expected types raises an exception.
>>> mul(secret_key, c, 3) Traceback (most recent call last): ... TypeError: can only perform operation using a public key >>> mul(public_key, 123, 3) Traceback (most recent call last): ... TypeError: can only multiply a ciphertext >>> mul(public_key, c, 'abc') Traceback (most recent call last): ... TypeError: can only multiply by an integer scalar