U af,@sddlZddlZddlZddlmZmZddlmZddlm Z m Z m Z m Z ddl mZddlmZddlmZmZddlmZmZdd lmZmZe ed d d Ze eefed ddZGdddZGdddZGdddZ dS)N) b64decode b64encode)Path)AnyStrOptionalUnioncast)x509)Fernet)hashes serialization)MGF1OAEP)aes_cbc_pkcs7_encryptaes_cbc_pkcs7_decrypt)datareturncCst|tr|d}tt|S)a Convert a Python `str` object to a `bytes` object. If the parameter is already a `bytes` object, return it unmodified. :param data: The object to be converted :return: The converted object, or the original object if it was not a `str` object utf-8) isinstancestrencoderbytes)rrE/opt/nydus/tmp/pip-target-53d1vnqk/lib/python/primordial/encryptor.py _make_bytess  r)key_pathrcCsB|dkrtdt|tr"t|}|s:tdj|d|S)a. Convenience function to load the content of a key or cert file and return its contents. :param key_path: Path to the key/cert file to be loaded :return: The file contents as a bytes object :raises: ValueError if the key_path parameter is None of doesn't point to an existing file Nz!key_path parameter cannot be Nonez$key path '{key_path}' does not existr) ValueErrorrrris_fileformat read_bytesrrrrload_key_content!s  r!c@s<eZdZdZeeeedddZeeeedddZ dS) Encryptor)encrypted_data secret_keyrcCsPtt|}|d|j}||jd}t|}t|}t|||dS)a Decrypt encrypted data using the PKCS7 symmetric decryption algorithm :param encrypted_data: Base-64 encoded byte array containing encrypted data, which is a combination of the salt and the actual data :param secret_key: Secret value used to generate an encryption key :return: Decrypted, plain text value Nr)rr_Encryptor__iv_sizehashlibsha256digestrdecode)clsr$r%Z decoded_dataivrsecret_key_byteshashed_secret_keyrrrdecrypt9s zEncryptor.decrypt)unencrypted_datar%rc CsFt|j}t|}t|}t|}t|||\}}t||S)a# Encrypts data using the PKCS7 symmetric encryption algorithm :param unencrypted_data: Data to be encrypted :param secret_key: Secret value used to generate an encryption key :return: Base-64 encoded byte array containing encrypted value ) osurandomr&rr'r(r)rr) r+r0r%Ziv_bytesZplain_text_bytesr-r.r,r$rrrencryptKs zEncryptor.encryptN) __name__ __module__ __qualname__r& classmethodrrr/rr3rrrrr"6s r"c@s`eZdZdZeZeeededdZ e e e e edddZe e e e e dd d ZdS) SmallPayloadEncryptora Utility class that provides methods to encrypt and decrypt small-ish payloads via an asymmetric (public/private key) algorithm. The definition of "small" depends on the size of the encryption key and the type of padding algorithm used. For example, given a key size of 4096 bytes and the type of padding used by this set class, the maximum size of a payload that can be encrypted is 447 bytes. ) algorithmN)Zmgfr9labelr$decryption_key_contentrcCsJ|dkr dS|dkrtdtt|}tj|dd}|||jdS)a Decrypts data encrypted by the `encrypt()` method in this class. :param encrypted_data: The data to be decrypted :param decryption_key_content: The content of the OpenSSL private key file corresponding to the public cert used to encrypt the data :return: The decrypted data :raises: ValueError if decryption_key_content` is None N$decryption_key_content can't be None)passwordr)rrrr Zload_pem_private_keyr/_SmallPayloadEncryptor__paddingr*)r+r$r<Zdecryption_keyrrrr/hs  zSmallPayloadEncryptor.decryptr0encryption_key_contentrcCsH|dkr dS|dkrtdt|}t|}|}t|||jS)a Encrypts any small payload using an RSA asymmetric key algorithm. The maximum size of the payload depends on the size of the encryption key. For example, given a key size of 4096 bits, the maximum size of the payload that can be encrypted is 447 bytes. :param unencrypted_data: The data to be encrypted :param encryption_key_content: The content of the OpenSSL X509 public certificate that will be used to encrypt the data :return: The base64 encoded and encrypted data as a bytes object :raises: ValueError if the payload size is too large :raises: ValueError if `encryption_key_content` is None N$encryption_key_content can't be None)rrr Zload_pem_x509_certificateZ public_keyrr3r?)r+r0rAZencryption_certZencryption_keyrrrr3~s zSmallPayloadEncryptor.encrypt)r4r5r6__doc__r SHA256Z&_SmallPayloadEncryptor__hash_algorithmrr r?r7rrrrr/r3rrrrr8]sr8c@sDeZdZdZeeeeedddZ eeeeedddZ dS) LargePayloadEncryptora This class provides methods to encrypt and decrypt large payloads via the Fernet symmetric encryption algorithm. The `encrypt()` method automatically generates a key for encryption. That key is then encrypted using the asymmetric public/private key algorithm of the `SmallPayloadEncrypter.encrypt()` method and is included in the resulting byte stream returned by this classes' `encrypt()` method. The "receiving" endpoint must then extract the Fernet key from the byte stream and use the corresponding private key of public/private key pair to decrypt the Fernet key. The decrypted Fernet key can then be used to decrypt the remainder of the payload. The only known restriction on payload size is that the payload must fit into memory. r;cCs|dkr dS|dkrtdt|}tt|d}|d}|dkrRtdt|}ttt ||}t|}t tt |}| |d ddS)a Decrypts data encrypted by the `encrypt()` method of this class. The decryption algorithm is 1. Decode the base-64 representation of the JSON object 2. Load the JSON into a Python dictionary 3. Extract the encrypted Fernet key from the JSON object and decrypt it using our asymmetric decryption algorithm, i.e., the same algorithm we use to decrypt passwords. 4. Extract the encrypted data from the JSON object and decrypt it using the Fernet decryption algorithm. :param encrypted_data: The data to be decrypted :param decryption_key_content: The content of the OpenSSL private key file corresponding to the public cert used to encrypt the data :return: The decrypted data as a `str` object :raises: ValueError if the decryption key is missing from the `encrypted_data` payload :raises: ValueError if decryption_key_content` is None Nr=rkeyz0token decryption key is missing from the payloadtoken)rrjsonloadsrr*getrrr8r/r rr)r+r$r<Z json_objectZencrypted_token_keyZdecrypted_token_keyfernet_encryptorrrrr/s zLargePayloadEncryptor.decryptr@cCs~|dkr dS|dkrtdt|tr0|d}t}t|}t||d|t t |dd}t t |dS)a Encrypts arbitrary data. This method uses a symmetric encryption algorithm (Fernet) to encrypt the data. This algorithm is capable of encrypting much larger payloads than asymmetric algorithms like RSA, which are limited by the key size and padding, if used. The encryption process is 1. Generate a random encryption key 2. Use that key to encrypt the original data. 3. Encrypt the key generated in step 1 by our asymmetric encryption algorithm, i.e., the same algorithm we use to encrypt passwords. This step may or may not use the same public/private keys we use for password encryption. 4. Create a Python dictionary with two entries: key: the encrypted Fernet key token: the data that was encrypted with the Fernet key Both the dictionary keys and values must be of type `str` to be JSON serializable. 5. Serialize the dictionary as a JSON string 6. Return a base-64 encoded representation of the JSON. :param unencrypted_data: The data to be encrypted :param encryption_key_content: The content of the OpenSSL X509 public certificate that will be used to encrypt the data :return: The encrypted key/text pair as a base-64 encoded `bytes` object :raises: ValueError if `encryption_key_content` is None NrBr)rFrG)rrrrr Z generate_keyr8r3r*rrrrHdumps)r+r0rArFrKresultrrrr3s  zLargePayloadEncryptor.encryptN) r4r5r6rCr7rrrrr/r3rrrrrEs  'rE)!r'rHr1base64rrpathlibrtypingrrrrZ cryptographyr Zcryptography.fernetr Zcryptography.hazmat.primitivesr r Z1cryptography.hazmat.primitives.asymmetric.paddingr rZoscrypto.symmetricrrrrrr!r"r8rErrrrs   '<