
    w,                         d Z ddlmZ ddlmZ ddlmZ ddl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
j0                        Zy)z)Encrypt a plaintext file using a raw key.    )absolute_import)division)unicode_literalsN)
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)	
RawEncrypta(  Encrypt a plaintext file using a raw key.

  Encrypts the given plaintext file using the given CryptoKey containing a raw
  key and writes the result to the named ciphertext file.
  The plaintext file must not be larger than 64KiB.
  For the AES-CBC algorithms, no server-side padding is being done,
  so the plaintext must be a multiple of the block size.

  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.

  The initialization vector (flag `--initialization-vector-file`) is only
  supported for `AES-CBC` and `AES-CTR` algorithms, and must be 16B in length.

  Therefore, both additional authenticated data and initialization vector can't
  be provided during encryption. If an additional authenticated data file is
  provided, its contents must also be provided during decryption.
  The file must not be larger than 64KiB.

  The flag `--version` indicates the version of the key to use for
  encryption.

  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 encrypts the file `path/to/input/plaintext`.
  The file will be encrypted using the `AES-GCM` CryptoKey `KEYNAME` from the
  KeyRing `KEYRING` in the `global` location using the additional authenticated
  data file `path/to/input/aad`.
  The resulting ciphertext will be written to `path/to/output/ciphertext`.

    $ {command} \
        --key=KEYNAME \
        --keyring=KEYRING \
        --location=global \
        --plaintext-file=path/to/input/plaintext \
        --additional-authenticated-data-file=path/to/input/aad \
        --ciphertext-file=path/to/output/ciphertext

  The following command reads and encrypts the file `path/to/input/plaintext`.
  The file will be encrypted using the `AES-CBC` CryptoKey `KEYNAME` from the
  KeyRing `KEYRING` in the `global` location using the initialization vector
  stored at `path/to/input/aad`.
  The resulting ciphertext will be written to `path/to/output/ciphertext`.

    $ {command} \
        --key=KEYNAME \
        --keyring=KEYRING \
        --location=global \
        --plaintext-file=path/to/input/plaintext \
        --initialization-vector-file=path/to/input/iv \
        --ciphertext-file=path/to/output/ciphertext
  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 key to use for encryption.zto use for encryptionTz
to encryptz	to outputzfor encryption)r
   AddKeyResourceFlagsAddCryptoKeyVersionFlagAddPlaintextFileFlagAddCiphertextFileFlagAddIvFileFlagAddAadFileFlagAddSkipIntegrityVerification)parsers    lib/surface/kms/raw_encrypt.pyArgszRawEncrypt.Argsf   ss    	f&FG	!!&*A4H	v|4	4	 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RawEncrypt._ReadFileOrStdinp   sM    ))$t<D
4y9''
H
O
OI 
 Kr   c                     |j                    S )N)skip_integrity_verification)r#   argss     r   _PerformIntegrityVerificationz(RawEncrypt._PerformIntegrityVerificationz   s    ////r   c                    |j                   r"|j                  rt        j                  dd      |j                  dk(  r4|j                   dk(  s|j                  dk(  rt        j                  dd      	 | j                  |j                  d      }d	}|j                  r	 | j                  |j                  d      }d	}|j                   r]	 | j                  |j                   t              }t        |      t        k7  r)t        j                  ddj                  t                    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)NzE--initialization-vector-file and --additional-authenticated-data-filez2both parameters cannot be provided simultaneously.-z--plaintext-filez.multiple parameters cannot be read from stdin.i   )r%   z(Failed to read plaintext file [{0}]: {1}r   z<Failed to read additional authenticated data file [{0}]: {1}z4Failed to read initialization vector file [{0}]: {1}z--initialization-vector-filezthe IV size must be {0} bytes.)name)	plaintextinitializationVectoradditionalAuthenticatedDataplaintextCrc32cinitializationVectorCrc32c!additionalAuthenticatedDataCrc32c)r/   r0   r1   )initialization_vector_file"additional_authenticated_data_filer   InvalidArgumentExceptionplaintext_filer'   r   Errorr!   r"   CBC_CTR_IV_SIZEr    r
   ParseCryptoKeyVersionNamecloudkms_baseGetMessagesModuleMCloudkmsProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsRawEncryptRequestRelativeNamer+   r   Crc32cRawEncryptRequestrawEncryptRequest)r#   r*   r/   eaadivcrypto_key_refmessagesreqplaintext_crc32c	iv_crc32c
aad_crc32cs               r   _CreateRawEncryptRequestz#RawEncrypt._CreateRawEncryptRequest}   s   ''33//2
>  c!''3.22c9//
N ''(;(;u'Mi C..	
##33u $ 
 
B&&

""++ # 
 
RO	#))*,33OD
 	

 44T:N..0H

`
`((* a C
 ))$/y1--#i==%j&88!&)*%.,6 9 c J '88!&) 9 c JE ;; ''
4
;
;!!1  [[ 
))JVD;;Q?
 	

 [[ 
))BII//
 	

sH   3G9 I !J 9I /H;;I J
/JJ
K /KKc                    |j                   |j                   k7  r=t        j                  t        j                  |j                   |j                               |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)a  Verifies integrity fields in RawEncryptResponse.

    Note: This methods assumes that self._PerformIntegrityVerification() is True
    and that all request CRC32C fields were pupolated.
    Args:
      req:
        messages.CloudkmsProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsRawEncryptRequest()
        object
      resp: messages.RawEncryptResponse() object.

    Returns:
      Void.
    Raises:
      e2e_integrity.ServerSideIntegrityVerificationError if the server reports
      request integrity verification error.
      e2e_integrity.ClientSideIntegrityVerificationError if response integrity
      verification fails.
    N)r.   r	   ResourceNameVerificationError#GetResourceNameMismatchErrorMessageverifiedPlaintextCrc32c$ClientSideIntegrityVerificationError'GetRequestToServerCorruptedErrorMessage)verifiedAdditionalAuthenticatedDataCrc32c"verifiedInitializationVectorCrc32cr   Crc32cMatches
ciphertextciphertextCrc32c*GetResponseFromServerCorruptedErrorMessage)r#   rH   resps      r   _VerifyResponseIntegrityFieldsz)RawEncrypt._VerifyResponseIntegrityFields   s    * xx49977

;
;CHHdii
P 
 ''>>

?
?
A 
 99>>

?
?
A 
 22>>

?
?
A 
 1F1FG>>

B
B
D  Hr   c                    t        j                         }| j                  |      }d }	 |j                  j	                  |      }| j                  |      r| j                  ||       	 t        j                  |j                  |j                  dd       |j                  sS|j                   rFdt#        t%        j&                               d d z   }t)        j*                  ||j                   d       y y y # t
        j                  $ r}t        j                  |       Y d }~d }~ww xY w# t(        j,                  $ r}t/        j0                  |      d }~ww xY w)NT)r   	overwritez./inialization_vector_   )r\   )r<   GetClientInstancerL   8projects_locations_keyRings_cryptoKeys_cryptoKeyVersionsr   apitools_exceptionsHttpBadRequestErrorr	   ProcessHttpBadRequestErrorr+   rZ   r   WriteToFileOrStdoutciphertext_filerV   r5   r0   struuiduuid4r   WriteBinaryFileContentsr9   r   r!   )r#   r*   clientrH   rY   erroriv_file_namerC   s           r   RunzRawEncrypt.Run	  s-   ,,.F

'
'
-CD6LLWW
d ))$/
))#t4+	



 ,,1J1J/#djjl2CBQ2GG%%%%	
 2K, 22 6..u556& ;; +''**+s0   C5 (B
D* 5D'D""D'*E=EEN)__name__
__module____qualname____doc__staticmethodr   r'   r+   rL   rZ   rl    r   r   r   r   $   s8    ?B / /0Xt0d+r   r   )rp   
__future__r   r   r   rf   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   rr   r   r   <module>r|      sK    0 &  '  > A ( . 1 8 0 # 2 *C+ C+r   