diff options
Diffstat (limited to 'examples')
-rwxr-xr-x | examples/make-8192-bit-key.py | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/examples/make-8192-bit-key.py b/examples/make-8192-bit-key.py new file mode 100755 index 0000000..c533fc9 --- /dev/null +++ b/examples/make-8192-bit-key.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""Create a new 8192-bit GnuPG keypair. + +:authors: Isis <isis@patternsinthevoid.net> 0xa3adb67a2cdb8b35 +:license: MIT license +:copyright: (c) 2013 Isis Agora Lovecruft +""" + +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals + +import os +import logging + +import gnupg + +from gnupg import _logger + +# Set up logging: +log = _logger.create_logger(9) +log.setLevel(9) + + +#――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― +# Settings +# +# You probably want to edit the following variables. Ones which are currently +# set to strings are necessary; the ones which are set to `None` are optional. + +# The directory to use as the homedir for GnuPG (it will contain the +# secring.gpg and pubring.gpg, etc.) +NEWKEY_DIR = './8192-bit-key' + +# The name you go by, as it should appear in the primary keyid, i.e. "Evey +# Hammond": +NAME = 'Someone' + +# The comment which goes in parantheses after the name and before the email +# address on the key's primary uid. Leave as None to not have one. +NAME_COMMENT = None + +# The email address for the primary UID (You *should* actually be able to put +# whatever you want here, like a domain or something, because the GnuPG +# `--allow-freeform-uid` option will be used. I've not actually tested this +# though.) +NAME_EMAIL = 'someone@example.com' + +# Expiration date for the new key. To use the default expiration of one year, +# set to None. +#EXPIRE_DATE = '1999-09-19' +EXPIRE_DATE = None + + +# GnuPG-1.4.x allows the automated creation of passphraseless keys. If using +# GnuPG-1.4.x, and you don't specify the passphrase, you can of course set it +# later with `$ gpg --edit-key` and then at the prompt typing `password`. If +# using a GnuPG from the 2.x series, you *must* specify a password here +# (though you can still change it afterward). +PASSPHRASE = None + +# Type of key, i.e. 'RSA' or 'DSA' or something else. I've only tested +# 8192-bit keys with RSA. +KEY_TYPE = 'RSA' + +# Uses for the key. Can be things like 'cert,sign' or 'cert' or 'cert,auth'. +KEY_USAGE = 'cert' + +# Key bitlength. You likely want 8192, if you're using this script. +# +# It *is* possible to create 16834-bit keys, though it requires modifying and +# recompiling GnuPG. Doing this is a bit janky due to internal GnuPG buffers +# in several parts of the codebase being limited to 8192-bits, the key cannot +# be handled by *most* keyservers (there appears to be only one public +# keyserver which supports 16384-bit keys being uploaded to it), and the +# 16834-bit key will likely require the modified GnuPG to work with it (even +# then some operations, such as removal of the primary secret key, but not the +# primary public key, from the keychain will be badly broken). +KEY_LENGTH = 8192 + +# Type of subkey. None to skip subkey generation. You can add keys later +# through `$ gpg --edit-key`. For compatibility with people who aren't doing +# crazy things with their keys, you maybe probably want to use `--edit-key` to +# create some nice, normal, "overly-paranoid" 4096-bit keys. +SUBKEY_TYPE = 'RSA' + +# Same as KEY_USAGE. +#SUBKEY_USAGE = None +SUBKEY_USAGE = 'sign' + +# Same as KEY_LENGTH. +#SUBKEY_LENGTH = None +SUBKEY_LENGTH = 4096 + +# The default keyserver for the key, which is embedded into the key, telling +# other people's GnuPGs to fetch (and send updates) to this URL: +KEYSERVER = None + +# Set the cipher, hash, and compression preference values for this key. This +# expects the same type of string as the sub-command ‘setpref’ in the +# --edit-key menu. The default preferences are given in +# ``gnupg.GPG.default_preference_list``. +PREFERENCES = None +#――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― + + +gpg = gnupg.GPG(homedir=NEWKEY_DIR) +allparams = {'name_real': NAME, + 'name_comment': NAME_COMMENT, + 'name_email': NAME_EMAIL, + 'expire_date': EXPIRE_DATE, + 'passphrase': PASSPHRASE, + 'key_type': KEY_TYPE, + 'key_usage': KEY_USAGE, + 'key_length': KEY_LENGTH, + 'subkey_type': SUBKEY_TYPE, + 'subkey_usage': SUBKEY_USAGE, + 'subkey_length': SUBKEY_LENGTH, + 'keyserver': KEYSERVER, + 'preferences': PREFERENCES} + +def createBatchfile(keyparams=allparams): + """Create the batchfile for our new key. + + :params dict keyparams: A dictionary of arguments for creating the key. It + should probably be ``allparams``. + :rtype: str + :returns: A string containing the entire GnuPG batchfile. + """ + useparams = {} + for key, value in keyparams.items(): + if value: + useparams.update({key: value}) + batchfile = gpg.gen_key_input(separate_keyring=True, + save_batchfile=True, + **useparams) + log.info("Generated GnuPG batch file:\n%s" % batchfile) + return batchfile + +def createKey(batchfile): + """Create a new keypair from a **batchfile**. + + Writes the new keys into keyrings named after ``NAME_EMAIL`` inside the + ``NEWKEY_DIR``. + + :params str batchfile: A GnuPG batchfile. See :func:`createBatchfile`. + """ + key = gpg.gen_key(batchfile) + fingerprint = key.fingerprint + + if not fingerprint: + log.error("Key creation seems to have failed: %s" % key.status) + return None, None + return key, fingerprint + +def displayNewKey(key): + """Use ``gnupg.GPG.list_keys()`` to display details of the new key.""" + + if key.keyring: + gpg.keyring = key.keyring + if key.secring: + gpg.secring = key.secring + + # Using '--fingerprint' twice will display subkey fingerprints too: + gpg.options = ['--fingerprint', '--fingerprint'] + keylist = gpg.list_keys(secret=True) + + # `result` is a `gnupg._parsers.ListKeys`, which is list-like, so iterate + # over all the keys and display their info: + for gpgkey in keylist: + for k, v in gpgkey.items(): + log.info("%s: %s" % (k.capitalize(), v)) + + return keylist + +def exportNewKey(fingerprint): + """Export the new keys into .asc files. + + :param str fingerprint: A full key fingerprint. + """ + log.info("Exporting key: %s" % fingerprint) + + keyfn = os.path.join(gpg.homedir, + fingerprint + '-8192-bit-key') + os.path.extsep + + pubkey = gpg.export_keys(fingerprint) + seckey = gpg.export_keys(fingerprint, secret=True) + subkey = gpg.export_keys(fingerprint, secret=True, subkeys=True) + + with open(keyfn + 'pub' + os.path.extsep + 'asc', 'w') as fh: + fh.write(pubkey) + with open(keyfn + 'sec' + os.path.extsep + 'asc', 'w') as fh: + fh.write(seckey) + with open(keyfn + 'sub' + os.path.extsep + 'asc', 'w') as fh: + fh.write(subkey) + + +if __name__ == '__main__': + if (NAME == 'Someone') or (NAME_EMAIL == 'someone@example.com'): + log.info("Please edit the settings variables within this script.") + log.info("Exiting...") + exit(1) + else: + try: + batchfile = createBatchfile() + key, fingerprint = createKey(batchfile) + log.info("New key with fingerprint %r created" % fingerprint) + displayNewKey(key) + exportNewKey(fingerprint) + + except Exception as error: + log.error(error) |