xref: /aosp_15_r20/external/tink/python/examples/signature/signature.py (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1# Copyright 2021 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS-IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15# [START digital-signature-example]
16
17"""A utility for signing and verifying files using digital signatures.
18
19It loads cleartext keys from disk - this is not recommended!
20"""
21
22import binascii
23
24from absl import app
25from absl import flags
26from absl import logging
27import tink
28from tink import cleartext_keyset_handle
29from tink import signature
30
31
32FLAGS = flags.FLAGS
33
34flags.DEFINE_enum('mode', None, ['sign', 'verify'],
35                  'The operation to perform.')
36flags.DEFINE_string('keyset_path', None,
37                    'Path to the keyset used for the signature operation.')
38flags.DEFINE_string('data_path', None,
39                    'Path to the file with the input data.')
40flags.DEFINE_string('signature_path', None,
41                    'Path to the signature file.')
42
43
44def main(argv):
45  del argv  # Unused.
46
47  # Initialise Tink
48  signature.register()
49
50  # Read the keyset into a keyset_handle
51  with open(FLAGS.keyset_path, 'rt') as keyset_file:
52    try:
53      text = keyset_file.read()
54      keyset_handle = cleartext_keyset_handle.read(tink.JsonKeysetReader(text))
55    except tink.TinkError as e:
56      logging.exception('Error reading key: %s', e)
57      return 1
58
59  with open(FLAGS.data_path, 'rb') as data_file:
60    data = data_file.read()
61
62  if FLAGS.mode == 'sign':
63    # Get the primitive
64    try:
65      cipher = keyset_handle.primitive(signature.PublicKeySign)
66    except tink.TinkError as e:
67      logging.exception('Error creating primitive: %s', e)
68      return 1
69
70    # Sign data
71    sig = cipher.sign(data)
72    with open(FLAGS.signature_path, 'wb') as signature_file:
73      signature_file.write(binascii.hexlify(sig))
74    return 0
75
76  # Get the primitive
77  try:
78    cipher = keyset_handle.primitive(signature.PublicKeyVerify)
79  except tink.TinkError as e:
80    logging.exception('Error creating primitive: %s', e)
81    return 1
82
83  # Verify data
84  with open(FLAGS.signature_path, 'rb') as signature_file:
85    try:
86      expected_signature = binascii.unhexlify(signature_file.read().strip())
87    except binascii.Error as e:
88      logging.exception('Error reading expected code: %s', e)
89      return 1
90  try:
91    cipher.verify(expected_signature, data)
92    logging.info('Signature verification succeeded.')
93    return 0
94  except binascii.Error as e:
95    logging.exception('Error reading expected signature: %s', e)
96  except tink.TinkError as e:
97    logging.info('Signature verification failed.')
98    return 1
99
100
101if __name__ == '__main__':
102  flags.mark_flags_as_required([
103      'mode', 'keyset_path', 'data_path', 'signature_path'])
104  app.run(main)
105
106# [END digital-signature-example]
107