Skip to content
This repository has been archived by the owner on Aug 26, 2023. It is now read-only.

duxsco/gpg-keyserver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

KISS-like, self-hosted GnuPG keyserver

  _________________________________________
/ This repo has been archived!              \
| Its successor is at:                      |
\ https://codeberg.org/duxsco/gpg-keyserver /
  -----------------------------------------
         \   ^__^
          \  (oo)\_______
             (__)\       )\/\
                 ||----w |
                 ||     ||

Following draft RFC, hkps2nginx.sh creates the Nginx configuration for hosting your own GnuPG keyserver which allows only for retrieval of public keys (no sks-like sync, no upload, no index, no vindex).

System requirements

hkps2nginx.sh has been tested on Gentoo Linux and macOS Catalina, both with GnuPG v2.2.x. For hkps2nginx.sh to function on macOS, you need to install HomeBrew's bash package:

brew install bash

Creation of Nginx config

A sample Nginx configuration is available in the nginx_example_config subfolder. The output of nginx2nginx.sh needs to be added to said sample config. Beware that I reduced Nginx modules to the bare minimum. Depending on the modules in use on your server, you need to take additional measures.

bash hkps2nginx.sh -h

Execute:
$ bash hkps2nginx.sh -l localPublicKeysFile.asc -r NginxWebroot

Example:
$ gpg --export --armor [email protected] [email protected] > pubkey.asc
$ bash hkps2nginx.sh -l pubkey.asc -r /var/www/keys/

To indent using tabs:
$ bash hkps2nginx.sh -l pubkey.asc -r /var/www/keys/ | sed 's/    /\t/g' | sed 's/^\([^$]\)/\t\t\1/'

Sample bash hkps2nginx.sh -l pubkey.asc -r /var/www/keys/ output:

location ~ "^/([0-9A-F]{40}|[0-9A-F]{50})\.asc$" {
    add_header content-disposition "attachment; filename=$1.asc";
    default_type application/pgp-keys;
    root /var/www/keys/;
}

location = /pks/lookup {

    # if query doesn't contain "op=get"
    if ($query_string !~ "^(.+&)*op=get(&.+)*$") {
        return 501;
    }

    # if query doesn't contain "search=..."
    if ($query_string !~ "^(.+&)*search=((0x|)([0-9a-fA-F]{8}|[0-9a-fA-F]{16}|[0-9a-fA-F]{40}|[0-9a-fA-F]{50})|.+@.+)(&.+)*$") {
        return 501;
    }

    # if query contains more than one "op=get"
    if ($query_string ~ "^(.+&)*op=(.+&)+op=.+(&.+)*$") {
        return 501;
    }

    # if query contains more than one "search=..."
    if ($query_string ~ "^(.+&)*search=(.+&)+search=.+(&.+)*$") {
        return 501;
    }

    if ($query_string ~* "^(.+&)*search=((0x|)(68669BDF2F787AE593115FDD9DEC9F9C5E587974|86615A9CC67D206645ACAFB42992799FB82E4BFB|1DD5D9EDE1203A39365C1894BC35F9A0C5FBA5C7|B6F039EA839BE75AB2B7204BA2217B8B48F41A2C|9DEC9F9C5E587974|2992799FB82E4BFB|BC35F9A0C5FBA5C7|A2217B8B48F41A2C|5E587974|B82E4BFB|C5FBA5C7|48F41A2C)|[email protected]|[email protected]|[email protected])(&.+)*$") {
        return 301 /68669BDF2F787AE593115FDD9DEC9F9C5E587974.asc;
    }

    if ($query_string ~* "^(.+&)*search=((0x|)(46E6C639E0F6A012AEA11683B8DD0599EDDA35AA|E86700A4C56A138EC54929D6D02E34BE663E6091|3AAF5CDAC88DAFFFF2A069A74D189EE4A6DE96F3|506CD61215D8CCBF7F458A44204443AA16CD9EF4|B8DD0599EDDA35AA|D02E34BE663E6091|4D189EE4A6DE96F3|204443AA16CD9EF4|EDDA35AA|663E6091|A6DE96F3|16CD9EF4)|[email protected])(&.+)*$") {
        return 301 /46E6C639E0F6A012AEA11683B8DD0599EDDA35AA.asc;
    }

    return 404;
}

You can visualise the regex in the if condition at Debuggex. Example:

Debuggex

Verification of public key delivery

You can retrieve a GnuPG public key from HKPS using e-mail addresses:

gpg --auto-key-locate clear,hkps://keys.example.org --locate-external-keys [email protected] [email protected]

... or via hexadecimal identifiers with/without 0x prefix and, of course, without whitespace:

Debuggex

Debuggex

Beside running above --locate-external-keys command for every of your e-mail addresses you should check whether your public key is retrievable with hex identifiers. First, specify the public keys you want to run a check upon and the HKPS server you want to retrieve them from. The commands expect you to have the public keys pre-imported.

IDS="[email protected] [email protected]"
HKPS="hkps://keys.example.org"

Then, copy&paste into your terminal and run:

COLONS_OUTPUT="$(gpg --with-colons --list-keys ${IDS})"
(
    grep "^fpr:" <<<"${COLONS_OUTPUT}" | cut -d: -f10
    grep "^fpr:" <<<"${COLONS_OUTPUT}" | cut -d: -f10 | grep -Eo "^.{50}"
    grep -e "^pub:" -e "^sub:" <<<"${COLONS_OUTPUT}" | cut -d: -f5
    grep -e "^pub:" -e "^sub:" <<<"${COLONS_OUTPUT}" | cut -d: -f5 | grep -Eo ".{8}$"
) | \
while read -r I; do
    gpg --quiet --keyserver "${HKPS}" --recv-keys "$I" &&
        echo "$I: ✅" || \
        echo "$I: ❌"
done

Publication of GnuPG keyserver

You can add the following DNS record for others to better find your keyserver:

$ delv +nodnssec SRV _hkps._tcp.example.org
; fully validated
_hkps._tcp.example.org. 300 IN SRV 1 1 443 keys.example.org.

Furthermore, you can add sig-keyserver-url to your ~/.gnupg/gpg.conf.

Other GnuPG repos

https://github.com/duxsco?tab=repositories&q=gpg-