o
    ɶdTO                     @   s  d dl Z d dlZd dlZd dlZd dlmZ d dlmZ d dlm	Z	m
Z
 d dlmZ d dlmZmZ d dlmZmZ d dlmZmZmZ d d	lmZmZmZmZ d d
lmZ d dlmZ e e!ddd Z"e"Z#dd Z$dd Z%G dd deZ&G dd deZ'dd Z(dS )    N)six)default_backend)Ciphermodes)Lock)serialize_headerdeserialize_header_from_stream)EncryptedDataHeader$EncryptedDataHeaderDataEncryptionKey)DEFAULT_MAX_GCM_ENCRYPTION_SIZEDEFAULT_ALGORITHM$DEFAULT_MAX_ENCRYPTION_SIZE_SENTINEL)convert_to_bytesconvert_to_strgenerate_random_iv$convert_encryption_context_to_string)	Algorithm)CryptoResultStream         c                 C   sj   d}t |tkr-d}t|}	 |t }||| }t |dkr"	 |S || j|d7 }|}q| j|d}|S )N    r   T)data)len2MAX_ENCRYPTOR_DECRYPTOR_UPDATE_CHUNK_SIZE_IN_BYTES
memoryviewupdate)Zcryptorr   resultZstart_indexmemviewZ	end_indexZ	next_data r   Eusr/lib/python3.10/site-packages/oci/encryption/internal/streaming.py_update_cryptor_with_data(   s   
r!   c              
   C   s  | d u rd S t | tstdg }g }g }t| D ]7\}}ttkr't |ts-t |tjs3|| n
|	dr=|| ttkrFt |tsLt |tjsQ|| q|sV|rbtd
t|t||rmtd
t|zt|  W d S  ty } z	td
t|d }~ww )Nz!encryption_context must be a dictzoci-zjencryption_context must be a dict with string keys and string values. Invalid keys: {}. Invalid values: {}zKencryption_context cannot contain keys with prefix 'oci-'. Invalid keys: {}z7encryption_context must be JSON serializable. Error: {})
isinstancedict	TypeErrorr   Z	iteritemsstrbytesZstring_typesappend
startswithformat
ValueErrorjsondumps)encryption_contextZinvalid_keysZinvalid_valuesZinvalid_prefix_keyskeyvalueer   r   r    _validate_encryption_context<   sF   



r1   c                   @   s\   e Zd ZedfddZdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd ZdddZdS )StreamEncryptorNc                 C   s  t | _| | _| jstd| j| j| _|| _t| || _	t
t|| _t| jj| _t| j| jj| j| jt d}| | _d| _|tu re| jjjtjjkr[t| _ntdt| j|durut|tsrt d|| _d| _!d| _"d| _#d| _$d| _%t& | _'d| _(dS )	a  
        Provides a stream that wraps 'stream_to_encrypt' and allows reading data from the underlying stream
        encrypted under the provided master key.

        :param int max_encryption_size: (optional)
            Max number of bytes able to be encrypted by this StreamEncryptor. The default value differs
            based on the algorithm used. For GCM (the default algorithm) the default value is 2147483647 bytes.
            This is provided mainly for use with authenticated encryption algorithms that require verification
            of an authentication tag upon decryption. Because decrypting using these algorithms will buffer
            the entire payload into memory before returning it, this max_encryption_size provides a sanity
            check against encrypting payloads too large to decrypt. This is possible because encryption does not
            require holding the entire payload in memory.

            The 2147483647 byte limit was chosen because that is the maximum number of bytes that can be encrypted or
            decrypted by the OCI Java SDK.  This is to avoid users accidentally encrypting payloads in Python that
            cannot be decrypted in Java.

            Explicitly passing this value as None will disable the size check and allow encrypting payloads up to
            the maximum size supported by the algorithm.

        :param dict encryption_context: (optional)
            Optional additional data to be provided as input to authenticated encryption
            algorithms. This must be a dict with keys that are strings and values that are strings. Keys may NOT
            match the prefix oci-* as that namespace is reserved for OCI internal keys that may be added to the AAD.
        zNmaster_key_provider must contain a primary master key in order to encrypt data	algorithmmodeZbackendNz#Unrecognized algorithm provided: {}z/argument max_encryption_size must be an integerr   r   F))r   
_algorithmZget_primary_master_key_primary_master_keyr*   Zgenerate_data_encryption_key_data_encryption_key_stream_to_encryptr1   _encryption_contextr   r   _encryption_context_bytesr   Ziv_lenivr   r4   Zplaintext_key_bytesr5   r   	encryptor_max_encryption_sizer   namer   ZGCMr   r)   r%   r"   intr$   _header_content_buffer_bytes_written_total_bytes_written_excluding_header
_finalizedr   _lock_closed)selfmaster_key_providerZstream_to_encryptZmax_encryption_sizer-   cipherr   r   r    __init__h   sL    



zStreamEncryptor.__init__c                 C   sF   t | j | jj| jj| jjdg}t|| j| j	j
| jd}t|dS )N)master_key_idvault_idregionencrypted_data_key_bytes)encrypted_data_keysiv_bytesalgorithm_id#additional_authenticated_data_bytes)encrypted_data_header)r
   r7   Zget_identifierrM   rN   r8   Zencrypted_key_bytesr	   r<   r6   idr;   r   )rH   rP   rT   r   r   r    _build_header_content   s   	
z%StreamEncryptor._build_header_contentc                 C   s>   | j dtj}| j dtj | j  }| j | || S )Nr   )r9   seekosSEEK_CURSEEK_ENDtell)rH   Zcur_poslengthr   r   r    =_get_bytes_remaining_in_stream_to_encrypt_using_seek_and_tell   s
   
zMStreamEncryptor._get_bytes_remaining_in_stream_to_encrypt_using_seek_and_tellc                 C   s|   | j | }|dkr't| jdr't| jdr't| jdr'| j r'| j |   }| jd ur:|| jkr<td|| jd S d S )NrW   r[   seekablezqAttempted to encrypt > _max_encryption_size bytes. Total bytes requested to encrypt: {}. Max encryption size: {}.)rD   hasattrr9   r_   r]   r>   r*   r)   )rH   size_of_next_readZ!_total_bytes_requested_to_encryptr   r   r    _enforce_max_encryption_size   s   .

z,StreamEncryptor._enforce_max_encryption_sizec                 C      | S Nr   rH   r   r   r    	__enter__      zStreamEncryptor.__enter__c                 C      |    d S rd   closerH   typer/   	tracebackr   r   r    __exit__      zStreamEncryptor.__exit__c                 C   4   | j   zd| _d| _W | j   d S | j   w NTr   rF   acquirerG   rB   releasere   r   r   r    rj      
   
zStreamEncryptor.closec                 C   s   | j S rd   )r:   re   r   r   r    get_encryption_context   s   z&StreamEncryptor.get_encryption_contextr^   c           	      C   s  | j   z| jrtd|dkrW | j   dS |dk}| js7|  | _|  j| j7  _| jr7| j	
| j | j|d | js|t| jksI|r|rNd}n|t| j }d}|rat| j }nt| j|}t|}t| j	|}||k px|}|r|| j	 | j	j 7 }d| _|  j|7  _|r| jdd }d| _n| jd| }| j|d | _|  jt|7  _| jt| jkr| jt| j | _nd| _| jdd |W | j   S | j   w )	  
        Read up to size bytes from the object and return them. As a convenience, if size is unspecified or -1,
        all bytes until EOF are returned.

        If 0 bytes are returned, and size was not 0, this indicates end of file.

        :param int size: (optional)
            The number of bytes to attempt to read from the underlying stream.

        :rtype: bytes
        Cannot read from closed streamr   r   r^   )ra   FTN)rF   rs   rG   r*   rt   rA   rV   rB   r;   r=   authenticate_additional_datarb   rE   r   r   r9   readr!   finalizetagrC   rD   )	rH   sizeREAD_ALLZsize_to_read_into_bufferZreached_endZbytes_to_encryptZtotal_bytes_to_encrypt_sizeZ
ciphertextoutputr   r   r    rz      sh   
K


zStreamEncryptor.readr^   )__name__
__module____qualname__r   rK   rV   r]   rb   rf   rn   rj   rv   rz   r   r   r   r    r2   g   s    
R
r2   c                   @   sN   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dddZ
dS )StreamDecryptorc                 C   sB   || _ || _d| _d| _d| _d| _d| _i | _t | _	d| _
dS )a  
        Returns a StreamDecryptor which produces decrypted data based on the underlying stream
        supplied as 'stream_to_decrypt'.

        :param oci.encryption.MasterKeyProvider master_key_provider: (required)
            A MasterKeyProvider to use for decrypting the data.

        :param stream stream_to_encrypt: (required)
            The stream to be decrypted.
        Nr   F)_stream_to_decrypt_master_key_provider
_decryptorr6   rB   _header_deserializedrE   r:   r   rF   rG   )rH   Zstream_to_decryptrI   r   r   r    rK   `  s   
zStreamDecryptor.__init__c                 C   rc   rd   r   re   r   r   r    rf   y  rg   zStreamDecryptor.__enter__c                 C   rh   rd   ri   rk   r   r   r    rn   |  ro   zStreamDecryptor.__exit__c                 C   rp   rq   rr   re   r   r   r    rj     ru   zStreamDecryptor.closec                    s    fddt D }|std j|d | _ jd }| jj|j|j	|j
d}||j}t|}t| j|| j jt d}| | _t jratt j| _| j j d S d S )Nc                    s   g | ]
} j |jkr|qS r   )rR   rU   ).0Zalgoheaderr   r    
<listcomp>  s    zMStreamDecryptor._init_decryptor_and_header_related_fields.<locals>.<listcomp>zGCould not decrypt payload encrypted using unrecognized algorithm ID: {}r   )rL   rM   rN   r3   )r   r*   r)   rR   r6   rP   r   Zget_master_keyrL   rM   rN   ZdecryptrO   base64	b64decoder   r4   r5   rQ   r   Z	decryptorr   r   rS   r+   loadsr   r:   ry   )rH   r   Zmatching_algosZencrypted_data_keyZprimary_master_keyZdecrypted_dek_bytesZdek_plaintext_bytesrJ   r   r   r    )_init_decryptor_and_header_related_fields  s@   





z9StreamDecryptor._init_decryptor_and_header_related_fieldsc                 C   s6   | j s| jr
tdd| _ t| j}| | d S d S )Nrx   T)r   rG   r*   r   r   r   )rH   r   r   r   r    _handle_header  s   
zStreamDecryptor._handle_headerc                 C   s2   | j   z|   | jW | j   S | j   w rd   )rF   rs   r   r:   rt   re   r   r   r    rv     s
   
z&StreamDecryptor.get_encryption_contextr^   c                 C   s  | j   zw| jrtd|dkrW | j   dS |   |dk}| jsUd| _tt| j	}|| j
j d }|d| j
j  }t| j|}|| j|7 }|  j|7  _|rb| jdd }d| _n| jd| }t| j}||d | _|W | j   S | j   w )rw   rx   r   r   r^   TN)rF   rs   rG   r*   rt   r   rE   r   _read_full_stream_contentr   r6   Ztag_lenr!   r   Zfinalize_with_tagrB   r   )rH   r}   r~   Zbytes_to_decryptr|   Zdecrypted_datar   r   r   r   r    rz     s6   
(
zStreamDecryptor.readNr   )r   r   r   rK   rf   rn   rj   r   r   rv   rz   r   r   r   r    r   _  s    
)
r   c                 C   s    t | dr
t| jS t|  S )Nreadall)r`   r   r   rz   )streamr   r   r    r     s   

r   ))rX   r   mathr+   Zoci._vendorr   Zcryptography.hazmat.backendsr   Z&cryptography.hazmat.primitives.ciphersr   r   	threadingr   Z%oci.encryption.internal.serializationr   r   Zoci.encryption.internal.modelsr	   r
   Z oci.encryption.internal.defaultsr   r   r   Zoci.encryption.internal.utilsr   r   r   r   Zoci.encryption.algorithmsr   Zoci.encryption.modelsr   r@   powZMAX_32_BIT_SIGNED_INTEGERr   r!   r1   r2   r   r   r   r   r   r    <module>   s.   + y #