18 from typing
import Tuple
19 from base64
import b64decode
23 from Crypto.PublicKey
import RSA
24 from cryptography.hazmat.primitives
import hashes, serialization
25 from cryptography.hazmat.primitives.asymmetric
import rsa, padding
27 from .random_generator
import Random
30 def _generateRsaNumbers(bits: int, seed: bytes) -> Tuple[int, int, int, int, int]:
32 Randomly generates numbers used for calculating RSA public
38 # of bits in the "n" public number
40 Array of bytes which represent seed for generating key in a deterministic way.
41 The entropy of the generated key is equal to the entropy of the seed.
44 Tuple[int, int, int, int, int] -> p, q, n, e, d RSA values, e is always equal to 65537
47 random = Random(seed, hashes.SHA256())
48 numbers = RSA.generate(bits, randfunc = random.getRandomBytes, e = 65537)
50 return numbers.p, numbers.q, numbers.n, numbers.e, numbers.d
53 def generateKey(length: int, seed: bytes) -> rsa.RSAPrivateKey:
55 Generates RSA key-pair with the provided length and seed
60 length of the key-pair
62 Array of bytes which represent seed for generating key in a deterministic way.
63 The entropy of the generated key is equal to the entropy of the seed.
67 RSAPrivateKey -> cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey object
75 p, q, n, e, d = _generateRsaNumbers(length, seed)
77 dmp1 = rsa.rsa_crt_dmp1(d, p)
78 dmq1 = rsa.rsa_crt_dmq1(d, q)
79 iqmp = rsa.rsa_crt_iqmp(p, q)
81 privateNumbers = rsa.RSAPrivateNumbers(p, q, d, dmp1, dmq1, iqmp, rsa.RSAPublicNumbers(e, n))
82 return privateNumbers.private_key()
85 def getPrivateKeyBytes(key: rsa.RSAPrivateKey) -> bytes:
87 Converts the provided key into a byte array.
88 Encoding is PEM, Format is PKCS8
93 cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey object
97 bytes -> RSA private key serialized to bytes
100 return key.private_bytes(
101 encoding = serialization.Encoding.PEM,
102 format = serialization.PrivateFormat.PKCS8,
103 encryption_algorithm = serialization.NoEncryption()
107 def getPublicKeyBytes(key: rsa.RSAPublicKey) -> bytes:
109 Converts the provided key into a byte array.
110 Encoding is PEM, Format is PKCS1
115 cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey object
119 bytes -> RSA public key serialized to bytes
122 return key.public_bytes(
123 encoding = serialization.Encoding.PEM,
124 format = serialization.PublicFormat.PKCS1
128 def privateKeyFromBytes(keyBytes: bytes) -> rsa.RSAPrivateKey:
130 Creates private key object from provided private
140 rsa.RSAPrivateKey -> private key object
143 key = serialization.load_pem_private_key(keyBytes, password =
None)
145 if not isinstance(key, rsa.RSAPrivateKey):
151 def getPrivateKey() -> rsa.RSAPrivateKey:
153 Retrieves RSA private key stored in CTX_PRIVATE_KEY
154 environment variable in base64 format.
158 rsa.RSAPrivateKey -> private key object
161 if "CTX_PRIVATE_KEY" not in os.environ:
162 raise RuntimeError(f
"\"CTX_PRIVATE_KEY\" environment variable not set")
164 privateKey = b64decode(os.environ[
"CTX_PRIVATE_KEY"])
165 return privateKeyFromBytes(privateKey)
168 def decrypt(key: rsa.RSAPrivateKey, value: bytes) -> bytes:
170 Decrypts ciphertext encrypted using provided key-pair.
171 It is assumed that PKCS#1 padding was used during encryption.
175 key : rsa.RSAPrivateKey
182 bytes -> decrypted ciphertext
185 return key.decrypt(value, padding.PKCS1v15())