xref: /aosp_15_r20/external/tink/python/examples/envelope_aead/envelope.py (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang# Copyright 2021 Google LLC
2*e7b1675dSTing-Kang Chang#
3*e7b1675dSTing-Kang Chang# Licensed under the Apache License, Version 2.0 (the "License");
4*e7b1675dSTing-Kang Chang# you may not use this file except in compliance with the License.
5*e7b1675dSTing-Kang Chang# You may obtain a copy of the License at
6*e7b1675dSTing-Kang Chang#
7*e7b1675dSTing-Kang Chang#      http://www.apache.org/licenses/LICENSE-2.0
8*e7b1675dSTing-Kang Chang#
9*e7b1675dSTing-Kang Chang# Unless required by applicable law or agreed to in writing, software
10*e7b1675dSTing-Kang Chang# distributed under the License is distributed on an "AS-IS" BASIS,
11*e7b1675dSTing-Kang Chang# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e7b1675dSTing-Kang Chang# See the License for the specific language governing permissions and
13*e7b1675dSTing-Kang Chang# limitations under the License.
14*e7b1675dSTing-Kang Chang# [START envelope-example]
15*e7b1675dSTing-Kang Chang"""A command-line utility for encrypting small files using envelope encryption with GCP."""
16*e7b1675dSTing-Kang Chang
17*e7b1675dSTing-Kang Changfrom absl import app
18*e7b1675dSTing-Kang Changfrom absl import flags
19*e7b1675dSTing-Kang Changfrom absl import logging
20*e7b1675dSTing-Kang Changimport tink
21*e7b1675dSTing-Kang Changfrom tink import aead
22*e7b1675dSTing-Kang Changfrom tink.integration import gcpkms
23*e7b1675dSTing-Kang Chang
24*e7b1675dSTing-Kang Chang
25*e7b1675dSTing-Kang ChangFLAGS = flags.FLAGS
26*e7b1675dSTing-Kang Chang
27*e7b1675dSTing-Kang Changflags.DEFINE_enum(
28*e7b1675dSTing-Kang Chang    'mode', None, ['encrypt', 'decrypt'], 'The operation to perform.'
29*e7b1675dSTing-Kang Chang)
30*e7b1675dSTing-Kang Changflags.DEFINE_string(
31*e7b1675dSTing-Kang Chang    'kek_uri', None, 'The Cloud KMS URI of the key encryption key.'
32*e7b1675dSTing-Kang Chang)
33*e7b1675dSTing-Kang Changflags.DEFINE_string(
34*e7b1675dSTing-Kang Chang    'gcp_credential_path', None, 'Path to the GCP credentials JSON file.'
35*e7b1675dSTing-Kang Chang)
36*e7b1675dSTing-Kang Changflags.DEFINE_string('input_path', None, 'Path to the input file.')
37*e7b1675dSTing-Kang Changflags.DEFINE_string('output_path', None, 'Path to the output file.')
38*e7b1675dSTing-Kang Changflags.DEFINE_string(
39*e7b1675dSTing-Kang Chang    'associated_data', None, 'Optional associated data used for the encryption.'
40*e7b1675dSTing-Kang Chang)
41*e7b1675dSTing-Kang Chang
42*e7b1675dSTing-Kang Chang
43*e7b1675dSTing-Kang Changdef main(argv):
44*e7b1675dSTing-Kang Chang  del argv  # Unused.
45*e7b1675dSTing-Kang Chang
46*e7b1675dSTing-Kang Chang  associated_data = (
47*e7b1675dSTing-Kang Chang      b''
48*e7b1675dSTing-Kang Chang      if not FLAGS.associated_data
49*e7b1675dSTing-Kang Chang      else bytes(FLAGS.associated_data, 'utf-8')
50*e7b1675dSTing-Kang Chang  )
51*e7b1675dSTing-Kang Chang
52*e7b1675dSTing-Kang Chang  # Initialise Tink
53*e7b1675dSTing-Kang Chang  aead.register()
54*e7b1675dSTing-Kang Chang
55*e7b1675dSTing-Kang Chang  try:
56*e7b1675dSTing-Kang Chang    # Read the GCP credentials and setup client
57*e7b1675dSTing-Kang Chang    client = gcpkms.GcpKmsClient(FLAGS.kek_uri, FLAGS.gcp_credential_path)
58*e7b1675dSTing-Kang Chang  except tink.TinkError as e:
59*e7b1675dSTing-Kang Chang    logging.exception('Error creating GCP KMS client: %s', e)
60*e7b1675dSTing-Kang Chang    return 1
61*e7b1675dSTing-Kang Chang
62*e7b1675dSTing-Kang Chang  # Create envelope AEAD primitive using AES256 GCM for encrypting the data
63*e7b1675dSTing-Kang Chang  try:
64*e7b1675dSTing-Kang Chang    remote_aead = client.get_aead(FLAGS.kek_uri)
65*e7b1675dSTing-Kang Chang    env_aead = aead.KmsEnvelopeAead(
66*e7b1675dSTing-Kang Chang        aead.aead_key_templates.AES256_GCM, remote_aead
67*e7b1675dSTing-Kang Chang    )
68*e7b1675dSTing-Kang Chang  except tink.TinkError as e:
69*e7b1675dSTing-Kang Chang    logging.exception('Error creating primitive: %s', e)
70*e7b1675dSTing-Kang Chang    return 1
71*e7b1675dSTing-Kang Chang
72*e7b1675dSTing-Kang Chang  with open(FLAGS.input_path, 'rb') as input_file:
73*e7b1675dSTing-Kang Chang    input_data = input_file.read()
74*e7b1675dSTing-Kang Chang    if FLAGS.mode == 'decrypt':
75*e7b1675dSTing-Kang Chang      output_data = env_aead.decrypt(input_data, associated_data)
76*e7b1675dSTing-Kang Chang    elif FLAGS.mode == 'encrypt':
77*e7b1675dSTing-Kang Chang      output_data = env_aead.encrypt(input_data, associated_data)
78*e7b1675dSTing-Kang Chang    else:
79*e7b1675dSTing-Kang Chang      logging.error(
80*e7b1675dSTing-Kang Chang          'Unsupported mode %s. Please choose "encrypt" or "decrypt".',
81*e7b1675dSTing-Kang Chang          FLAGS.mode,
82*e7b1675dSTing-Kang Chang      )
83*e7b1675dSTing-Kang Chang      return 1
84*e7b1675dSTing-Kang Chang
85*e7b1675dSTing-Kang Chang    with open(FLAGS.output_path, 'wb') as output_file:
86*e7b1675dSTing-Kang Chang      output_file.write(output_data)
87*e7b1675dSTing-Kang Chang
88*e7b1675dSTing-Kang Chang
89*e7b1675dSTing-Kang Changif __name__ == '__main__':
90*e7b1675dSTing-Kang Chang  flags.mark_flags_as_required(
91*e7b1675dSTing-Kang Chang      ['mode', 'kek_uri', 'gcp_credential_path', 'input_path', 'output_path']
92*e7b1675dSTing-Kang Chang  )
93*e7b1675dSTing-Kang Chang  app.run(main)
94*e7b1675dSTing-Kang Chang# [END envelope-example]
95