From b23c2c486949eb76c22d3dbd371e43875482ee41 Mon Sep 17 00:00:00 2001 From: Frank Sauerburger <frank@sauerburger.com> Date: Sun, 21 Feb 2021 14:45:38 +0100 Subject: [PATCH] Display open pgp key data --- keys/settings.py | 1 - keys/urls.py | 1 + pgp/models.py | 43 ++++++++++++++++++++++++- pgp/templates/pgp/publickey_detail.html | 39 +++++++++++++++++++++- pgp/views.py | 7 ++++ 5 files changed, 88 insertions(+), 3 deletions(-) diff --git a/keys/settings.py b/keys/settings.py index e2be4f2..5cbb30e 100644 --- a/keys/settings.py +++ b/keys/settings.py @@ -15,7 +15,6 @@ from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent - # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ diff --git a/keys/urls.py b/keys/urls.py index 7acaa72..fe4c047 100644 --- a/keys/urls.py +++ b/keys/urls.py @@ -20,5 +20,6 @@ urlpatterns = [ path('pki/', include('owlca.urls')), path('pgp/', include('pgp.urls')), path('ssh/', include('ssh.urls')), + path('pks/', include('hkp.urls')), path('admin/', admin.site.urls), ] diff --git a/pgp/models.py b/pgp/models.py index 75671f3..c244617 100644 --- a/pgp/models.py +++ b/pgp/models.py @@ -31,6 +31,47 @@ class PublicKey(models.Model): def details(self): self._decode() - return self.decoded + def get_exp(created, expires_at): + if not expires_at: + return None + return created + expires_at + data = { + "userids": [{ + "email": userid.email, + "name": userid.name, + "comment": userid.comment, + "signatures": [{ + "created": sig.created, + "expires_at": get_exp(sig.created, sig.expires_at), + "signer": sig.signer, + } for sig in userid._signatures], + } for userid in self.decoded.userids], + "fingerprint": self.decoded.fingerprint, + "id": re.sub("\s+", "", self.decoded.fingerprint[-8:]), + "created": self.decoded.created, + "expires_at": self.decoded.expires_at, + "signatures": [{ + "created": sig.created, + "expires_at": get_exp(sig.created, sig.expires_at), + "signer": sig.signer, + } for sig in self.decoded._signatures], + "subkeys": [{ + "fingerprint": subkey.fingerprint, + "created": subkey.created, + "expires_at": subkey.expires_at, + "signatures": [{ + "created": sig.created, + "expires_at": get_exp(subkey.created, sig.key_expiration), + "signer": sig.signer, + } + for sig in subkey._signatures + if sig.type == pgpy.constants.SignatureType.Subkey_Binding], + } for id, subkey in self.decoded.subkeys.items()], + } + return data + + def __str__(self): + keyid = f" (0x{self.keyid[-8:]})" if self.keyid else "" + return f"{self.email}{keyid}" diff --git a/pgp/templates/pgp/publickey_detail.html b/pgp/templates/pgp/publickey_detail.html index 05e0ac3..f5d42f1 100644 --- a/pgp/templates/pgp/publickey_detail.html +++ b/pgp/templates/pgp/publickey_detail.html @@ -2,5 +2,42 @@ {% block content %} <h2>Public key for: {{ publickey.email }}</h2> -<pre>{{ publickey.armor }}</pre> +<pre> +gpg2 --keyserver hkp://{{ request.get_host }} --recv-key 0x{{ publickey.details.id }} +</pre> +<p> +<span style="font-family: monospace; font-weight: bold">{{ publickey.details.fingerprint }} +{% for sig in publickey.details.signatures %} + <span style="font-family: monospace">{{ sig.signer }}</span> + ({{ sig.created|date:"Y-m-d" }} – {{ sig.expires_at|date:"Y-m-d"|default:"never" }})<br /> +{% endfor %} +</p> +<h3>User Ids</h3> +<ul> +{% for uid in publickey.details.userids %} + <li> + {{ uid.name }} + {% if uid.comment %}({{ uid.comment }}) {% endif %} + <<a href="mailto:{{ uid.email }}">{{ uid.email }}</a>><br> + {% for sig in uid.signatures %} + <span style="font-family: monospace">{{ sig.signer }}</span> + ({{ sig.created|date:"Y-m-d" }} – {{ sig.expires_at|date:"Y-m-d"|default:"never" }})<br /> + {% endfor %} + </li> +{% endfor %} +</ul> +<h3>Subkeys</h3> +<ul> +{% for key in publickey.details.subkeys %} + <li> + <span style="font-family: monospace; font-weight: bold">{{ key.fingerprint }}</span><br /> + {% for sig in key.signatures %} + <span style="font-family: monospace">{{ sig.signer }}</span> + ({{ sig.created|date:"Y-m-d" }} – {{ sig.expires_at|date:"Y-m-d"|default:"never" }})<br /> + {% endfor %} + </li> +{% endfor %} +</ul> +<h3>Key data</h3> +<textarea cols="80" rows="20" readonly>{{ publickey.armor }}</textarea> {% endblock %} diff --git a/pgp/views.py b/pgp/views.py index 88cb030..bf6513e 100644 --- a/pgp/views.py +++ b/pgp/views.py @@ -8,6 +8,13 @@ from guardian.utils import get_anonymous_user from . import models from . import forms +from django import template + +register = template.Library() +@register.simple_tag +def get_private_attribute(model_instance, attrib_name): + return getattr(model_instance, attrib_name, '') + class PublicKeyListView(PermissionListMixin, ListView): model = models.PublicKey permission_required = ['view_publickey'] -- GitLab