bcl module
Python library that provides a simple interface for symmetric (i.e., secret-key) and asymmetric (i.e., public-key) encryption/decryption primitives.
This library exports a number of classes (derived from bytes) for
representing keys, nonces, plaintexts, and ciphertexts. It also exports
two classes symmetric and asymmetric that have only static
methods (for key generation and encryption/decryption).
- class bcl.bcl.raw[source]
Bases:
bytesWrapper class for a raw bytes-like object that represents a key, nonce, plaintext, or ciphertext. The derived classes
secret,public,nonce,plain, andcipherall inherit the methods defined in this class.>>> s = secret.from_base64('1P3mjNnadofjTUkzTmipYl+xdo9z/EaGLbWcJ8MAPBQ=') >>> s.hex() 'd4fde68cd9da7687e34d49334e68a9625fb1768f73fc46862db59c27c3003c14' >>> n = nonce.from_base64('JVN9IKBLZi3lEq/eDgkV+y6n4v7x2edI') >>> c = symmetric.encrypt(s, 'abc'.encode(), n) >>> c.to_base64() 'JVN9IKBLZi3lEq/eDgkV+y6n4v7x2edI9dvFXD+om1dHB6UUCt1y4BqrBw=='
- classmethod from_base64(s: str) bcl.bcl.raw[source]
Convert Base64 UTF-8 string representation of a raw value.
- class bcl.bcl.nonce(argument: Optional[Union[bytes, bytearray, int]] = None)[source]
Bases:
bcl.bcl.rawWrapper class for a bytes-like object that represents a nonce.
>>> n = nonce() >>> n = nonce(bytes(n)) >>> isinstance(n, nonce) and isinstance(n, bytes) True
While the constructor works like the constructor for bytes-like objects in also accepting an integer argument, an instance can only have the exact length permitted for a nonce.
>>> nonce(nonce.length).hex() '000000000000000000000000000000000000000000000000'
The constructor for this class checks that the supplied bytes-like object or integer argument satisfy the conditions for a valid nonce.
>>> nonce('abc') Traceback (most recent call last): ... TypeError: nonce constructor argument must be a bytes-like object or an integer >>> try: ... nonce(bytes([1, 2, 3])) ... except ValueError as e: ... str(e) == 'nonce must have exactly ' + str(nonce.length) + ' bytes' True >>> try: ... nonce(123) ... except ValueError as e: ... str(e) == 'nonce must have exactly ' + str(nonce.length) + ' bytes' True
- class bcl.bcl.key[source]
Bases:
bcl.bcl.rawWrapper class for a bytes-like object that represents a key. The derived classes
secretandpublicinherit the methods defined in this class.Any
keyobjects (including instances of classes derived fromkey) have a few features and behaviors that distinguish them from bytes-like objects.Comparison of keys (using the built-in
==and!=operators via the__eq__and__ne__methods) is performed in constant time.Keys of different types are not equivalent even if their binary representation is identical.
>>> b = 'd6vGTIjbxZyMolCW+/p1QFF5hjsYC5Q4x07s+RIMKK8=' >>> secret.from_base64(b) == public.from_base64(b) False >>> secret.from_base64(b) != public.from_base64(b) True
Consistent with the above property, keys having different classes are distinct when used as keys or items within containers.
>>> b = 'd6vGTIjbxZyMolCW+/p1QFF5hjsYC5Q4x07s+RIMKK8=' >>> len({secret.from_base64(b), public.from_base64(b)}) 2
- __eq__(other: bcl.bcl.key) bool[source]
Compare two keys (including their subclass). The portion of the method that compares byte values runs in constant time.
>>> key(bytes([0] * 32)) == key(bytes([1] * 32)) False >>> key(bytes([1] * 32)) == key(bytes([1] * 32)) True >>> secret(bytes([0] * 32)) == public(bytes([0] * 32)) False
- __ne__(other: bcl.bcl.key) bool[source]
Compare two keys (including their subclass). The portion of the method that compares byte values runs in constant time.
>>> key(bytes([0] * 32)) != key(bytes([1] * 32)) True >>> key(bytes([1] * 32)) != key(bytes([1] * 32)) False >>> secret(bytes([0] * 32)) != public(bytes([0] * 32)) True
- class bcl.bcl.secret(argument: Optional[Union[bytes, bytearray, int]] = None)[source]
Bases:
bcl.bcl.keyWrapper class for a bytes-like object that represents a secret key. The constructor for this class can be used to generate an instance of a secret key or to convert a bytes-like object into a secret key.
>>> s = secret() >>> s = secret(bytes(s)) >>> isinstance(s, secret) and isinstance(s, key)and isinstance(s, bytes) True
While the constructor works like the constructor for bytes-like objects in also accepting an integer argument, an instance can only have the exact length permitted for a secret key.
>>> secret(secret.length).hex() '0000000000000000000000000000000000000000000000000000000000000000'
The constructor for this class checks that the supplied bytes-like object or integer argument satisfy the conditions for a valid secret key.
>>> secret('abc') Traceback (most recent call last): ... TypeError: secret key constructor argument must be a bytes-like object or an integer >>> try: ... secret(bytes([1, 2, 3])) ... except ValueError as e: ... str(e) == 'secret key must have exactly ' + str(secret.length) + ' bytes' True >>> try: ... secret(123) ... except ValueError as e: ... str(e) == 'secret key must have exactly ' + str(secret.length) + ' bytes' True
The methods
symmetric.encrypt,symmetric.decrypt, andasymmetric.decryptonly accept key parameters that are objects of this class.
- class bcl.bcl.public(argument: Optional[Union[bytes, bytearray, int]] = None)[source]
Bases:
bcl.bcl.keyWrapper class for a bytes-like object that represents a public key. The constructor for this class can be used to generate an instance of a public key or to convert a bytes-like object into a public key.
>>> p = public() >>> p = public(bytes(p)) >>> isinstance(p, public) and isinstance(p, key)and isinstance(p, bytes) True
While the constructor works like the constructor for bytes-like objects in also accepting an integer argument, an instance can only have the exact length permitted for a public key.
>>> public(public.length).hex() '0000000000000000000000000000000000000000000000000000000000000000'
The constructor for this class checks that the supplied bytes-like object or integer argument satisfy the conditions for a valid public key.
>>> public('abc') Traceback (most recent call last): ... TypeError: public key constructor argument must be a bytes-like object or an integer >>> try: ... public(bytes([1, 2, 3])) ... except ValueError as e: ... length = crypto_box_PUBLICKEYBYTES ... str(e) == 'public key must have exactly ' + str(length) + ' bytes' True >>> try: ... public(123) ... except ValueError as e: ... length = crypto_box_PUBLICKEYBYTES ... str(e) == 'public key must have exactly ' + str(length) + ' bytes' True
The method
asymmetric.encryptonly accepts key parameters that are objects of this class.
- class bcl.bcl.plain[source]
Bases:
bcl.bcl.rawWrapper class for a bytes-like object that represents a plaintext.
>>> x = plain(os.urandom(1024)) >>> x == plain.from_base64(x.to_base64()) True
The methods
symmetric.decryptandasymmetric.decryptreturn objects of this class.
- class bcl.bcl.cipher[source]
Bases:
bcl.bcl.rawWrapper class for a bytes-like object that represents a ciphertext.
>>> c = cipher(os.urandom(1024)) >>> c == cipher.from_base64(c.to_base64()) True
The methods
symmetric.encryptandasymmetric.encryptreturn objects of this class, and the methodssymmetric.decryptandasymmetric.decryptcan only be applied to objects of this class.
- class bcl.bcl.symmetric[source]
Bases:
objectSymmetric (i.e., secret-key) encryption/decryption primitives. This class encapsulates only static methods and should not be instantiated.
>>> x = 'abc'.encode() >>> s = symmetric.secret() >>> isinstance(s, key) and isinstance(s, secret) True >>> s == secret.from_base64(s.to_base64()) True >>> c = symmetric.encrypt(s, x) >>> isinstance(c, raw) and isinstance(c, cipher) True >>> c == cipher.from_base64(c.to_base64()) True >>> symmetric.decrypt(s, c) == x True >>> isinstance(symmetric.decrypt(s, c), plain) True
Encryption is non-deterministic if no
nonceparameter is supplied.>>> symmetric.encrypt(s, x) == symmetric.encrypt(s, x) False
Deterministic encryption is possible by supplying a
nonceparameter.>>> n = nonce() >>> symmetric.encrypt(s, x, n) == symmetric.encrypt(s, x, n) True
- static secret() bcl.bcl.secret[source]
Generate a
secretkey.
- static encrypt(secret_key: bcl.bcl.secret, plaintext: Union[bcl.bcl.plain, bytes, bytearray], noncetext: Optional[bcl.bcl.nonce] = None) bcl.bcl.cipher[source]
Encrypt a plaintext (a bytes-like object) using the supplied
secretkey (and an optionalnonce, if applicable).>>> m = plain(bytes([1, 2, 3])) >>> s = symmetric.secret() >>> c = symmetric.encrypt(s, m) >>> m == symmetric.decrypt(s, c) True
All parameters supplied to this method must have appropriate types.
>>> c = symmetric.encrypt(bytes([0, 0, 0]), m) Traceback (most recent call last): ... TypeError: can only encrypt using a symmetric secret key >>> c = symmetric.encrypt(s, 'abc') Traceback (most recent call last): ... TypeError: can only encrypt a plaintext object or bytes-like object >>> c = symmetric.encrypt(s, m, bytes([0, 0, 0])) Traceback (most recent call last): ... TypeError: nonce parameter must be a nonce object
- static decrypt(secret_key: bcl.bcl.secret, ciphertext: bcl.bcl.cipher) bcl.bcl.plain[source]
Decrypt a ciphertext (an instance of
cipher) using the suppliedsecretkey.>>> m = plain(bytes([1, 2, 3])) >>> s = symmetric.secret() >>> c = symmetric.encrypt(s, m) >>> m == symmetric.decrypt(s, c) True
All parameters supplied to this method must have appropriate types.
>>> c = symmetric.decrypt(bytes([0, 0, 0]), m) Traceback (most recent call last): ... TypeError: can only decrypt using a symmetric secret key >>> c = symmetric.decrypt(s, 'abc') Traceback (most recent call last): ... TypeError: can only decrypt a ciphertext >>> symmetric.decrypt(s, cipher(c + bytes([0, 0, 0]))) Traceback (most recent call last): ... RuntimeError: ciphertext failed verification
- class bcl.bcl.asymmetric[source]
Bases:
objectAsymmetric (i.e., public-key) encryption/decryption primitives. This class encapsulates only static methods and should not be instantiated.
>>> x = 'abc'.encode() >>> s = asymmetric.secret() >>> isinstance(s, key) and isinstance(s, secret) True >>> p = asymmetric.public(s) >>> isinstance(p, key) and isinstance(p, public) True >>> p == public.from_base64(p.to_base64()) True >>> c = asymmetric.encrypt(p, x) >>> asymmetric.decrypt(s, c) == x True
- static secret() bcl.bcl.secret[source]
Generate a
secretkey.>>> s = symmetric.secret() >>> isinstance(s, key) and isinstance(s, secret) True
- static public(secret_key: bcl.bcl.secret) bcl.bcl.public[source]
Generate a
publickey using asecretkey.>>> s = asymmetric.secret() >>> p = asymmetric.public(s) >>> isinstance(p, key) and isinstance(p, public) True
- static encrypt(public_key: bcl.bcl.public, plaintext: Union[bcl.bcl.plain, bytes, bytearray]) bcl.bcl.cipher[source]
Encrypt a plaintext (any bytes-like object) using the supplied
publickey.>>> m = plain(bytes([1, 2, 3])) >>> s = asymmetric.secret() >>> p = asymmetric.public(s) >>> c = asymmetric.encrypt(p, m) >>> m == asymmetric.decrypt(s, c) True
All parameters supplied to this method must have appropriate types.
>>> c = asymmetric.encrypt(s, m) Traceback (most recent call last): ... TypeError: can only encrypt using a public key >>> c = asymmetric.encrypt(p, 'abc') Traceback (most recent call last): ... TypeError: can only encrypt a plaintext object or bytes-like object
- static decrypt(secret_key: bcl.bcl.secret, ciphertext: bcl.bcl.cipher) bcl.bcl.plain[source]
Decrypt a ciphertext (an instance of
cipher) using the suppliedsecretkey.>>> m = plain(bytes([1, 2, 3])) >>> s = asymmetric.secret() >>> p = asymmetric.public(s) >>> c = asymmetric.encrypt(p, m) >>> m == asymmetric.decrypt(s, c) True
All parameters supplied to this method must have appropriate types.
>>> c = asymmetric.decrypt(p, m) Traceback (most recent call last): ... TypeError: can only decrypt using an asymmetric secret key >>> c = asymmetric.decrypt(s, 'abc') Traceback (most recent call last): ... TypeError: can only decrypt a ciphertext >>> try: ... asymmetric.decrypt(s, cipher(bytes([0]))) ... except ValueError as e: ... length = crypto_box_SEALBYTES ... str(e) == 'asymmetric ciphertext must have at least ' + str(length) + ' bytes' True