
    h]                     4   S SK r S SKJr  S SKr S SKJr  S SKJs  J	r
  S SKJrJr  SrSrSrSrSr\ R(                  R*                  \ R(                  R                  /r\ R.                  " S	S
9S 5       r\ R.                  " S	S
9S 5       rS rS rS rS rS rS rS r S r!S r"S r#S r$S r%S r&S r'S r(S r)S r*S r+S r,\ R(                  R[                  S S!9S" 5       r.\ R(                  R[                  S#S!9S$ 5       r/S% r0S& r1S' r2g! \ a    SrSr
 Nf = f)(    N)	timedelta)InMemoryKmsClientverify_file_encryptedzencrypted_table.in_mem.parquets   0123456789112345
footer_keys   1234567890123450col_keymodule)scopec                      [         R                  R                  [         R                  " / SQ5      [         R                  " / SQ5      [         R                  " / SQ5      S.5      n U $ )N)         )abc)xyz)paTablefrom_pydictarray)
data_tables    _/home/james-whalen/.local/lib/python3.13/site-packages/pyarrow/tests/parquet/test_encryption.pyr   r   0   sG    %%XXi XXo&XXo&' J
     c                  H    [         R                  " [        [        SS/0S9n U $ )Nr   r   )r   column_keys)peEncryptionConfigurationFOOTER_KEY_NAMECOL_KEY_NAME)basic_encryption_configs    r   r!   r!   :   s,     88"3*

 #"r   c                 b    [         R                  " U S9nS n[         R                  " U5      nX4$ )zy
Sets up and returns the KMS connection configuration and crypto factory
based on provided KMS configuration parameters.
custom_kms_confc                     [        U 5      $ Nr   kms_connection_configurations    r   kms_factory1setup_encryption_environment.<locals>.kms_factoryK        !=>>r   )r   KmsConnectionConfigCryptoFactory)r$   kms_connection_configr*   crypto_factorys       r   setup_encryption_environmentr1   D   s5    
 22?S? %%k2N 00r   c                     X$R                  S5      X5R                  S5      0n[        U5      u  p[        XUX5        X4$ )zD
Writes an encrypted parquet file based on the provided parameters.
UTF-8)decoder1   write_encrypted_parquet)
pathr   footer_key_namecol_key_namer   r   encryption_configr$   r/   r0   s
             r   write_encrypted_filer:   T   sW     	**73nnW-O -I-) D.?1C !00r   c           	      f   U [         -  n[        R                  " [        [        SS/0S[        SS9SS9nUR                  SL d   e[        X![        [        [        [        U5      u  pE[        U5        [        R                  " [        SS9S	9n[        X&XE5      nUR                  U5      (       d   eg
)DWrite an encrypted parquet, verify it's encrypted, and then read it.r   r   
AES_GCM_V1      @minutes   r   r   encryption_algorithmcache_lifetimedata_key_length_bitsFrD   N)PARQUET_NAMEr   r   r   r    r   uniform_encryptionr:   
FOOTER_KEYCOL_KEYr   DecryptionConfigurationread_encrypted_parquetequalstempdirr   r6   r9   r/   r0   decryption_configresult_tables           r   !test_encrypted_parquet_write_readrR   j   s    \!D
 22"3*
 * - " //5888,@/<W-) $ 22 -/)!6HL\****r   c           	      N   U [         -  n[        R                  " [        SS[	        SS9SS9nUR
                  SL d   e[        X![        [        [        SU5      u  pE[        U5        [        R                  " [	        SS9S9n[        X&XE5      nUR                  U5      (       d   eg	)
r<   Tr=   r>   r?   rA   )r   rH   rC   rD   rE   r   rF   N)rG   r   r   r   r   rH   r:   r    rI   r   rK   rL   rM   rN   s           r   )test_uniform_encrypted_parquet_write_readrT      s    \!D 22") - " //4777,@/<S-) $ 22 -/)!6HL\****r   c                     UR                  X25      nUc   e[        R                  " XR                  US9 nUR	                  U5        S S S 5        g ! , (       d  f       g = f)N)encryption_properties)file_encryption_propertiespqParquetWriterschemawrite_table)r6   tabler9   r/   r0   rW   writers          r   r5   r5      s[    !/!J!J"2%111			,,"<
>AG5!
> 
> 
>s   A
Ac                    UR                  X!5      nUc   e[        R                  " XS9nUR                  S:X  d   e[        R                  " XS9n[        UR                  5      S:X  d   e[        R                  " XS9nUR                  SS9$ )Ndecryption_propertiesr   Tuse_threads)	file_decryption_propertiesrX   read_metadatanum_columnsread_schemalennamesParquetFileread)r6   rP   r/   r0   rc   metarZ   results           r   rL   rL      s    !/!J!J"2%111@Dq   ^^@Fv||!!!^^@F;;4;((r   c           	         U [         -  n[        R                  " [        [        SS/0S[        SS9SS9n[        X![        [        [        [        U5        [        U5        [        [        [        R                  S5      [        [        R                  S5      05      u  pE[        R                  " [        SS9S	9n[        R                  " [        S
S9   [!        X&UU5        SSS5        g! , (       d  f       g= f)zUWrite an encrypted parquet, verify it's encrypted,
and then read it using wrong keys.r   r   r=   r>   r?   rA   rB   r3   rF   zIncorrect master key usedmatchN)rG   r   r   r   r    r   r:   rI   rJ   r   r1   r4   rK   pytestraises
ValueErrorrL   )rO   r   r6   r9   wrong_kms_connection_configwrong_crypto_factoryrP   s          r   +test_encrypted_parquet_write_read_wrong_keyru      s     \!D
 22"3*
 * - " ?L#W.?A $8T0j''0V 95
 22 -/	z)E	F%@ 	" 
G	F	Fs   C**
C8c                     [        X5        [        R                  " [        SS9   [        R
                  " U [        -  5      R                  5         SSS5        g! , (       d  f       g= f)ziWrite an encrypted parquet, verify it's encrypted,
but then try to read it without decryption properties.no decryptionrn   N)rR   rp   rq   IOErrorrX   ri   rG   rj   rO   r   s     r   0test_encrypted_parquet_read_no_decryption_configrz      sA     &g:	w&6	7
w-.335 
8	7	7s   ,A
A(c                     [        X5        [        R                  " [        SS9   [        R
                  " U [        -  5        SSS5        g! , (       d  f       g= f)zsWrite an encrypted parquet, verify it's encrypted,
but then try to read its metadata without decryption properties.rw   rn   N)rR   rp   rq   rx   rX   rd   rG   ry   s     r   9test_encrypted_parquet_read_metadata_no_decryption_configr|      s:     &g:	w&6	7
</0 
8	7	7   A
Ac                     [        X5        [        R                  " [        SS9   [        R
                  " U [        -  5        SSS5        g! , (       d  f       g= f)zqWrite an encrypted parquet, verify it's encrypted,
but then try to read its schema without decryption properties.rw   rn   N)rR   rp   rq   rx   rX   rf   rG   ry   s     r   7test_encrypted_parquet_read_schema_no_decryption_configr      s8     &g:	w&6	7
w-. 
8	7	7r}   c           
          U S-  n[         R                  " [        S9n[        R                  " [
        SS9   [        X![        [        [        SU5        SSS5        g! , (       d  f       g= f)IWrite an encrypted parquet, but give only footer key,
without column key.z)encrypted_table_no_col_key.in_mem.parquetr   z4Either column_keys or uniform_encryption must be setrn   r   N)	r   r   r   rp   rq   OSErrorr:   r    rI   rO   r   r6   r9   s       r   'test_encrypted_parquet_write_no_col_keyr      sc     @@D 22"$ 
w%
& 	T'.?	A	
& 
& 
&s   A
A+c           
          U S-  n[         R                  " [        [        SS/0SS9n[        R
                  " [        SS9   [        X![        [        [        SU5        S	S	S	5        g	! , (       d  f       g	= f)
r   z=encrypted_table_col_key_and_uniform_encryption.in_mem.parquetr   r   T)r   r   rH   z2Cannot set both column_keys and uniform_encryptionrn   r   N)	r   r   r   r    rp   rq   r   r:   rI   r   s       r   ;test_encrypted_parquet_write_col_key_and_uniform_encryptionr     sx     TTD 22"3*
  ! 
wR
T 	T'.?	A
T 
T 
Ts   A''
A5c                     U S-  nUn[         R                  " 5       nS n[         R                  " U5      n[        R                  " [
        SS9   [        X1UXW5        SSS5        g! , (       d  f       g= f)<Write an encrypted parquet, but raise KeyError in KmsClient.(encrypted_table_kms_error.in_mem.parquetc                     [        U 5      $ r&   r'   r(   s    r   r*   ;test_encrypted_parquet_write_kms_error.<locals>.kms_factory-  s     !!=>>r   r   rn   N)r   r-   r.   rp   rq   KeyErrorr5   rO   r   r!   r6   r9   r/   r*   r0   s           r   &test_encrypted_parquet_write_kms_errorr   $  sh     ??D/ 224?
 %%k2N	x|	42C 5	G 
5	4	4   A&&
A4c                 (  ^ U S-  nUn[         R                  " 5       n " S S[         R                  5      mU4S jn[         R                  " U5      n[        R
                  " [        SS9   [        X1UXW5        SSS5        g! , (       d  f       g= f)r   r   c                   *    \ rS rSrSrS rS rS rSrg)Jtest_encrypted_parquet_write_kms_specific_error.<locals>.ThrowingKmsClientiB  zFA KmsClient implementation that throws exception in
wrap/unwrap calls
c                 N    [         R                  R                  U 5        Xl        g)z%Create an InMemoryKmsClient instance.N)r   	KmsClient__init__configselfr   s     r   r   Stest_encrypted_parquet_write_kms_specific_error.<locals>.ThrowingKmsClient.__init__G  s    LL!!$' Kr   c                     [        S5      e)NCannot Wrap Keyrr   r   	key_bytesmaster_key_identifiers      r   wrap_keyStest_encrypted_parquet_write_kms_specific_error.<locals>.ThrowingKmsClient.wrap_keyL  s    .//r   c                     [        S5      e)NzCannot Unwrap Keyr   r   wrapped_keyr   s      r   
unwrap_keyUtest_encrypted_parquet_write_kms_specific_error.<locals>.ThrowingKmsClient.unwrap_keyO  s    011r   )r   N	__name__
__module____qualname____firstlineno____doc__r   r   r   __static_attributes__ r   r   ThrowingKmsClientr   B  s    		!
	0	2r   r   c                    > T" U 5      $ r&   r   )r)   r   s    r   r*   Dtest_encrypted_parquet_write_kms_specific_error.<locals>.kms_factoryR  s     !=>>r   r   rn   N)r   r-   r   r.   rp   rq   rr   r5   )	rO   r   r!   r6   r9   r/   r*   r0   r   s	           @r   /test_encrypted_parquet_write_kms_specific_errorr   9  sz     ??D/ 2242BLL 2 ? %%k2N	z):	;2C 5	G 
<	;	;s   ,B
Bc                     U S-  nUn[         R                  " 5       nS n[         R                  " U5      n[        R                  " [
        SS9   [        X1UXW5        SSS5        g! , (       d  f       g= f)z@Write an encrypted parquet, but raise ValueError in kms_factory.0encrypted_table_kms_factory_error.in_mem.parquetc                     [        S5      e)NCannot create KmsClientr   r(   s    r   r*   Ctest_encrypted_parquet_write_kms_factory_error.<locals>.kms_factoryf  s    233r   r   rn   N)r   r-   r.   rp   rq   rr   r5   r   s           r   .test_encrypted_parquet_write_kms_factory_errorr   ]  sq     GGD/ 2244 %%k2N	z6
8 	 2C 5	G
8 
8 
8r   c                   ^ U S-  nUn[         R                  " 5       n " S S5      mU4S jn[         R                  " U5      n[        R                  " [
        5         [        X1UXW5        SSS5        g! , (       d  f       g= f)z[Write an encrypted parquet, but use wrong KMS client type
that doesn't implement KmsClient.r   c                   *    \ rS rSrSrS rS rS rSrg)Otest_encrypted_parquet_write_kms_factory_type_error.<locals>.WrongTypeKmsClienti{  z4This is not an implementation of KmsClient.
        c                 &    UR                   U l        g r&   )r$   master_keys_mapr   s     r   r   Xtest_encrypted_parquet_write_kms_factory_type_error.<locals>.WrongTypeKmsClient.__init__  s    #)#9#9D r   c                     g r&   r   r   s      r   r   Xtest_encrypted_parquet_write_kms_factory_type_error.<locals>.WrongTypeKmsClient.wrap_key      r   c                     g r&   r   r   s      r   r   Ztest_encrypted_parquet_write_kms_factory_type_error.<locals>.WrongTypeKmsClient.unwrap_key  r   r   )r   Nr   r   r   r   WrongTypeKmsClientr   {  s    		:		r   r   c                    > T" U 5      $ r&   r   )r)   r   s    r   r*   Htest_encrypted_parquet_write_kms_factory_type_error.<locals>.kms_factory  s    !">??r   N)r   r-   r.   rp   rq   	TypeErrorr5   )	rO   r   r!   r6   r9   r/   r*   r0   r   s	           @r   3test_encrypted_parquet_write_kms_factory_type_errorr   q  sr     GGD/ 224 @ %%k2N	y	!2C 5	G 
"	!	!s   A55
Bc                  6   S n [         R                  " [        [        SS/0SSS[	        SS9SS	S
9nU " U5        [         R                  " [        S9n[        SS/0Ul        SUl        SUl        SUl        [	        SS9Ul	        SUl
        S	Ul        U " U5        g )Nc                 R   [         U R                  :X  d   eSS/U R                  [           :X  d   eSU R                  :X  d   eU R
                  (       d   eU R                  (       a   e[        SS9U R                  :X  d   eU R                  (       a   eSU R                  :X  d   eg )Nr   r   AES_GCM_CTR_V1      $@r?      )r   r   r   r    rC   plaintext_footerdouble_wrappingr   rD   internal_key_materialrE   )r9   s    r   !validate_encryption_configurationZtest_encrypted_parquet_encryption_configuration.<locals>.validate_encryption_configuration  s    "3">">>>>Sz.::<HHHH#4#I#IIII 1111$4444&*;*J*JJJJ$::::'<<<<<r   r   r   r   TFr   r?   r   )r   r   rC   r   r   rD   r   rE   r   )r   r   r   r    r   r   rC   r   r   rD   r   rE   )r   r9   encryption_config_1s      r   /test_encrypted_parquet_encryption_configurationr     s    = 22"!C:0- .# 	 &&7844"$'3c3Z&B#/?,+/(*/')24)@&05-/2,%&9:r   c                      [         R                  " [        SS9S9n [        SS9U R                  :X  d   e[         R                  " 5       n[        SS9Ul        [        SS9UR                  :X  d   eg )Nr   r?   rF   )r   rK   r   rD   )rP   decryption_config_1s     r   /test_encrypted_parquet_decryption_configurationr     sl    22 .0T"&7&F&FFFF446)24)@&T"&9&H&HHHHr   c                      S n [         R                  " SSSSSS.S9nU " U5        [         R                  " 5       nSUl        SUl        SUl        SSS.Ul        U " U5        g )	Nc                     SU R                   :X  d   eSU R                  :X  d   eSU R                  :X  d   eSSS.U R                  :X  d   eg )N	Instance1URL1MyTokenkey_material_1key_material_2key1key2kms_instance_idkms_instance_urlkey_access_tokenr$   )r/   s    r   validate_kms_connection_configPtest_encrypted_parquet_kms_configuration.<locals>.validate_kms_connection_config  sb    3CCCCC.?????1BBBBB)3CD%556 	7 6r   r   r   r   r   r   r   r   )r   r-   r   r   r   r$   )r   r/   kms_connection_config_1s      r   (test_encrypted_parquet_kms_configurationr     s    7 22#"$$
	 ##89 446.9+/5,/8,  /+ ##:;r   zNPlaintext footer - reading plaintext column subset reads encrypted columns too)reasonc                 4   U [         -  n[        R                  " [        [        SS/0SSS9n[        R
                  " [        [        R                  S5      [        [        R                  S5      0S9nS n[        R                  " U5      n[        X!UXF5        g	)
zWrite an encrypted parquet, with plaintext footer
and with single wrapping,
verify it's encrypted, and then read plaintext columns.r   r   TF)r   r   r   r   r3   r#   c                     [        U 5      $ r&   r'   r(   s    r   r*   Stest_encrypted_parquet_write_read_plain_footer_single_wrapping.<locals>.kms_factory  r,   r   N)rG   r   r   r   r    r-   rI   r4   rJ   r.   r5   rO   r   r6   r9   r/   r*   r0   s          r   >test_encrypted_parquet_write_read_plain_footer_single_wrappingr     s     \!D
 22"3*
  22Z..w7'..1
? %%k2ND.?1Cr   z'External key material not supported yetc                     U [         -  n[        R                  " [        0 SS9n[        R                  " [        [
        R                  S5      0S9nS n[        R                  " U5      n[        X!UXF5        g)ztWrite an encrypted parquet, with external key
material.
Currently it's not implemented, so should throw
an exceptionF)r   r   r   r3   r#   c                     [        U 5      $ r&   r'   r(   s    r   r*   :test_encrypted_parquet_write_external.<locals>.kms_factory  r,   r   N)	rG   r   r   r   r-   rI   r4   r.   r5   r   s          r   %test_encrypted_parquet_write_externalr     sx     \!D 22"#%
 22(**;*;G*DE? %%k2ND.?1Cr   c           	      l   U [         -  n[        X1[        [        [        [
        U5      u  pE[        U5        [        R                  " [        SS9S9n[        S5       HT  nUR                  XF5      nUc   e[        R                  " X8S9n	U	R                  SS9n
UR                  U
5      (       a  MT   e   g)	z\Write an encrypted parquet, verify it's encrypted,
and then read it multithreaded in a loop.r>   r?   rF   2   Nr_   Tra   )rG   r:   r   r    rI   rJ   r   r   rK   r   rangerc   rX   ri   rj   rM   )rO   r   r!   r6   r/   r0   rP   irc   rl   rQ   s              r   test_encrypted_parquet_loopr      s     \!D
 -A/<W-!) $22 -/ 2Y%3%N%N!&6")555D{{t{4  .... r   c           	      @   U [         -  n[        X1[        [        [        [
        U5      u  pE[        U5        [        R                  " [        SS9S9nUR                  XF5      nA[        R                  " X7S9nUR                  SS9n	UR                  U	5      (       d   eg)zV
Test that decryption properties can be used if the crypto factory is no longer alive
r>   r?   rF   r_   Tra   N)rG   r:   r   r    rI   rJ   r   r   rK   r   rc   rX   ri   rj   rM   )
rO   r   r!   r6   r/   r0   rP   rc   rl   rQ   s
             r   %test_read_with_deleted_crypto_factoryr   =  s     \!D,@/<W-!) $ 22 -/!/!J!J"2^^@F;;4;0L\****r   c           	      b   U [         -  n[        X1[        [        [        [
        U5      u  pE[        R                  " [        SS9S9nUR                  XF5      n[        R                  " X7S9nUR                  U5      (       d   e[        R                  " XS9nUR                  U5      (       d   eg)z>Write an encrypted parquet then read it back using read_table.r>   r?   rF   r_   N)rG   r:   r   r    rI   rJ   r   rK   r   rc   rX   
read_tablerM   )	rO   r   r!   r6   r/   r0   rP   rc   rQ   s	            r   !test_encrypted_parquet_read_tabler   U  s    \!D -A/<W-!) 22 -/!/!J!J"2 ==XL \**** ==CL\****r   )3rp   datetimer   pyarrowr   pyarrow.parquetparquetrX   pyarrow.parquet.encryption
encryptionr    pyarrow.tests.parquet.encryptionr   r   ImportErrorrG   rI   r   rJ   r    markparquet_encryption
pytestmarkfixturer   r!   r1   r:   rR   rT   r5   rL   ru   rz   r|   r   r   r   r   r   r   r   r   r   r   xfailr   r   r   r   r   r   r   r   <module>r     s  "   2 ++
2 0 

 KK""
KK
 h   h#  #1 1,+>+6")" "F61/A"A(G*!GHG(GB ;FI<:  2 3C3CN CDC EC4/:+0+{  	B	Bs   D
 

DD