1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- #!/usr/bin/env python3
- import cryptography.hazmat.backends
- import cryptography.hazmat.primitives.serialization
- import cryptography.x509
- import math
- DEFAULT_KEY_OUTPUT_PATH = 'gpg-key.sexp'
- DEFAULT_SMARTCARD_APP_ID_HEX = 'D2760001240102010001234567890000'
- def convert_to_sexp(data):
- if isinstance(data, int):
- return convert_to_sexp(data.to_bytes(
- math.ceil(data.bit_length() / 8),
- 'big',
- ))
- elif isinstance(data, str):
- return convert_to_sexp(data.encode())
- elif isinstance(data, bytes):
- return str(len(data)).encode() + b':' + data
- else:
- return b'(' + b''.join(convert_to_sexp(i) for i in data) + b')'
- def create_gpg_key(input_path, gpg_key_output_path, smartcard_app_id_hex):
- backend = cryptography.hazmat.backends.default_backend()
- with open(input_path, 'rb') as f:
- req = cryptography.x509.load_pem_x509_csr(f.read(), backend)
- assert req.is_signature_valid
- pubnums = req.public_key().public_numbers()
- key_data = ['shadowed-private-key', [
- 'rsa',
- ['n', pubnums.n],
- ['e', pubnums.e],
- ['shadowed', 't1-v1', [int(smartcard_app_id_hex, 16), 'OPENPGP.1']],
- ]]
- key = convert_to_sexp(key_data)
- with open(gpg_key_output_path, 'wb') as f:
- f.write(key)
- def _init_argparser():
- import argparse
- argparser = argparse.ArgumentParser(
- description='create a shadowed-private-key in sexp format for gnupg\'s private-keys-v1.d folder'
- + ' containing the public key of a PEM-encoded X.509 certificate signing request (CSR)',
- )
- argparser.add_argument(
- 'input_path',
- help='path to PEM-encoded X.509 signing request',
- )
- argparser.add_argument(
- '--gpg-key-output-path',
- dest='gpg_key_output_path',
- default=DEFAULT_KEY_OUTPUT_PATH,
- help='path to sexp-encoded shadowed-private-key to be created (default: "%(default)s")',
- )
- argparser.add_argument(
- '--smartcard-app-id',
- dest='smartcard_app_id_hex',
- metavar='hex-string',
- default=DEFAULT_SMARTCARD_APP_ID_HEX,
- help='default: %(default)s',
- )
- return argparser
- def main(argv):
- argparser = _init_argparser()
- args = argparser.parse_args(argv[1:])
- create_gpg_key(**vars(args))
- return 0
- if __name__ == '__main__':
- import sys
- sys.exit(main(sys.argv))
|