xref: /aosp_15_r20/external/tink/python/examples/signature/signature.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
15*e7b1675dSTing-Kang Chang# [START digital-signature-example]
16*e7b1675dSTing-Kang Chang
17*e7b1675dSTing-Kang Chang"""A utility for signing and verifying files using digital signatures.
18*e7b1675dSTing-Kang Chang
19*e7b1675dSTing-Kang ChangIt loads cleartext keys from disk - this is not recommended!
20*e7b1675dSTing-Kang Chang"""
21*e7b1675dSTing-Kang Chang
22*e7b1675dSTing-Kang Changimport binascii
23*e7b1675dSTing-Kang Chang
24*e7b1675dSTing-Kang Changfrom absl import app
25*e7b1675dSTing-Kang Changfrom absl import flags
26*e7b1675dSTing-Kang Changfrom absl import logging
27*e7b1675dSTing-Kang Changimport tink
28*e7b1675dSTing-Kang Changfrom tink import cleartext_keyset_handle
29*e7b1675dSTing-Kang Changfrom tink import signature
30*e7b1675dSTing-Kang Chang
31*e7b1675dSTing-Kang Chang
32*e7b1675dSTing-Kang ChangFLAGS = flags.FLAGS
33*e7b1675dSTing-Kang Chang
34*e7b1675dSTing-Kang Changflags.DEFINE_enum('mode', None, ['sign', 'verify'],
35*e7b1675dSTing-Kang Chang                  'The operation to perform.')
36*e7b1675dSTing-Kang Changflags.DEFINE_string('keyset_path', None,
37*e7b1675dSTing-Kang Chang                    'Path to the keyset used for the signature operation.')
38*e7b1675dSTing-Kang Changflags.DEFINE_string('data_path', None,
39*e7b1675dSTing-Kang Chang                    'Path to the file with the input data.')
40*e7b1675dSTing-Kang Changflags.DEFINE_string('signature_path', None,
41*e7b1675dSTing-Kang Chang                    'Path to the signature file.')
42*e7b1675dSTing-Kang Chang
43*e7b1675dSTing-Kang Chang
44*e7b1675dSTing-Kang Changdef main(argv):
45*e7b1675dSTing-Kang Chang  del argv  # Unused.
46*e7b1675dSTing-Kang Chang
47*e7b1675dSTing-Kang Chang  # Initialise Tink
48*e7b1675dSTing-Kang Chang  signature.register()
49*e7b1675dSTing-Kang Chang
50*e7b1675dSTing-Kang Chang  # Read the keyset into a keyset_handle
51*e7b1675dSTing-Kang Chang  with open(FLAGS.keyset_path, 'rt') as keyset_file:
52*e7b1675dSTing-Kang Chang    try:
53*e7b1675dSTing-Kang Chang      text = keyset_file.read()
54*e7b1675dSTing-Kang Chang      keyset_handle = cleartext_keyset_handle.read(tink.JsonKeysetReader(text))
55*e7b1675dSTing-Kang Chang    except tink.TinkError as e:
56*e7b1675dSTing-Kang Chang      logging.exception('Error reading key: %s', e)
57*e7b1675dSTing-Kang Chang      return 1
58*e7b1675dSTing-Kang Chang
59*e7b1675dSTing-Kang Chang  with open(FLAGS.data_path, 'rb') as data_file:
60*e7b1675dSTing-Kang Chang    data = data_file.read()
61*e7b1675dSTing-Kang Chang
62*e7b1675dSTing-Kang Chang  if FLAGS.mode == 'sign':
63*e7b1675dSTing-Kang Chang    # Get the primitive
64*e7b1675dSTing-Kang Chang    try:
65*e7b1675dSTing-Kang Chang      cipher = keyset_handle.primitive(signature.PublicKeySign)
66*e7b1675dSTing-Kang Chang    except tink.TinkError as e:
67*e7b1675dSTing-Kang Chang      logging.exception('Error creating primitive: %s', e)
68*e7b1675dSTing-Kang Chang      return 1
69*e7b1675dSTing-Kang Chang
70*e7b1675dSTing-Kang Chang    # Sign data
71*e7b1675dSTing-Kang Chang    sig = cipher.sign(data)
72*e7b1675dSTing-Kang Chang    with open(FLAGS.signature_path, 'wb') as signature_file:
73*e7b1675dSTing-Kang Chang      signature_file.write(binascii.hexlify(sig))
74*e7b1675dSTing-Kang Chang    return 0
75*e7b1675dSTing-Kang Chang
76*e7b1675dSTing-Kang Chang  # Get the primitive
77*e7b1675dSTing-Kang Chang  try:
78*e7b1675dSTing-Kang Chang    cipher = keyset_handle.primitive(signature.PublicKeyVerify)
79*e7b1675dSTing-Kang Chang  except tink.TinkError as e:
80*e7b1675dSTing-Kang Chang    logging.exception('Error creating primitive: %s', e)
81*e7b1675dSTing-Kang Chang    return 1
82*e7b1675dSTing-Kang Chang
83*e7b1675dSTing-Kang Chang  # Verify data
84*e7b1675dSTing-Kang Chang  with open(FLAGS.signature_path, 'rb') as signature_file:
85*e7b1675dSTing-Kang Chang    try:
86*e7b1675dSTing-Kang Chang      expected_signature = binascii.unhexlify(signature_file.read().strip())
87*e7b1675dSTing-Kang Chang    except binascii.Error as e:
88*e7b1675dSTing-Kang Chang      logging.exception('Error reading expected code: %s', e)
89*e7b1675dSTing-Kang Chang      return 1
90*e7b1675dSTing-Kang Chang  try:
91*e7b1675dSTing-Kang Chang    cipher.verify(expected_signature, data)
92*e7b1675dSTing-Kang Chang    logging.info('Signature verification succeeded.')
93*e7b1675dSTing-Kang Chang    return 0
94*e7b1675dSTing-Kang Chang  except binascii.Error as e:
95*e7b1675dSTing-Kang Chang    logging.exception('Error reading expected signature: %s', e)
96*e7b1675dSTing-Kang Chang  except tink.TinkError as e:
97*e7b1675dSTing-Kang Chang    logging.info('Signature verification failed.')
98*e7b1675dSTing-Kang Chang    return 1
99*e7b1675dSTing-Kang Chang
100*e7b1675dSTing-Kang Chang
101*e7b1675dSTing-Kang Changif __name__ == '__main__':
102*e7b1675dSTing-Kang Chang  flags.mark_flags_as_required([
103*e7b1675dSTing-Kang Chang      'mode', 'keyset_path', 'data_path', 'signature_path'])
104*e7b1675dSTing-Kang Chang  app.run(main)
105*e7b1675dSTing-Kang Chang
106*e7b1675dSTing-Kang Chang# [END digital-signature-example]
107