From 7a294b88c9f9ef0600034a00d1b9ff41025b8de2 Mon Sep 17 00:00:00 2001 From: Ari Archer Date: Wed, 21 Aug 2024 11:17:47 +0300 Subject: [PATCH] update @ Wed Aug 21 11:17:47 EEST 2024 Signed-off-by: Ari Archer --- blog.json | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/blog.json b/blog.json index 1f6b89c..7fbd4ea 100644 --- a/blog.json +++ b/blog.json @@ -128,24 +128,6 @@ "top-words": 64, "top-tags": 64, "posts": { - "openpgpkey-records-are-cool": { - "title": "OPENPGPKEY records are cool", - "description": "Dive into the world of email security with the OPENPGPKEY DNS record! This powerful tool is essential for encryption and authentication in today's digital landscape. I'll break down the specifications from RFC 7929, guide you through creating your own OPENPGPKEY record generator, and highlight common mistakes to avoid that were made by others. This guide will help you to understand the OPENPGPKEY record. Join me in making the internet and email a more secure place!", - "content": "OPENPGPKEY are a nice feature of modern DNS for email encryption and authentication. Let's see what talk there is about it!\n\n## OPENPGPKEY DNS record & resources online\n\nI just found out about OPENPGPKEY records in modern DNS while exploring the [deSEC homepage](https://desec.io/).\nI logged into my deSEC account and there it was - OPENPGPKEY DNS record type.\n\nWell, I wondered - what is it, and how can I set it up.\n\nFirstly, I stumbled upon [ClouDNS' article about OPENPGPKEY](https://www.cloudns.net/wiki/article/382/)\nwhich I found pretty unhelpful, as it seemingly explained nothing, and not only that - it\nseemingly provided incorrect information which contradicts the OPENPGPKEY RFC, which I will\ncover a bit later on.\n\nRegardless, after I realised that article was wrong, I tried to look for DNS record generators,\none result - . Well, I clicked on it and tried to generate\nan OPENPGPKEY DNS record multiple times and it ended up returning nothing, which disappointed me\nat the time. I thought 'welp, I can't take the black box approach now.' and was stuck for a couple\nof seconds until I saw what it stated on its homepage:\n\n> The OPENPGPKEY DNS record is specied in RFC 7929. The localpart of the uid is encoded as a DNS label containing the hexdump of the SHA-256 hash of the utf-8 encoded localpart, truncated to 28 octets. Normally the \"Standard\" output format should be used. The \"Generic Encoding\" output format is provided to help work with older DNS software that does not yet understand the OPENPGPKEY record type.\n\nWhich led me to the RFC document at which is finally where I found my answers!\n\nI began hand-crafting my own OPENPGPKEY record generator based off the RFC.\n\n## OPENPGPKEY record generator\n\nI read the intro of the aforementioned RFC until I found this:\n\n> 3. Location of the OPENPGPKEY Record\n>\n> The DNS does not allow the use of all characters that are supported\n> in the \"local-part\" of email addresses as defined in [RFC5322] and\n> [RFC6530]. Therefore, email addresses are mapped into DNS using the\n> following method:\n>\n> 1. The \"left-hand side\" of the email address, called the \"local-\n> part\" in both the mail message format definition [RFC5322] and in\n> the specification for internationalized email [RFC6530]) is\n> encoded in UTF-8 (or its subset ASCII). If the local-part is\n> written in another charset, it MUST be converted to UTF-8.\n>\n> 2. The local-part is first canonicalized using the following rules.\n> If the local-part is unquoted, any comments and/or folding\n> whitespace (CFWS) around dots (\".\") is removed. Any enclosing\n> double quotes are removed. Any literal quoting is removed.\n>\n> 3. If the local-part contains any non-ASCII characters, it SHOULD be\n> normalized using the Unicode Normalization Form C from\n> [Unicode90]. Recommended normalization rules can be found in\n> Section 10.1 of [RFC6530].\n>\n> 4. The local-part is hashed using the SHA2-256 [RFC5754] algorithm,\n> with the hash truncated to 28 octets and represented in its\n> hexadecimal representation, to become the left-most label in the\n> prepared domain name.\n>\n> 5. The string \"_openpgpkey\" becomes the second left-most label in\n> the prepared domain name.\n>\n> 6. The domain name (the \"right-hand side\" of the email address,\n> called the \"domain\" in [RFC5322]) is appended to the result of\n> step 2 to complete the prepared domain name.\n>\n> For example, to request an OPENPGPKEY resource record for a user\n> whose email address is \"hugh@example.com\", an OPENPGPKEY query would\n> be placed for the following QNAME: \"c93f1e400f26708f98cb19d936620da35\n> eec8f72e57f9eec01c1afd6._openpgpkey.example.com\". The corresponding\n> RR in the example.com zone might look like (key shortened for\n> formatting):\n>\n> c9[..]d6._openpgpkey.example.com. IN OPENPGPKEY \\\n\nBased off this part alone pretty much, I made a shell script that FINALLY generated\na valid output! It is located at \nlicensed under the public domain (CC0) and it looks like this:\n\n #!/usr/bin/env sh\n\n ...\n\n set -eu\n\n main() {\n if [ \"$#\" -ne 2 ]; then\n {\n echo \"Generates an OPENPGPKEY DNS record based off your Email and a Public GPG key ID.\"\n echo \"Usage: $0 \"\n } >&2\n return 1\n fi\n\n # Confirm user localpart\n\n localpart=\"$(printf -- '%s' \"$1\" | cut -d'@' -f1 | tr '[:upper:]' '[:lower:]')\"\n\n printf -- \" * Your email username (localpart) is '\\033[1m%s\\033[0m', correct? In lowecase, enter either 'y' (for yes) or 'n' (for no): \" \"$localpart\"\n read -r yn\n if [ \"$yn\" -ne 'y' ]; then\n echo \" * Incorrect information provided.\" >&2\n return 1\n fi\n\n # Localpart digest is the SHA256 hex digest truncated to 28 octets\n localpart_digest=\"$(printf -- '%s' \"$localpart\" | sha256sum | cut -d' ' -f1 | cut -c1-28)\"\n\n # And the value has to be the base64-encoded public key, exported as binary\n gpg_public_key_b64=\"$(gpg --export --export-options export-minimal,no-export-attributes -- \"$2\" | base64 -w 0)\"\n\n printf '\\n\\033[32m%s\\033[0m._openpgpkey. \\033[90mIN OPENPGPKEY\\033[0m \\033[1m%s\\033[0m\\n' \"$localpart_digest\" \"$gpg_public_key_b64\"\n }\n\n main \"$@\"\n\n(`...` just signifies the cut out status message, author, and license)\n\nThe main functionality is located in two lines of code:\n\n # Localpart digest is the SHA256 hex digest truncated to 28 octets\n localpart_digest=\"$(printf -- '%s' \"$localpart\" | sha256sum | cut -d' ' -f1 | cut -c1-28)\"\n\n # And the value has to be the base64-encoded public key, exported as binary\n gpg_public_key_b64=\"$(gpg --export --export-options export-minimal,no-export-attributes -- \"$2\" | base64 -w 0)\"\n\n`localpart_digest` SHA-256 hex digest of the localpart (username) of an email address (for example hi@ari.lt becomes just 'hi').\nAs per the RFC point 3.4 it is truncated to 28 octets, for which we use the `cut` utility.\n\n`gpg_public_key_b64` is the public key encoded in base64, pretty self-explanatory. It exports solely the key by using\nGPG options, ignoring all attributes and only exporting the essential parts of the key, and then encoding it in a single-line\nof base64.\n\nAfter which, we just print out the DNS record in a pretty way :D\n\n ._openpgpkey. IN OPENPGPKEY \n\nAnd now, you can even verify my key this way by checking the OPENPGPKEY records on `d2efaa6dd6ae6136c19944fae329._openpgpkey.ari.lt` :)\n\n## Alright, what's wrong with the ClouDNS article and the generator?\n\n- ClouDNS article: It does not strictly follow the RFC7929 specification, and does not specify any information that would be helpful in understanding this record. In fact, it provides contradictory information when having the RFC as the reference because it does not specify the hashing algorithm (just says `hashedLocalPart`) and nowhere does mention the required truncation, in fact, it shows that the whole hash should be included, or a part of it? It seems to be truncating some hex digest to 56 characters.\n- Generator: For the first few times I tried to generate the records, it returned me nothing. That's what got me going down the rabbit hole of hand-crafting my own. After trying now it seems to generate output. The output seems to be wrong as well because it seems to generate the same 56 octet hash, rather than RFC-specified 28 octets despite having the quote on their homepage.\n\nI don't think either of them could be misunderstanding the RFC because there's no mention of the number 56 in the RFC. Probably just an honest mistake.\n\nOf course, no hate or anything! Just the inaccuracies I found frustrating myself, and I am writing in hope that people find this and find this post helpful, and I'm hoping the generator as well as the ClouDNS article get fixed :)\n\nPeace :)", - "keywords": [ - "dns record generator", - "email encryption", - "modern dns features", - "gpg public key", - "email authentication", - "rfc 7929", - "openpgpkey dns records", - "openpgpkey setup", - "dns security", - "local-part hashing" - ], - "created": 1724215850.778874 - }, "ariweb-status-page": { "title": "ari-web status page", "description": "Ari-web status hosted by FSKY: status.ari.lt :)",