I recently discovered a new DNS Resource Record type called OPENPGPKEY. Being a user of OpenPGP and having some interest in DANE, I decided to give it a try.

The RR is specified in RFC7929, which is still an experimental RFC. I think it is important to mention that the use of the OPENPGPKEY RR has some security implications that shouldn’t be ignored by users. They are talked about in detail in Section 7 of the aforementioned RFC.

Creating an OPENPGPKEY Resource Record

Creating the resource record is a rather simple operation. The name is formed by a SHA-256 hash of the local part of the email address truncated to 28 octets (or 56 chars) in hexadecimal. This is then followed by a _opengpgkey on the next level. The domain part of the email address is then appended to it and that forms the FQDN.

The data part is simply the public key, encoded in Base64. Special case should be taken with the size, as PGP keys can be quite big. Some considerations in regards to size are listed in Section 2.1.2 of the RFC.

As an example, let’s take something@yolo.engineer. The first part of the FQDN can be created with:

1
2
$ echo -n 'something' | sha256sum | head -c56
3fc9b689459d738f8c88a3a48aa9e33542016b7a4052e001aaa536fc

To that we append _openpgpkey.yolo.engineer and we have our FQDN.

The data part, you can create by using gpg --armor --export <key_id> and cutting out the -----BEGIN PGP PUBLIC KEY BLOCK----- and -----END PGP PUBLIC KEY BLOCK----- lines.

A full RR entry for BIND DNS would look like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
3fc9b689459d738f8c88a3a48aa9e33542016b7a4052e001aaa536fc._openpgpkey.yolo.engineer. IN OPENPGPKEY (
mDMEZPtAEBYJKwYBBAHaRw8BAQdAqJ/e3L2/uDv6zwrhredkZVMOWoF14m9aYInO
NTOUSLu0JUx1aXogQW1hcmFsIDxzb21ldGhpbmdAeW9sby5lbmdpbmVlcj6IkAQT
FggAOBYhBOKRF57s2nWdVYifncMNCNLw/1gbBQJk+0AQAhsDBQsJCAcCBhUKCQgL
AgQWAgMBAh4BAheAAAoJEMMNCNLw/1gbHiIA/Aj02mx3YxQVG6PyvwijhqAoDxW5
ZV9clhPCCWGUyVElAP48C+/M95J1zB13GXmKzL0+R8KFeoZvaGmCN3ElWvswD7g4
BGT7QBASCisGAQQBl1UBBQEBB0DOFGZlkXDvlcQwGITVXegvtc4R2V8NmwrXasNK
1J78BAMBCAeIeAQYFggAIBYhBOKRF57s2nWdVYifncMNCNLw/1gbBQJk+0AQAhsM
AAoJEMMNCNLw/1gbwaIA/iRXPjZ5VnRJUAmpI/g7FntiSNTdaIE0chmB2t4tKfXW
AQD8B4v1B4y0e7CJe+Lgfi+O9qyaNBX2j6Rbp3JEQaPRCA==
)

Importing keys published via DNS/DANE

Importing keys published via this method is quite trivial as the gpg binary provides tooling for it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$gpg --auto-key-locate clear,nodefault,dane --locate-keys something@yolo.engineer
gpg: keybox '/tmp/tmp.WLxaRGRvRP/pubring.kbx' created
gpg: /tmp/tmp.WLxaRGRvRP/trustdb.gpg: trustdb created
gpg: key C30D08D2F0FF581B: public key "Luiz Amaral <something@yolo.engineer>" imported
gpg: Total number processed: 1
gpg:               imported: 1
pub   ed25519 2023-09-08 [SC]
      E291179EECDA759D55889F9DC30D08D2F0FF581B
uid           [ unknown] Luiz Amaral <something@yolo.engineer>
sub   cv25519 2023-09-08 [E]

It is important to remember that the imported key fingerprint should still be checked in an out-of-band manner, as recommended by the RFC.