{"id":22564670,"url":"https://github.com/elliotkillick/vanity-pgp-subkey-tools","last_synced_at":"2025-03-28T13:16:18.208Z","repository":{"id":241674294,"uuid":"807401213","full_name":"ElliotKillick/vanity-pgp-subkey-tools","owner":"ElliotKillick","description":"Tooling for generating vanity PGP subkeys ","archived":false,"fork":false,"pushed_at":"2024-05-29T03:18:25.000Z","size":6,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-24T06:56:46.252Z","etag":null,"topics":["gnupg","gnupg2","gpg","key-fingerprint","pgp","pgp-key","pgp-keys","subkey","subkeys","vanity","vanitygen"],"latest_commit_sha":null,"homepage":"https://elliotonsecurity.com","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ElliotKillick.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-29T03:16:53.000Z","updated_at":"2024-05-29T10:37:22.000Z","dependencies_parsed_at":"2024-05-29T16:37:53.558Z","dependency_job_id":null,"html_url":"https://github.com/ElliotKillick/vanity-pgp-subkey-tools","commit_stats":null,"previous_names":["elliotkillick/vanity-pgp-subkey-tools"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElliotKillick%2Fvanity-pgp-subkey-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElliotKillick%2Fvanity-pgp-subkey-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElliotKillick%2Fvanity-pgp-subkey-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElliotKillick%2Fvanity-pgp-subkey-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ElliotKillick","download_url":"https://codeload.github.com/ElliotKillick/vanity-pgp-subkey-tools/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246034308,"owners_count":20712857,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gnupg","gnupg2","gpg","key-fingerprint","pgp","pgp-key","pgp-keys","subkey","subkeys","vanity","vanitygen"],"created_at":"2024-12-07T23:17:13.701Z","updated_at":"2025-03-28T13:16:18.186Z","avatar_url":"https://github.com/ElliotKillick.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Vanity PGP Subkey Tools\n\nThis repo contains helpful tools for generating vanity PGP subkeys. The tools here were created for use with vanity PGP key finders like [VanityGPG](https://github.com/RedL0tus/VanityGPG).\n\n## Tools\n\n- [`get-compatible-pgp-subkeys` Program](#get-compatible-pgp-subkey-program)\n  - This program reads a directory full of PGP keys to find the ones that have a creation timestamp compatible with a given primary key\n    - OpenPGP v4 includes a PGP key's creation timestamp as part of its (vanity) fingerprint calculation, so a compatible subkey must have a creation timestamp greater than or equal to the primary key\n  - A fast C program is necessary to sort through the potential tens of millions of vanity key candidates you generated with VanityGPG or likewise\n- [GPG commands for adding a vanity subkey to your vanity primary key](#adding-a-vanity-subkey-to-your-vanity-primary-key-instructions)\n- A [VanityGPG fork](https://github.com/ElliotKillick/VanityGPG-ESS) for generating vanity encryption subkeys\n  - For generating Curve25519 encryption keys ([this may be integrated in the future](https://github.com/RedL0tus/VanityGPG/issues/5))\n  - **Note:** This fork is pending release.\n\n## `get-compatible-pgp-subkeys` Program\n\n### Usage\n\n```\nUsage: ./get-compatible-pgp-subkeys \u003cSOURCE_DIRECTORY\u003e [\u003cPRIMARY_PGP_KEY\u003e \u003cDESTINATION_DIRECTORY\u003e]\n\nPassing a source directory with no other arguments opens each PGP key and prints its creation\ntimestamp. Further specifying a primary PGP key and destination directory will move each PGP key if\nits creation timestamp is equal to or greater than that of the primary PGP key.\n\nBoth raw and ASCII-armored PGP keys are supported.\n```\n\n### Compiling\n\nYou can build a `get-compatible-pgp-subkeys` binary by doing:\n\nDebian: `sudo apt-get install pkg-config libglib2.0-dev`\n\nFedora: `sudo dnf install pkg-config glib2-devel`\n\n```shell\nmake\n```\n\n### Performance\n\n**Performance is excellent:**\n\n1. No dynamic memory allocation (`malloc`) in the main program loop (w/ in-place base64 decoding)\n2. Fully zero copy / pass-by-reference (no `memcpy`, `strcpy`, etc.)\n3. For armored (base64) PGP keys, only the exact 4 bytes of base64 containing the PGP creation timestamp are decoded\n\nThese three performance wins allow us to quickly process a huge number of keys. Disk I/O is currently the bottleneck (as it should be).\n\n### Code Quality\n\nThe program structure is easy to understand. Return values of standard library functions (e.g. malloc, fread, fopen, etc.) are always checked to ensure success. The most crucial parts of the code are split up into their own functions so we don't repeat ourselves (DRY principle). The code compiles warning-free (even on `-Wall`). Address sanitizer has been used to ensure there's no memory corruption or resource leak problems. Only standard C features are used (other than a dependency on the cross-platform GNOME GLib library) so this code is portable across Windows, Mac, Linux, the BSDs, Solaris, Android, iOS, a toaster, etc.\n\n## Adding a Vanity Subkey to Your Vanity Primary Key Instructions\n\n### Make Key Importable\n\nThis step is only applicable if you didn't specify a user ID `-u`/`--user-id` when generating keys with VanityGPG. To add a temporary user ID so you can import your new vanity PGP key:\n\n```shell\ngpg --output \u003cGPG_PRIVATE_KEY_FILE\u003e --dearmor \u003cASC_PRIVATE_KEY_FILE\u003e\nprintf '\\xb4\\x04temp' \u003e\u003e \u003cGPG_PRIVATE_KEY_FILE\u003e\ngpg --allow-non-selfsigned-uid --import \u003cGPG_PRIVATE_KEY_FILE\u003e\n```\n\nIf this key will be your primary key, proceed to correct the user ID of the imported key with GPG by running `gpg --edit-key \u003cKEY_FINGERPRINT\u003e`, then using the `adduid`, `uid`, and `deluid` commands to add a new user ID and delete the old one. Also, use the `trust` command to trust your own primary key ultimately. Run the `save` command to complete changes and exit. If you will be turning this key into a subkey, then you don't need to correct the user ID.\n\n### Attach Vanity Subkey\n\n1. Import your vanity key (if it's not already imported): `gpg --import \u003cKEY_FILE\u003e`\n2. List keys with details to collect the keygrip: `gpg --list-keys --with-keygrip`\n  - Keygrip is a GPG implementation detail referring to the secret key material (these are part of what calculates a PGP key fingerprint)\n3. Get the creation timestamp of your vanity key: `gpg --list-packets \u003cKEY_FILE\u003e | grep '^\\sversion 4' | grep -oE 'created [0-9]+'`\n4. Knowing the keygrip and creation timestamp of the vanity key (soon-to-be subkey), we can now replicate its vanity PGP fingerprint onto our vanity primary key: `gpg --expert --faked-system-time '\u003cKEY_TIMESTAMP\u003e!' --edit-key \u003cPRIMARY_KEY_FINGERPRINT\u003e`\n  - The `!` after a timestamp tells GPG to keep the clock exactly at the given time (no ticking)\n\nGood, now in the GPG shell we operate on your primary key:\n\n1. Run command: `addkey`\n2. Enter `13` to choose this option: `(13) Existing key`\n3. GPG will request your keygrip, enter it: `Enter the keygrip:`\n4. Continue through the remaining typical questions asked when adding a PGP key (typically stick with the defaults)\n5. Run `save` to complete changes and exit\n6. Verify your new vanity subkey: `gpg --list-secret-keys --with-keygrip --with-subkey-fingerprints`\n7. Export the final product (including primary key and subkeys):\n  - Public: `gpg --output final.asc --armor --export \u003cPRIMARY_KEY_FINGERPRINT\u003e`\n  - Private: `gpg --output final-secret.asc --armor --export-secret-key \u003cPRIMARY_KEY_FINGERPRINT\u003e`\n\n**You're done! Your vanity primary key is now adorned with a vanity subkey!**\n\nHere's what my final PGP keyring looks like:\n\n```shell\n$ gpg --list-keys --with-subkey-fingerprints\n/home/user/.gnupg/pubring.kbx\n-----------------------------\npub   ed25519 2024-05-12 [SC]\n      EEEE1AE12A5B322909EBDC5D2CEEA9CE5BD0EEEE\nuid           [ultimate] Elliot Killick \u003ccontact@elliotkillick.com\u003e\nsub   ed25519 2024-05-22 [S]\n      EEEE6403CE850791ECB1F8207C4ECB25B6B1C0DE\nsub   ed25519 2024-05-21 [S]\n      EEEE819EAB6A6D1ACB25416A1B212E0A541E2222\n```\n\n## License\n\nMIT License - Copyright (C) 2024 Elliot Killick \u003ccontact@elliotkillick.com\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felliotkillick%2Fvanity-pgp-subkey-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felliotkillick%2Fvanity-pgp-subkey-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felliotkillick%2Fvanity-pgp-subkey-tools/lists"}