
    &                         d 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 ddlmZ dZ G d de	j.                        Zy)z*Decrypt a ciphertext file using a raw key.    )absolute_import)division)unicode_literals)
exceptions)base)crc32c)e2e_integrity)flags)log)
console_io)files   c                   >    e Zd ZdZed        Zd Zd Zd Zd Z	d Z
y)	
RawDecrypta  Decrypt a ciphertext file using a raw key.

  `{command}` decrypts the given ciphertext file using the given CryptoKey
  containing a raw key and writes the result to the named plaintext file.
  The ciphertext file must not be larger than 64KiB.

  The supported algorithms are: `AES-128-GCM`, `AES-256-GCM`, `AES-128-CBC`,
  `AES-256-CBC`, `AES-128-CTR`, `and AES-256-CTR`.

  `AES-GCM` provides authentication which means that it accepts additional
  authenticated data (AAD). So, the flag `--additional-authenticated-data-file`
  is only valid with `AES-128-GCM` and `AES-256-GCM` algorithms. If AAD is
  provided during encryption, it must be provided during decryption too.
  The file must not be larger than 64KiB.

  If `--plaintext-file` or `--additional-authenticated-data-file` or
  `--initialization-vector-file` is set to '-', that file is read from stdin.
  Similarly, if `--ciphertext-file` is set to '-', the ciphertext is written
  to stdout.

  By default, the command performs integrity verification on data sent to and
  received from Cloud KMS. Use `--skip-integrity-verification` to disable
  integrity verification.

  ## EXAMPLES
  The following command reads and decrypts the file `path/to/input/ciphertext`.
  The file will be decrypted using the CryptoKey `KEYNAME` containing a raw key,
  from the KeyRing `KEYRING` in the `global` location. It uses the additional
  authenticated data file `path/to/input/aad` (only valid with the `AES-GCM`
  algorithms) and the initialization vector file `path/to/input/iv`.
  The resulting plaintext will be written to `path/to/output/plaintext`.

    $ {command} \
        --key=KEYNAME \
        --keyring=KEYRING \
        --location=global \
        --ciphertext-file=path/to/input/ciphertext \
        --additional-authenticated-data-file=path/to/input/aad \
        --initialization-vector-file=path/to/input/iv \
        --plaintext-file=path/to/output/plaintext
  c                 6   t        j                  | d       t        j                  | dd       t        j                  | d       t        j                  | d       t        j
                  | d       t        j                  |        t        j                  |        y )Nz$The (raw) key to use for decryption.zto use for decryptionTzto store the decrypted dataz
to decryptzfor decryption)r
   AddKeyResourceFlagsAddCryptoKeyVersionFlagAddPlaintextFileFlagAddCiphertextFileFlagAddIvFileFlagAddAadFileFlagAddSkipIntegrityVerification)parsers    lib/surface/kms/raw_decrypt.pyArgszRawDecrypt.ArgsN   st    	f&LM	!!&*A4H	v'DE	5	 01	 	&&v.    c                     t        j                  |d      }t        |      |kD  r%t        j                  dj                  ||            |S )NT)binaryz<The file [{0}] is larger than the maximum size of {1} bytes.)r   ReadFromFileOrStdinlenr   BadFileExceptionformat)selfpath	max_bytesdatas       r   _ReadFileOrStdinzRawDecrypt._ReadFileOrStdinX   sM    ))$t<D
4y9''
H
O
OI 
 Kr   c                     |j                    S )N)skip_integrity_verification)r#   argss     r   _PerformIntegrityVerificationz(RawDecrypt._PerformIntegrityVerificationb   s    ////r   c                    |j                   dk(  r%|j                  dk(  rt        j                  dd      |j                   dk(  r%|j                  dk(  rt        j                  dd      |j                  dk(  r%|j                  dk(  rt        j                  dd      	 | j                  |j                   d      }	 | j                  |j                  t              }t        |      t        k7  r)t        j                  d
dj                  t                    d}|j                  r	 | j                  |j                  d      }t        j                  |      }t        j                         }|j!                  |j#                               }| j%                  |      r]t'        j(                  |      }	t'        j(                  |      }
t'        j(                  |      }|j+                  ||||	|
|      |_        |S |j+                  |||      |_        |S # t        j                  $ r4}t        j                  dj                  |j                   |            d }~ww xY w# t        j                  $ r4}t        j                  d	j                  |j                  |            d }~ww xY w# t        j                  $ r4}t        j                  dj                  |j                  |            d }~ww xY w)N-z2--ciphertext-file and --initialization-vector-filez)both parameters can't be read from stdin.z:--ciphertext-file and --additional-authenticated-data-filezE--initialization-vector-file and --additional-authenticated-data-filei   )r%   z)Failed to read ciphertext file [{0}]: {1}z4Failed to read initialization vector file [{0}]: {1}z--initialization-vector-filezthe IV size must be {0} bytes.r   i   z<Failed to read additional authenticated data file [{0}]: {1})name)
ciphertextinitializationVectoradditionalAuthenticatedDataciphertextCrc32cinitializationVectorCrc32c!additionalAuthenticatedDataCrc32c)r/   r0   r1   )ciphertext_fileinitialization_vector_filer   InvalidArgumentException"additional_authenticated_data_filer'   r   Errorr!   r"   CBC_CTR_IV_SIZEr    r
   ParseCryptoKeyVersionNamecloudkms_baseGetMessagesModuleMCloudkmsProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsRawDecryptRequestRelativeNamer+   r   Crc32cRawDecryptRequestrawDecryptRequest)r#   r*   r/   eivaadcrypto_key_refmessagesrequestciphertext_crc32c	iv_crc32c
aad_crc32cs               r   _CreateRawDecryptRequestz#RawDecrypt._CreateRawDecryptRequeste   s   s"t'F'F#'M//
>
5  	#33s://
F
5  	''3.33s://2
5  ((


) ) j
  

)
)_ ! b 2w/!''
(
*
1
1/
B 
 C..	
##33u $ 
 44T:N..0Hdd((* e G
 ))$/ --
3--#i==%j"*"<"<!&),%.,6 #= #g N #+"<"<!&) #= #g NA ;; ''
5
<
<""A  ;; ''
@
G
G--q ( [[ 
))JVD;;Q?
 	

sH   H <!I  'J* I)/II J'3/J""J'*K1=/K,,K1c                    |j                   s't        j                  t        j                               |j                  s't        j                  t        j                               |j
                  s't        j                  t        j                               t        j                  |j                  |j                        s't        j                  t        j                               y)z&Verifies integrity fields in response.N)verifiedCiphertextCrc32cr	   $ClientSideIntegrityVerificationError'GetRequestToServerCorruptedErrorMessage)verifiedAdditionalAuthenticatedDataCrc32c"verifiedInitializationVectorCrc32cr   Crc32cMatches	plaintextplaintextCrc32c*GetResponseFromServerCorruptedErrorMessage)r#   resps     r   _VerifyResponseIntegrityFieldsz)RawDecrypt._VerifyResponseIntegrityFields   s     ((>>

?
?
A 
 99>>

?
?
A 
 22>>

?
?
A 
 0D0DE>>

B
B
D  Fr   c                    d }| j                  |      }t        j                         }	 |j                  j	                  |      }| j                  |      r| j                  |       	 |j                  ?t        j                  |j                        5  	 d d d        t        j                   d       y t        j"                  |j                  |j                  dd       y # t
        j                  $ r}t        j                  |       Y d }~d }~ww xY w# 1 sw Y   xY w# t        j$                  $ r}t'        j(                  |      d }~ww xY w)NzDecrypted file is emptyT)r   	overwrite)rL   r<   GetClientInstance8projects_locations_keyRings_cryptoKeys_cryptoKeyVersionsr   apitools_exceptionsHttpBadRequestErrorr	   ProcessHttpBadRequestErrorr+   rX   rT   r   
FileWriterplaintext_filer   PrintWriteToFileOrStdoutr9   r   r!   )r#   r*   responserH   clienterrorrC   s          r   RunzRawDecrypt.Run   s   H++D1G,,.F6PP[[
h ))$/
))(3+				#d112
 3 			+,!3!3DD	
 22 6..u556 32 ;; +''**+sM   C  '+D! DD! 2-D!  D3DDDD! !E4E		EN)__name__
__module____qualname____doc__staticmethodr   r'   r+   rL   rX   rg    r   r   r   r   #   s7    (T / /0aF6+r   r   N)rk   
__future__r   r   r   apitools.base.pyr   r]   googlecloudsdk.api_lib.cloudkmsr   r<   googlecloudsdk.calliopegooglecloudsdk.command_lib.kmsr   r	   r
   googlecloudsdk.corer   googlecloudsdk.core.consoler   googlecloudsdk.core.utilr   r:   Commandr   rm   r   r   <module>rw      sH    1 &  ' > A ( . 1 8 0 # 2 *[+ [+r   