diff --git a/tools/testing/cross_language/aead_test.sh b/tools/testing/cross_language/aead_test.sh index 230048295081c26518ea413e44e17bc6338abefb..e681f711e886ca266f77a34438beb468493a5977 100755 --- a/tools/testing/cross_language/aead_test.sh +++ b/tools/testing/cross_language/aead_test.sh @@ -15,6 +15,8 @@ ROOT_DIR="$TEST_SRCDIR/tink" CC_AEAD_CLI="$ROOT_DIR/tools/testing/cc/aead_cli_cc" +PY2_AEAD_CLI="" # placeholder, please ignore +PY3_AEAD_CLI="" # placeholder, please ignore GO_AEAD_CLI="$ROOT_DIR/tools/testing/go/aead_cli_go" JAVA_AEAD_CLI="$ROOT_DIR/tools/testing/aead_cli_java" TEST_UTIL="$ROOT_DIR/tools/testing/cross_language/test_util.sh" @@ -164,13 +166,13 @@ aead_gcp_test() { ############################################################################# ##### Run the actual tests. KEY_TEMPLATES=(AES128_GCM AES256_GCM AES128_CTR_HMAC_SHA256 AES256_CTR_HMAC_SHA256) -ENCRYPT_CLIS=($CC_AEAD_CLI $JAVA_AEAD_CLI $GO_AEAD_CLI) -DECRYPT_CLIS=($CC_AEAD_CLI $JAVA_AEAD_CLI $GO_AEAD_CLI) +ENCRYPT_CLIS=($CC_AEAD_CLI $JAVA_AEAD_CLI $GO_AEAD_CLI $PY2_AEAD_CLI $PY3_AEAD_CLI) +DECRYPT_CLIS=($CC_AEAD_CLI $JAVA_AEAD_CLI $GO_AEAD_CLI $PY2_AEAD_CLI $PY3_AEAD_CLI) aead_basic_test "${ENCRYPT_CLIS[*]}" "${DECRYPT_CLIS[*]}" "${KEY_TEMPLATES[*]}" KEY_TEMPLATES=(AES128_EAX AES256_EAX) -ENCRYPT_CLIS=($CC_AEAD_CLI $JAVA_AEAD_CLI) -DECRYPT_CLIS=($CC_AEAD_CLI $JAVA_AEAD_CLI) +ENCRYPT_CLIS=($CC_AEAD_CLI $JAVA_AEAD_CLI $PY2_AEAD_CLI $PY3_AEAD_CLI) +DECRYPT_CLIS=($CC_AEAD_CLI $JAVA_AEAD_CLI $PY2_AEAD_CLI $PY3_AEAD_CLI) aead_basic_test "${ENCRYPT_CLIS[*]}" "${DECRYPT_CLIS[*]}" "${KEY_TEMPLATES[*]}" KEY_TEMPLATES=(AES128_GCM AES128_CTR_HMAC_SHA256) diff --git a/tools/testing/python/aead_cli.py b/tools/testing/python/aead_cli.py new file mode 100644 index 0000000000000000000000000000000000000000..6ff3101b161eb88b9cd81ed497090977787b59ae --- /dev/null +++ b/tools/testing/python/aead_cli.py @@ -0,0 +1,129 @@ +# Copyright 2019 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS-IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A command-line utility for testing AEAD-primitives. + +It requires 5 arguments: + keyset-file: name of the file with the keyset to be used for encryption + operation: the actual AEAD-operation, i.e. "encrypt" or "decrypt" + input-file: name of the file with input (plaintext for encryption, or + or ciphertext for decryption) + associated-data-file: name of the file containing associated data + output-file: name of the file for the resulting output +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import google_type_annotations +from __future__ import print_function + +# Special imports +from absl import app +from absl import flags +import tink + +from pyglib import logging + + +FLAGS = flags.FLAGS + + +def read_keyset(keyset_filename): + """Load a keyset from a file. + + Args: + keyset_filename: A path to a keyset file + Returns: + A KeysetHandle of the file's keyset + Raises: + TinkError: if the file is not valid + IOError: if the file does not exist + """ + with open(keyset_filename, 'rb') as keyset_file: + text = keyset_file.read() + keyset = tink.KeysetHandle(tink.BinaryKeysetReader(text).read()) + return keyset + + +def main(argv): + if len(argv) != 6: + raise app.UsageError( + 'Expected 5 arguments, got %d.\n' + 'Usage: %s keyset-file operation input-file associated-data-file' % + (len(argv) - 1, argv[0])) + + keyset_filename = argv[1] + operation = argv[2] + input_filename = argv[3] + associated_data_filename = argv[4] + output_filename = argv[5] + + logging.info( + 'Using keyset from file %s to AEAD-%s file %s with associated data ' + 'from file %s.\nThe resulting output will be written to file %s', + keyset_filename, operation, input_filename, associated_data_filename, + output_filename) + + # Initialise Tink + try: + tink.tink_config.register() + except tink.TinkError as e: + logging.error('Error initialising Tink: %s', e) + return 1 + + # Read the keyset + try: + keyset = read_keyset(keyset_filename) + except tink.TinkError as e: + logging.error('Error reading key: %s', e) + return 1 + + # Get the primitive + try: + cipher = keyset.primitive(tink.Aead) + except tink.TinkError as e: + logging.error('Error creating primitive: %s', e) + return 1 + + # Read the input files + with open(input_filename, 'rb') as input_file: + input_data = input_file.read() + with open(associated_data_filename, 'rb') as associated_data_file: + aad = associated_data_file.read() + + # Compute the output + if operation.lower() == 'encrypt': + try: + output_data = cipher.encrypt(input_data, aad) + except tink.TinkError as e: + logging.error('Error encrypting the input: %s', e) + elif operation.lower() == 'decrypt': + try: + output_data = cipher.decrypt(input_data, aad) + except tink.TinkError as e: + logging.error('Error decrypting the input: %s', e) + else: + logging.error( + 'Did not recognise operation %s.\n' + 'Expected either "encrypt" or "decrypt"', operation) + return 1 + + with open(output_filename, 'wb') as output_file: + output_file.write(output_data) + + logging.info('All done.') + + +if __name__ == '__main__': + app.run(main)