-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Some of you may remember earlier on in the year I went through a phase of wanting to sign my posts with PGP. This plan fell to the wayside fairly quickly and got "placed on the backburner" i.e. I will fix this when I figure out how. Well, after finding myself away from work for a week I have taken the time to figure this out. ## Taking advantage of the new feature Before I get into how I did this I want to clarify how you can take advantage of this new feature. Every post now has an accompanying plaintext page showing the signature. An example of this is the section page for the signing posts project - - **Main page -** https://eddiequinn.xyz/build-logs/eddiequinn.xyz/signing-posts/ - - **Sig page -** https://eddiequinn.xyz/sigs/build-logs/eddiequinn.xyz/signing-posts/sig.txt The reason why I did it this way was to make it easier to curl the file, and pipe that into `gpg --verify`. This however will only work if you have my public key in your keyring. Please use the following two commands to install my key and verify the post. ```bash # Install my public key curl https://keybase.io/eddiequinn/pgp_keys.asc | gpg --import # Verfy the post curl -sS https://eddiequinn.xyz/sigs/build-logs/eddiequinn.xyz/signing-posts/sig.txt | gpg --verify - ``` ## How I did it For full details on this, I would seriously recommend looking at [build logs](/build-logs/eddiequinn.xyz/signing-posts/). That gives the full details of my thought process as this project was built out, including my various mistakes. The crux of the way this works is based on three factors 1) Hugos multiple output formats 2) Storing posts in a folder inside `content` called `sigs` 3) A custom Python script **Multiple output formats** Hugo supports [custom output formats](https://gohugo.io/templates/output-formats/), which can be defined in the `hugo.toml` file. What this essentially means in layman's terms is that hugo can output content in not just HTML, but many other options. These include e-books, calendars, and JSON; the most important in this case is `text/plain` which outputs in in plaintext form. The actual `toml` code establishing these is shown below ```toml [outputFormats] [outputFormats.standardFormat] name = "standard-format" baseName = "index" mediaType = "text/html" path = "" permalinkable = true weight = 1 [outputFormats.sigFormat] name = "sig-format" baseName = "sig" mediaType = "text/plain" path = "" permalinkable = true weight = 2 ``` As can be seen, these follow a standard layout. - - **name -** This is the name it will be referred by in any YAML frontmatter - - **baseName -** This is the name for files that appear i.e. `sig.txt` - - **isPlainText -** Still not 100% sure what this does, I'm yet to delete it however - - **mediaType -** This is where you establish what type of media output you want i.e `text/html` for `HTML` & `text/plain` for plaintext - - **path -** This is where you establish a subpath to save the files - - **permalinkable -** Allows the page to be permalinkable - - **weight -** Setting this to a non-zero value will be used as the first sort criteria. **Storing posts in `content/sigs`** In an ideal world, I would have been able to generate two outputs from the same file, but in practicality, this wasn't possible. I'll get into why during the Python script section, but as a bodge I am storing the posts signed inside the `content/sigs` directory. This means all posts had to have their GPG signatures added and change their YAML front matter to say `outputs: sig-format`. This, in reality, was quite simple to do but was imperative for the script to work **Python script** The core functionality of the script is to strip out PGP artefacts in the main posts. In an *ideal world* I could have found a way to get this done without the need to use an activated separately to `hugo -t risotto`. The issue is I could not find a way to filter things out of the content of a post during the build process; I could have used `replaceRe` but some of my posts contain PGP-signed messages within them, and RE doesn't cope well with nested structures. To see the script id recommendation [click here](https://gist.github.com/eddiebquinn/9b3d2b59bef080a62db7866d13d53ec9) To simplify its functionality, it does the following 1) Maps out the directory structure, removing `sigs`, `.git`, `.gitignore` from the list to avoid those being tampered with 2) Deleted all items in the `content` directory other than the `sigs` directory and its contents 3) Copies all files out of the `sigs` directory into the content directory 3) Recursivley edits all files to remove PGP artefacts and updates YAML to output it as the correct format ## Clarifications There are limitations to this method. One that was brought up to me by a friend is that with pages like [build-logs](/build-logs), the links are not part of the signed post. This is mainly due to how the site is built. Within Hugo, there is a template called `list.html`. This template is used to output pages like [build-logs](/build-logs), where it acts as a directory too other posts. An example of this template is shown below ```html {{ define "main" }}

{{ .Title | markdownify }}

{{ .Content }} {{ end }} {{define "aside" }} {{ if .Params.description }}

{{ .Params.description }}

{{ end }} {{ end }} ``` The part that is signed is the `.Content`. I would argue that this makes sense, given I didn't put the links there, a script did *but* this does deserve to be clarified. ## What next I'm going to go over my plans following this in the accompanying post I'll do in the build logs section, however in short this has somewhat negatively affected my workflow. I have plans to rectify this, mainly revolving around a few new scripts, and potentially cloning a repo and creating a "writing environment" where I can just write my posts. This has also messed with the formatting of some posts, but again, fairly easy to fix (I hope). Keep an eye out for that post! -----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEEVR2DXk8VSeBYxT6vvUo0nUeoF5wFAmVhRCUACgkQvUo0nUeo F5zPFg//alp38v3QzU7nZj5jhNJoWHZ1Z8L8vTyNTMamp6TAprKS6+p3ikM5ldpW vBYOTksataRzqLQIpb6yigeYWYUyicLAyMKS5V04DmItKJMLpgzF5kUkjhDbGliS M6YmJlS2EABHJAFnxM/vpCyQAM56ruKbiAGUS27iDOCsEBZUfzGwBOp/fmpkYNSj ySAnc8vaVMk0mjvZ8wszVCKrXNRZqUS8YGLWmDFqK52JWBeeiOkQdC9F1iKEWoaV dVzKd50O5oEu4qeZ313kaHf3E2Q+uxkgWL1QpbN6DKkdZAJcw5Uu6DseeNhioSdH qS4KUskhijgvQ7ng3/0LEoS/UPetTcBJJ1UCDxu7GvF2eMY7SUxedppK+g8pxz1y vaWkN0mgcI1Z45EWDX5dZw9qoo/xDWHQqLVvaJsmtgBJKS6yQUC0P2RTYn/gMEUc DvdhUWIIjgDsWd97SPoVTKiLDiKIm/eRl12BNzVReo5fghn/bAFKC/WqIhPkY8FN aoEHYa+U96GYtcoTnJzrkBApzBVunaCObiTwSVo0fffXJpRJjgAbuBoYs/fUBPmB 0gbxKLglw8qCQ5R4iLrbC2wef7tA3y4qikSkLGqTb1PetVhEtNmj5TTAPvCdt0CO lOkFmqbYqWs/cX6bb4pfalChPgnFAz1Uyz/xxECrI8+QzE5iAXo= =bTPb -----END PGP SIGNATURE-----