
    ]h                         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mZmZmZmZmZmZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dl m!Z! d dl"m#Z# d dl$m%Z% ddl&m'Z' ddl(m)Z)m*Z* erd dl+m,Z, d dlm-Z- d dl m.Z. dZ/dZ0dZ1e/e0e1gZ2e0e1gZ3dZ4dZ5dZ6dZ7dZ8 G d de      Z9de:d efd!Z;d"e9fd#Z< G d$ d%e=      Z> G d& d'e=      Z? G d( d)      Z@ G d* d+      ZA G d, d-      ZB G d. d/      ZC G d0 d1      ZDd2eEd3eFd4eEd5eEfd6ZGd7eeC   d5eHfd8ZId9e:d:e:d;e:d<ee:ef   d5df
d=ZJd>eFd;e:d5eFfd?ZKd@eFdAeFd>eeF   d7eeC   d5eeeFeFf   eeFeFf   f   f
dBZLdCee:ef   d5eeC   fdDZMdEeFd7eeC   d5eFfdFZNd"e9dGeEdHeeE   dIe:d5ee:ef   f
dJZOdKee:ef   d5eCfdLZPdGeEdHeEd5efdMZQ	 	 ded7eCdNee9   dOeee:ge9f      d5eEfdPZR	 	 dedQeEd7eCdNee9   dReee:ge9f      d5eEf
dSZSdTeEdNe9dIe:d5ee:eEf   fdUZTdNee9   dIe:d5eeeE   eeE   ee:   f   fdVZUdWeHdNee9   dOeee:ge9f      dXeEdYeFdZeFd[ee:ef   d5eEfd\ZVdGeeE   dHeeE   d]eHd5eed^   ed_   f   fd`ZWdQe:dNe9dIe:d5e:fdaZXdQe:dbdcdWeHdNee9   dReee:ge9f      d5e:fddZYy)f    N)OrderedDict)BytesIO)dumpsloads)AnyCallableDictIOOptionalTupleTYPE_CHECKING)Protocol)default_backend)Cipher)AESGCM)AES)CBC)PKCS7)HttpResponseError)CaseInsensitiveDict   )VERSION)decode_base64_to_bytesencode_base64)PipelineResponse)AEADEncryptionContext)PaddingContext1.0z2.0z2.1i  @       zT{0} does not define a complete interface. Value of {1} is either missing or invalid.zTThe require_encryption flag is set, but encryption is not supported for this method.c                   H    e Zd ZdedefdZdededefdZdefdZdefdZy)	KeyEncryptionKeykeyreturnc                      y N )selfr#   s     d/var/www/core.comfia.cic-ware.com/crm/lib/python3.12/site-packages/azure/storage/blob/_encryption.pywrap_keyzKeyEncryptionKey.wrap_key<           	algorithmc                      y r&   r'   )r(   r#   r-   s      r)   
unwrap_keyzKeyEncryptionKey.unwrap_key?   r+   r,   c                      y r&   r'   r(   s    r)   get_kidzKeyEncryptionKey.get_kidB   r+   r,   c                      y r&   r'   r1   s    r)   get_key_wrap_algorithmz'KeyEncryptionKey.get_key_wrap_algorithmE   r+   r,   N)	__name__
__module____qualname__bytesr*   strr/   r2   r4   r'   r,   r)   r"   r"   :   sG    E e e     r,   r"   
param_nameparamc                 $    |t        |  d      y )Nz should not be None.)
ValueError)r:   r;   s     r)   _validate_not_noner>   I   s    }J<';<== r,   kekc                    t        | d      rt        | j                        st        t        j                  dd            t        | d      rt        | j                        st        t        j                  dd            t        | d      rt        | j                        st        t        j                  dd            y )Nr*   key encryption keyr2   r4   )hasattrcallabler*   AttributeError_ERROR_OBJECT_INVALIDformatr2   r4   )r?   s    r)   !_validate_key_encryption_key_wraprG   N   s    3
#8CLL+A299:NPZ[\\3	"(3;;*?299:NPYZ[[301#B\B\9]299:NPhijj :^r,   c                   "    e Zd Zdeeef   fdZy)StorageEncryptionMixinkwargsc                    |j                  dd      | _        |j                  dd      | _        |j                  d      | _        |j                  d      | _        | j                  r&| j                  dk(  rt        j                  d       y y y )Nrequire_encryptionFencryption_versionr   key_encryption_keykey_resolver_functiona  This client has been configured to use encryption with version 1.0. Version 1.0 is deprecated and no longer considered secure. It is highly recommended that you switch to using version 2.0. The version can be specified using the 'encryption_version' keyword.)getrL   rM   rN   rO   warningswarn)r(   rJ   s     r)   _configure_encryptionz,StorageEncryptionMixin._configure_encryptionY   s    "(**-A5"I"(**-A5"I"(**-A"B%+ZZ0G%H"""t'>'>%'GMM N O (H"r,   N)r5   r6   r7   r	   r9   r   rS   r'   r,   r)   rI   rI   X   s    	ODcN 	Or,   rI   c                       e Zd ZdZdZdZy)_EncryptionAlgorithmz>
    Specifies which client encryption algorithm is used.
    AES_CBC_256AES_GCM_256N)r5   r6   r7   __doc__rV   rW   r'   r,   r)   rU   rU   e   s      KKr,   rU   c                   (    e Zd ZdZdedededdfdZy)_WrappedContentKeyzD
    Represents the envelope key details stored on the service.
    r-   encrypted_keykey_idr$   Nc                 v    t        d|       t        d|       t        d|       || _        || _        || _        y)z
        :param str algorithm:
            The algorithm used for wrapping.
        :param bytes encrypted_key:
            The encrypted content-encryption-key.
        :param str key_id:
            The key-encryption-key identifier string.
        r-   r[   r\   N)r>   r-   r[   r\   )r(   r-   r[   r\   s       r)   __init__z_WrappedContentKey.__init__r   s8     	;	2?M:8V,"*r,   )r5   r6   r7   rX   r9   r8   r^   r'   r,   r)   rZ   rZ   m   s(    # e S T r,   rZ   c                   (    e Zd ZdZdedededdfdZy)_EncryptedRegionInfoz`
    Represents the length of encryption elements.
    This is only used for Encryption V2.
    data_lengthnonce_length
tag_lengthr$   Nc                 v    t        d|       t        d|       t        d|       || _        || _        || _        y)a  
        :param int data_length:
            The length of the encryption region data (not including nonce + tag).
        :param int nonce_length:
            The length of nonce used when encrypting.
        :param int tag_length:
            The length of the encryption tag.
        ra   rb   rc   N)r>   ra   rb   rc   )r(   ra   rb   rc   s       r)   r^   z_EncryptedRegionInfo.__init__   s9     	=+6><8<4&($r,   )r5   r6   r7   rX   intr^   r'   r,   r)   r`   r`      s)    
%C %s % %PT %r,   r`   c                   $    e Zd ZdZdededdfdZy)_EncryptionAgentz
    Represents the encryption agent stored on the service.
    It consists of the encryption protocol version and encryption algorithm used.
    encryption_algorithmprotocolr$   Nc                 b    t        d|       t        d|       t        |      | _        || _        y)z
        :param _EncryptionAlgorithm encryption_algorithm:
            The algorithm used for encrypting the message contents.
        :param str protocol:
            The protocol version used for encryption.
        rh   ri   N)r>   r9   rh   ri   )r(   rh   ri   s      r)   r^   z_EncryptionAgent.__init__   s/     	13GH:x0$'(<$=! r,   )r5   r6   r7   rX   rU   r9   r^   r'   r,   r)   rg   rg      s#    
!-A !S !UY !r,   rg   c                   F    e Zd ZdZdee   dee   dedede	e
ef   ddfd	Zy)
_EncryptionDatazG
    Represents the encryption data that is stored on the service.
    content_encryption_IVencrypted_region_infoencryption_agentwrapped_content_keykey_wrapping_metadatar$   Nc                 8   t        d|       t        d|       |j                  t        j                  k(  rt        d|       n5|j                  t        j                  k(  rt        d|       nt        d      || _        || _        || _        || _	        || _
        y)a  
        :param Optional[bytes] content_encryption_IV:
            The content encryption initialization vector.
            Required for AES-CBC (V1).
        :param Optional[_EncryptedRegionInfo] encrypted_region_info:
            The info about the autenticated block sizes.
            Required for AES-GCM (V2).
        :param _EncryptionAgent encryption_agent:
            The encryption agent.
        :param _WrappedContentKey wrapped_content_key:
            An object that stores the wrapping algorithm, the key identifier,
            and the encrypted key bytes.
        :param Dict[str, Any] key_wrapping_metadata:
            A dict containing metadata related to the key wrapping.
        ro   rp   rm   rn   zInvalid encryption algorithm.N)r>   rh   rU   rV   rW   r=   rm   rn   ro   rp   rq   )r(   rm   rn   ro   rp   rq   s         r)   r^   z_EncryptionData.__init__   s    , 	-/?@02EF 004H4T4TT68MN226J6V6VV68MN<==%:"%:" 0#6 %:"r,   )r5   r6   r7   rX   r   r8   r`   rg   rZ   r	   r9   r   r^   r'   r,   r)   rl   rl      sV    %;%-e_%;'(<=%; +%; 0	%;
  $CH~%; 
%;r,   rl   c                   <    e Zd ZdZdedee   ddfdZd	dedefdZy)
GCMBlobEncryptionStreamz
    A stream that performs AES-GCM encryption on the given data as
    it's streamed. Data is read and encrypted in regions. The stream
    will use the same encryption key and will generate a guaranteed unique
    nonce for each encryption region.
    content_encryption_keydata_streamr$   Nc                 J    || _         || _        d| _        d| _        d| _        y)z
        :param bytes content_encryption_key: The encryption key to use.
        :param IO[bytes] data_stream: The data stream to read data from.
        r   r,   N)ru   rv   offsetcurrentnonce_counter)r(   ru   rv   s      r)   r^   z GCMBlobEncryptionStream.__init__   s*     '=#&r,   sizec                    t               }|dk(  rt        j                  n|}|dkD  rt        | j                        dkD  rkt        |t        | j                              }|j                  | j                  d|        | j                  |d | _        | xj                  |z  c_        ||z  }|dkD  ry| j                  j                  t              }t        |      dk(  r	 |j                         S t        || j                  | j                        | _        | xj                  dz  c_        |dkD  r|j                         S )z
        Read data from the stream. Specify -1 to read all available data.

        :param int size: The amount of data to read. Defaults to -1 for all data.
        :return: The bytes read.
        :rtype: bytes
        r   Nr   )r   sysmaxsizelenry   minwriterx   rv   read_GCM_REGION_DATA_LENGTHencrypt_data_v2rz   ru   getvalue)r(   r{   result	remainingr   datas         r)   r   zGCMBlobEncryptionStream.read   s    #'2:CKK4	!m4<< 1$9c$,,&78T\\%401#||DE2t#T!	1}'',,-DEt9>   	  /tT5G5GIdIde""a'"' !m*   r,   )r}   )	r5   r6   r7   rX   r8   r
   r^   re   r   r'   r,   r)   rt   rt      s=    &+Y 
 !  !e  !r,   rt   r   noncer#   r$   c                 t    |j                  t        d      }t        |      }|j                  || d      }||z   S )a  
    Encrypts the given data using the given nonce and key using AES-GCM.
    The result includes the data in the form: nonce + ciphertext + tag.

    :param bytes data: The raw data to encrypt.
    :param int nonce: The nonce to use for encryption.
    :param bytes key: The encryption key to use for encryption.
    :return: The encrypted bytes in the form: nonce + ciphertext + tag.
    :rtype: bytes
    bigN)to_bytes_GCM_NONCE_LENGTHr   encrypt)r   r   r#   nonce_bytesaesgcmciphertext_with_tags         r)   r   r     s?     ..!2E:KC[F !..dDA,,,r,   encryption_datac                 T    t        | xr | j                  j                  t        v       S )a'  
    Determine whether the given encryption data signifies version 2.0 or 2.1.

    :param Optional[_EncryptionData] encryption_data: The encryption data. Will return False if this is None.
    :return: True, if the encryption data indicates encryption V2, false otherwise.
    :rtype: bool
    )boolro   ri   _ENCRYPTION_V2_PROTOCOLS)r   s    r)   is_encryption_v2r   )  s&     k_%E%E%N%NRj%jllr,   
user_agentmonikerrM   request_optionsc                     |j                  d      ryd| }|| v ry| j                  d|       }| d|  | d| |d  } |j                  d      r|j                  d       d|  } | |d<   d|d<   y)a%  
    Modifies the request options to contain a user agent string updated with encryption information.
    Adds azstorage-clientsideencryption/<version> immediately proceeding the SDK descriptor.

    :param str user_agent: The existing User Agent to modify.
    :param str moniker: The specific SDK moniker. The modification will immediately proceed azsdk-python-{moniker}.
    :param str encryption_version: The version of encryption being used.
    :param Dict[str, Any] request_options: The reuqest options to add the user agent override to.
    user_agent_overwriteNzazstorage-clientsideencryption/zazsdk-python- r   T)rP   find)r   r   rM   r   feature_flagindexs         r)    modify_user_agent_for_encryptionr   5  s      12 55G4HILz!OOmG956Ev&'~Qz%&7I6JKJ<('++L9:!J<H
$.OL!.2O*+r,   lengthc                     |t         k(  r| d| dz  z
  z   S |t        k(  r1t        t        z   }t	        j
                  | t        z        }| ||z  z   S t        d      )a.  
    Get the adjusted size of the blob upload which accounts for
    extra encryption data (padding OR nonce + tag).

    :param int length: The plaintext data length.
    :param str encryption_version: The version of encryption being used.
    :return: The new upload size to use.
    :rtype: int
    r    %Invalid encryption version specified.)_ENCRYPTION_PROTOCOL_V1_ENCRYPTION_PROTOCOL_V2r   _GCM_TAG_LENGTHmathceilr   r=   )r   rM   encryption_data_lengthregionss       r)   get_adjusted_upload_sizer   W  sf     44v{+,,44!2_!D))F%<<=#99::
<
==r,   startendc                 0   d\  }}|| |f||ffS |j                   j                  t        k(  r+| | dz  }| |z  } | dkD  r
|dz  }| dz  } |d|dz  z
  }||z  }n|j                   j                  t        v rd|}}|j                  t        d      |j                  j                  }|j                  j                  }|j                  j                  }||z   |z   }	|| z
  }
| | |z  }||z  }||	z  }| |z
  }|} |||z  }||
z   dz   }||	z  |	z   dz
  }| |f||ffS )aA  
    Gets the new download range and offsets into the decrypted data for
    the given user-specified range. The new download range will include all
    the data needed to decrypt the user-provided range and will include only
    full encryption regions.

    The offsets returned will be the offsets needed to fetch the user-requested
    data out of the full decrypted data. The end offset is different based on the
    encryption version. For V1, the end offset is offset from the end whereas for
    V2, the end offset is the ending index into the stream.
    V1: decrypted_data[start_offset : len(decrypted_data) - end_offset]
    V2: decrypted_data[start_offset : end_offset]

    :param int start: The user-requested start index.
    :param int end: The user-requested end index.
    :param Optional[int] length: The user-requested length. Only used for V1.
    :param Optional[_EncryptionData] encryption_data: The encryption data to determine version and sizes.
    :return: (new start, new end), (start offset, end offset)
    :rtype: Tuple[Tuple[int, int], Tuple[int, int]]
    )r   r   r    r      +Missing required metadata for Encryption V2r   )	ro   ri   r   r   rn   r=   rb   ra   rc   )r   r   r   r   start_offset
end_offsetrb   ra   rc   region_lengthrequested_length
region_num
data_startregion_starts                 r)   &get_adjusted_download_range_and_offsetr   l  s   2  $L*s|lJ777''004KK 2:L\!E
 qy"sRxJ:C		)	)	2	26N	N#$cj008JKK&<<II%;;GG$::EE
${2Z?;+-J#k1J%5L :-L E?+J%(881<J->BC3<,
333r,   metadatac                 V    	 t        |       }t        t        |d               S #  Y yxY w)aE  
    Parses the encryption data out of the given blob metadata. If metadata does
    not exist or there are parsing errors, this function will just return None.

    :param Dict[str, Any] metadata: The blob metadata parsed from the response.
    :return: The encryption data or None
    :rtype: Optional[_EncryptionData]
    encryptiondataN)r   _dict_to_encryption_datar   )r   case_insensitive_metadatas     r)   parse_encryption_datar     s3    $7$A!'.GHX.Y(Z[[s   !$ (r{   c                    ||j                   zt        |      ro|j                   j                  }|j                   j                  }|j                   j                  }||z   |z   }t        j                  | |z        }|||z   z  }| |z
  S | S )ai  
    Adjusts the given blob size for encryption by subtracting the size of
    the encryption data (nonce + tag). This only has an affect for encryption V2.

    :param int size: The original blob size.
    :param Optional[_EncryptionData] encryption_data: The encryption data to determine version and sizes.
    :return: The new blob size.
    :rtype: int
    )rn   r   rb   ra   rc   r   r   )r{   r   rb   ra   rc   r   num_regionsmetadata_sizes           r)   adjust_blob_size_for_encryptionr     s     	#--9)&<<II%;;GG$::EE
${2Z?ii} 45#|j'@Am##Kr,   cekivversionc                    |t         k(  r| j                  |      }nM|t        k(  r9t        j                         j	                  dd      |z   }| j                  |      }nt        d      t               }| j                         |d<   t        |      |d<   | j                         |d<   t               }||d<   |t         k(  rt        j                  |d<   n8|t        k(  r/t        j                  |d<   t               }t        |d	<   t        |d
<   t               }	||	d<   ||	d<   |t         k(  rt        |      |	d<   n|t        k(  r|	d<   t        ddt        z   i      |	d<   |	S )a  
    Generates and returns the encryption metadata as a dict.

    :param KeyEncryptionKey kek: The key encryption key. See calling functions for more information.
    :param bytes cek: The content encryption key.
    :param Optional[bytes] iv: The initialization vector. Only required for AES-CBC.
    :param str version: The client encryption version used.
    :return: A dict containing all the encryption metadata.
    :rtype: Dict[str, Any]
           r   KeyIdEncryptedKey	Algorithmr   EncryptionAlgorithm
DataLengthNonceLengthWrappedContentKeyEncryptionAgentContentEncryptionIVEncryptedRegionInfoEncryptionLibraryzPython KeyWrappingMetadata)r   r*   r   encodeljustr=   r   r2   r   r4   rU   rV   rW   r   r   r   )
r?   r   r   r   wrapped_cekto_wraprp   ro   rn   encryption_data_dicts
             r)   _generate_encryption_data_dictr     sw   " ))ll3'	+	+)00288EBSHll7+@AA &-#&;;= *7*D''*'A'A'C$"}#*Z ))2F2R2R./	+	+2F2R2R./ +.El+/@m,7B}0C,-.>*+))6CB6G23	+	+6K232=?RT]`gTg>h2i./r,   r   c                    	 | d   d   }|t         vrt        d      	 | d   }t        |d   t	        |d         |d         }| d   }t        |d	   |d         }d
| v r| d
   }nd}d}d| v rt	        | d         }d}d| v r| d   }t        |d   |d   t              }t        |||||      }	|	S # t        $ r}t        d      |d}~ww xY w)a'  
    Converts the specified dictionary to an EncryptionData object for
    eventual use in decryption.

    :param dict encryption_data_dict:
        The dictionary containing the encryption data.
    :return: an _EncryptionData object built from the dictionary.
    :rtype: _EncryptionData
    r   r   zUnsupported encryption version.Nr   r   r   r   r   r   r   r   r   r   )	_VALID_ENCRYPTION_PROTOCOLSr=   KeyErrorrZ   r   rg   r`   r   rl   )
r   ri   excrp   ro   rq   encryption_ivregion_inforn   r   s
             r)   r   r   "  sR   E'(9::F66>?? 7 //BC,-@-M-CDWXfDg-h-@-IK ,,=>'(89N(O(8(DF  44 45J K $ M 44./CDY/Z[ K 44 45J K*+@+N+@+O+:< &m&1&6&9&;	=O G  E:;DEs   B, ,	C5CCc                 \    t               }t        |       }t        |      }t        |||      S )aP  
    Generates and returns an encryption cipher for AES CBC using the given cek and iv.

    :param bytes[] cek: The content encryption key for the cipher.
    :param bytes[] iv: The initialization vector for the cipher.
    :return: A cipher for encrypting in AES256 CBC.
    :rtype: ~cryptography.hazmat.primitives.ciphers.Cipher
    )r   r   r   r   )r   r   backendr-   modes        r)   _generate_AES_CBC_cipherr   V  s-     GCIr7D)T7++r,   rN   key_resolverc                 l   t        d| j                  j                         | j                  j                  t
        k(  rt        d| j                         n>| j                  j                  t        v rt        d| j                         nt        d      d}| || j                  j                        }|t        d      t        |d      rt        |j                        st        t        j!                  dd            t        |d	      rt        |j"                        st        t        j!                  dd	            | j                  j                  |j                         k7  rt        d
      |j#                  | j                  j                  | j                  j$                        }| j                  j                  t        v r`| j                  j                  j'                         j)                  dd      }|dt+        |       }||k7  rt        d      |t+        |      d }t        d|       |S )a  
    Extracts and returns the content_encryption_key stored in the encryption_data object
    and performs necessary validation on all parameters.
    :param _EncryptionData encryption_data:
        The encryption metadata of the retrieved value.
    :param Optional[KeyEncryptionKey] key_encryption_key:
        The user-provided key-encryption-key. Must implement the following methods:
        wrap_key(key)
            - Wraps the specified key using an algorithm of the user's choice.
        get_key_wrap_algorithm()
            - Returns the algorithm used to wrap the specified symmetric key.
        get_kid()
            - Returns a string key id for this key-encryption-key.
    :param Optional[Callable[[str], KeyEncryptionKey]] key_resolver:
        A function used that, given a key_id, will return a key_encryption_key. Please refer
        to high-level service object instance variables for more details.
    :return: The content_encryption_key stored in the encryption_data object.
    :rtype: bytes
    r[   rm   rn   .Specified encryption version is not supported.NzKUnable to decrypt. key_resolver and key_encryption_key cannot both be None.r2   rA   r/   zUProvided or resolved key-encryption-key does not match the id of key used to encrypt.r   r   z@The encryption metadata is not valid and may have been modified.ru   )r>   rp   r[   ro   ri   r   rm   r   rn   r=   r\   rB   rC   r2   rD   rE   rF   r/   r-   r   r   r   )r   rN   r   ru   version_2_bytescek_version_bytess         r)   _validate_and_unwrap_cekr   f  s   2 (K(K(Y(YZ ''004KK2O4Y4YZ		)	)	2	26N	N2O4Y4YZIJJ.2 )/*M*M*T*TU!fgg%y1BTB\B\9]299:NPYZ[[%|4HEWEbEb<c299:NP\]^^**115G5O5O5QQpqq/::++99++557 ''004LL)::CCJJLRRSTV[\23HC4HI/_`` "8O8L8M!N/1GH!!r,   messageresolverc                    t        d|        t        |||      }|j                  j                  t        k(  r|j
                  st        d      t        ||j
                        }|j                         }|j                  |       |j                         z   }t        d      j                         }|j                  |      |j                         z   }|S |j                  j                  t        v r|j                  }	|	r|	j                  st        d      |j                  t        d      t!        |j                  j                        }
| d|
 }| |
d }t#        |      }|j%                  ||d      }|S t        d      )aA  
    Decrypts the given ciphertext using AES256 in CBC mode with 128 bit padding.
    Unwraps the content-encryption-key using the user-provided or resolved key-encryption-key (kek).
    Returns the original plaintext.

    :param bytes message:
        The ciphertext to be decrypted.
    :param _EncryptionData encryption_data:
        The metadata associated with this ciphertext.
    :param Optional[KeyEncryptionKey] key_encryption_key:
        The user-provided key-encryption-key. Must implement the following methods:
        wrap_key(key)
            - Wraps the specified key using an algorithm of the user's choice.
        get_key_wrap_algorithm()
            - Returns the algorithm used to wrap the specified symmetric key.
        get_kid()
            - Returns a string key id for this key-encryption-key.
    :param Optional[Callable[[str], KeyEncryptionKey]] resolver:
        The user-provided key resolver. Uses the kid string to return a key-encryption-key
        implementing the interface defined above.
    :return: The decrypted plaintext.
    :rtype: bytes
    r   z)Missing required metadata for decryption.   Nr   r   )r>   r   ro   ri   r   rm   r=   r   	decryptorupdatefinalizer   unpadderr   rn   rb   re   r   decrypt)r   r   rN   r   ru   cipherr   decrypted_datar   
block_inforb   r   r   r   s                 r)   _decrypt_messager     sx   : y'*5oGY[cd''004KK44HII)*@/BgBgh $$&	#**73i6H6H6JJ :&&("//.9H<M<M<OO, ) 
	)	)	2	26N	N$::
!8!8HII008JKK?@@MMN &%lm4.//BDI
  IJJr,   blobc                    t        d|        t        d|       t        |       |t        k(  rt        j                  d      }t        j                  d      }t        ||      }t        d      j                         }|j                  |       |j                         z   }|j                         }|j                  |      |j                         z   }	nS|t        k(  r?t        j                  d      }d}t        |       }
t        ||
      }|j                         }	nt        d      t!        ||||      }d|d	<   t#        |      |	fS )
aK  
    Encrypts the given blob using the given encryption protocol version.
    Wraps the generated content-encryption-key using the user-provided key-encryption-key (kek).
    Returns a json-formatted string containing the encryption metadata. This method should
    only be used when a blob is small enough for single shot upload. Encrypting larger blobs
    is done as a part of the upload_data_chunks method.

    :param bytes blob:
        The blob to be encrypted.
    :param KeyEncryptionKey key_encryption_key:
        The user-provided key-encryption-key. Must implement the following methods:
        wrap_key(key)
            - Wraps the specified key using an algorithm of the user's choice.
        get_key_wrap_algorithm()
            - Returns the algorithm used to wrap the specified symmetric key.
        get_kid()
            - Returns a string key id for this key-encryption-key.
    :param str version: The client encryption version to use.
    :return: A tuple of json-formatted string containing the encryption metadata and the encrypted blob data.
    :rtype: (str, bytes)
    r   rN       r    r   Nr   FullBlobEncryptionMode)r>   rG   r   osurandomr   r   padderr   r   	encryptorr   r   rt   r   r=   r   r   )r   rN   r   ru   initialization_vectorr   r   padded_datar  encrypted_datar   encryption_streamr   s                r)   encrypt_blobr    s3   . vt$+-?@%&89))!#B "

2)*@BWX s""$mmD)FOO,== $$&	"))+69K9K9MM	+	+!#B $t}34JDQ*//1 @AA45GI_5JGUO(2O$%!>11r,   c                     d}d}d}| r\t        |        t        j                  d      }|t        k(  rt        j                  d      }t	        | |||      }d|d<   t        |      }|||fS )a  
    Generates the encryption_metadata for the blob.

    :param Optional[KeyEncryptionKey] key_encryption_key:
        The key-encryption-key used to wrap the cek associate with this blob.
    :param str version: The client encryption version to use.
    :return: A tuple containing the cek and iv for this blob as well as the
        serialized encryption metadata for the blob.
    :rtype: (Optional[bytes], Optional[bytes], Optional[str])
    Nr   r    r   r   )rG   r   r   r   r   r   )rN   r   r   ru   r  r   s         r)   generate_blob_encryption_datar  /  s     O! )*<=!#B--$&JJrN!=>P9O9N9@ B 2<-. 45!#8/IIr,   rL   contentr   r   response_headersc                    	 t        t        |d               }|j                  j
                  }	|	t        j                  t        j                  fvrt        d      |j                  j                  }
|
t        vrt        d      t        |||      }|
t        k(  rA|d   }d}d}d|v r|d   }|j                  d	      }|d
   j                  d      }|d
   j                  d      }t        |d         }t        |d
         }|dk\  r|dd }|dd }|dz  }n|j                  }||d
z
  k(  rd}nd}|j                  }|dk(  rd}|t        d      t!        ||      }|j#                         }|j%                  |      |j'                         z   }|r;t)        d      j+                         }|j%                  |      |j'                         z   }||t-        |      |z
   S |
t.        v rt-        |      }d}|j0                  t        d      |j0                  j2                  }|j0                  j4                  }|j0                  j6                  }||z   |z   }t9               }||k  rXt;        ||      }||||z    }|d| }||d }t=        |      } | j?                  ||d      }!|jA                  |!       ||z  }||k  rX||| S t        d      # t        $ r}| rt        d      ||cY d}~S d}~ww xY w)a  
    Decrypts the given blob contents and returns only the requested range.

    :param bool require_encryption:
        Whether the calling blob service requires objects to be decrypted.
    :param Optional[KeyEncryptionKey] key_encryption_key:
        The user-provided key-encryption-key. Must implement the following methods:
        wrap_key(key)
            - Wraps the specified key using an algorithm of the user's choice.
        get_key_wrap_algorithm()
            - Returns the algorithm used to wrap the specified symmetric key.
        get_kid()
            - Returns a string key id for this key-encryption-key.
    :param key_resolver:
        The user-provided key resolver. Uses the kid string to return a key-encryption-key
        implementing the interface defined above.
    :type key_resolver: Optional[Callable[[str], KeyEncryptionKey]]
    :param bytes content:
        The encrypted blob content.
    :param int start_offset:
        The adjusted offset from the beginning of the *decrypted* content for the caller's data.
    :param int end_offset:
        The adjusted offset from the end of the *decrypted* content for the caller's data.
    :param Dict[str, Any] response_headers:
        A dictionary of response headers from the download request. Expected to include the
        'x-ms-meta-encryptiondata' header if the blob was encrypted.
    :return: The decrypted blob content.
    :rtype: bytes
    zx-ms-meta-encryptiondatazEncryption required, but received data does not contain appropriate metadata.Data was either not encrypted or metadata has been lost.Nz0Specified encryption algorithm is not supported.r   zx-ms-blob-typeFzcontent-ranger   r   -/r   r    TPageBlobz+Missing required metadata for Encryption V1r   r   )!r   r   	Exceptionr=   ro   rh   rU   rV   rW   ri   r   r   r   splitre   rm   r   r   r   r   r   r   r   r   rn   rb   ra   rc   	bytearrayr   r   r   extend)"rL   rN   r   r	  r   r   r
  r   r   r-   r   ru   	blob_typer   unpadcontent_range	end_range	blob_sizer   r   r   
total_sizerx   rb   ra   rc   r   decrypted_contentprocess_sizeencrypted_regionr   r   r   r   s"                                     r)   decrypt_blobr  Q  sV   L259IJd9e3fg  00EEI,88:N:Z:Z[[KLL..77G11IJJ5oGY[gh))$%56	"..,_=M *//4M)!,2237M)!,2237MM!,-IM!,-Ir!Sb\!"#,"$::IM)E 66B
"E:JKK)*@"E$$&	""7+i.@.@.BBSz**,Hoog.1B1B1DDG|S\J%>??**\
008JKK&<<II%;;GG$::EE
${2Z?%Kz!}j9L&vf|.CD %]l3E"2<="A23F#^^E3FMN$$^4l"F z!  !j99
E
FFA  KLQTU s   K
 
	K-K("K-(K-
should_padr   r   c                     d }d }| ;|9t        | |      }|j                         }|rt        d      j                         nd }||fS )Nr   )r   r  r   r   )r   r   r  r  r   r   s         r)   get_blob_encryptor_and_padderr    sR    
 IF
2>)#r2$$&	(2s""$fr,   c                    t        d|        t        d|       t        |       | j                  d      }|t        k(  rt	        j
                  d      }t	        j
                  d      }t        ||      }t        d      j                         }|j                  |      |j                         z   }|j                         }	|	j                  |      |	j                         z   }
nd|t        k(  rPt	        j
                  d      }d}t	        j
                  d      }t        |      }|j                  ||d      }||z   }
nt        d	      t!        |
      t#        ||||      d
}t%        |      S )a  
    Encrypts the given plain text message using the given protocol version.
    Wraps the generated content-encryption-key using the user-provided key-encryption-key (kek).
    Returns a json-formatted string containing the encrypted message and the encryption metadata.

    :param str message:
        The plain text message to be encrypted.
    :param KeyEncryptionKey key_encryption_key:
        The user-provided key-encryption-key. Must implement the following methods:
        wrap_key(key)
            - Wraps the specified key using an algorithm of the user's choice.
        get_key_wrap_algorithm()
            - Returns the algorithm used to wrap the specified symmetric key.
        get_kid()
            - Returns a string key id for this key-encryption-key.
    :param str version: The client encryption version to use.
    :return: A json-formatted string containing the encrypted message and the encryption metadata.
    :rtype: str
    r   rN   utf-8r   r    r   Nr   r   )EncryptedMessageContentsEncryptionData)r>   rG   r   r   r   r   r   r   r   r   r   r  r   r   r   r=   r   r   r   )r   rN   r   message_as_bytesru   r  r   r   r  r  r  r   r   cipertext_with_tagqueue_messages                  r)   encrypt_queue_messager'    s^   * y'*+-?@%&89 &nnW5))!#B "

2)*@BWX s""$mm$458II $$&	"))+69K9K9MM	+	+!#B $ 

2./ $^^E3CTJ!33 @AA 2?~1N'EFXF\F[FM(OPM r,   responser   c                 >   |j                   }	 t        |       }t        |d         }t        |d         }	 t        ||||      j                  d      S # t        t
        f$ r}|rt        d      || cY d}~S d}~ww xY w# t        $ r}	t        d||	      |	d}	~	ww xY w)a  
    Returns the decrypted message contents from an EncryptedQueueMessage.
    If no encryption metadata is present, will return the unaltered message.
    :param str message:
        The JSON formatted QueueEncryptedMessage contents with all associated metadata.
    :param Any response:
        The pipeline response used to generate an error with.
    :param bool require_encryption:
        If set, will enforce that the retrieved messages are encrypted and decrypt them.
    :param Optional[KeyEncryptionKey] key_encryption_key:
        The user-provided key-encryption-key. Must implement the following methods:
        wrap_key(key)
            - Wraps the specified key using an algorithm of the user's choice.
        get_key_wrap_algorithm()
            - Returns the algorithm used to wrap the specified symmetric key.
        get_kid()
            - Returns a string key id for this key-encryption-key.
    :param Optional[Callable[[str], KeyEncryptionKey]] resolver:
        The user-provided key resolver. Uses the kid string to return a key-encryption-key
        implementing the interface defined above.
    :return: The plain text message from the queue message.
    :rtype: str
    r#  r"  zEncryption required, but received message does not contain appropriate metatadata. Message was either not encrypted or metadata was incorrect.Nr!  zDecryption failed.)r   r(  error)
http_responser   r   r   r   r=   r   decoder  r   )
r   r(  rL   rN   r   deserialized_messager   decoded_datar   r*  s
             r)   decrypt_queue_messager/  2  s    < %%H/4W~23GHX3YZ-.BC].^_$o?QS[\ccdkll j! 	 NOTWX 	  $( $	$$s4   'A A? A<"A71A<7A<?	BBB)NN)Zr   r   r~   rQ   collectionsr   ior   jsonr   r   typingr   r   r	   r
   r   r   r   TypedOrderedDicttyping_extensionsr   cryptography.hazmat.backendsr   &cryptography.hazmat.primitives.ciphersr   +cryptography.hazmat.primitives.ciphers.aeadr   1cryptography.hazmat.primitives.ciphers.algorithmsr   ,cryptography.hazmat.primitives.ciphers.modesr   &cryptography.hazmat.primitives.paddingr   azure.core.exceptionsr   azure.core.utilsr   _versionr   _sharedr   r   azure.core.pipeliner   r   r   r   r   _ENCRYPTION_PROTOCOL_V2_1r   r   r   r   r   rE   (_ERROR_UNSUPPORTED_METHOD_FOR_ENCRYPTIONr"   r9   r>   rG   objectrI   rU   rZ   r`   rg   rl   rt   r8   re   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r'  r/  r'   r,   r)   <module>rD     s9    	 
  #  K J J 2 & 8 9 > A < 8 3 0  :4LE    ! 68OQjk 35NO )   [  )
x >3 >s >
k+; k
OV 
O 6   .% %0! !(*; *;Z6! 6!r-% - -% -E -&	mh&? 	mD 	m333  3 c3h	3
 
3D>S >c >c >*M4M4M4 M4 "/2	M4 8=U38_eTWY\T\o=]7^	M4`DcN x7P "# @Y ^a 48 8 8  UO8  	8 
 
#s(	#8 v14S> 1o 1h,% ,U ,v ,$ 6:@DC"$C" !12C" 8SE+;$;<=C" 	C"R 6:<@	BB$B !!12B x'7 789	B
 BJ;2u ;22B ;2S ;2UZ[^`e[eUf ;2|J !12JJ 8E?HUOXc]:;JDHG HG$%56HG x/?(?@AHG 	HG
 HG HG sCx.HG HGV	%  8+,h7G.HHI	 C 3 C <L C WZ C _b C L5$5$ 5$ 5$ !!12	5$
 x'7 7895$ 	5$r,   