commit 57a8fc9cede9e701b644ab06848d229fc37fbde4
parent 0f0b86b3963c22d22d5bdde047eeae968285bb55
Author: Jack Sangdahl <jack@pngu.org>
Date: Fri, 16 Jan 2026 19:28:41 -0700
Migration of some pages to new structure
Diffstat:
| A | content.html | | | 42 | ++++++++++++++++++++++++++++++++++++++++++ |
| D | extra.html | | | 110 | ------------------------------------------------------------------------------- |
| A | gpg_key_git.html | | | 46 | ++++++++++++++++++++++++++++++++++++++++++++++ |
| A | hardware_key.html | | | 121 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | index.html | | | 70 | +++++++++++++++++++++++----------------------------------------------- |
| M | kernel.html | | | 58 | +++++++++++++++++++++++++--------------------------------- |
| D | projects.html | | | 283 | ------------------------------------------------------------------------------- |
| A | ssh_agent.html | | | 50 | ++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | style.css | | | 19 | +++++++++++++++---- |
| A | synacor.html | | | 225 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | template.html | | | 7 | ++++--- |
| A | wpa_supplicant.html | | | 43 | +++++++++++++++++++++++++++++++++++++++++++ |
12 files changed, 594 insertions(+), 480 deletions(-)
diff --git a/content.html b/content.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <title>Content</title>
+ <script src="header.js"></script>
+ </head>
+ <body>
+ <a style="text-decoration: none" href="index.html"><--</a>
+ <h3>Content & Postings</h3>
+ <h4>Computers</h4>
+ <ul>
+ <li>Gentoo Desktop</li>
+ <li>Artix Laptop</li>
+ <li>macOS Laptop</li>
+ <li>Programs & Utilities</li>
+ <li><a href="kernel.html">Kernel Configuration</a></li>
+ </ul>
+ <h4>Keyboards</h4>
+ <ul>
+ <li>QMK Firmware</li>
+ <li>Designs</li>
+ </ul>
+ <h4>Projects</h4>
+ <ul>
+ <li>Leetcode</li>
+ <li>Cryptopals</li>
+ <li>Advent of Code</li>
+ <li><a href="synacor.html">Synacor Challenge</a></li>
+ <li><a href="hardware_key.html">Linux Hardware Authenticator Key</a></li>
+ </ul>
+ <h4>Miscellaneous</h4>
+ <p>Mostly system configuration notes for myself</p>
+ <ul>
+ <li><a href="gpg_key_git.html">GPG key signing with Git</a></li>
+ <li><a href="ssh_agent.html">SSH agent for password-less login</a></li>
+ <li><a href="wpa_supplicant.html">WPA Supplicant usage</a></li>
+ </ul>
+ <script src="frame.js"></script>
+ </body>
+</html>
diff --git a/extra.html b/extra.html
@@ -1,110 +0,0 @@
-<html lang="en">
- <head>
- <title>Extra Extra</title>
- <link rel="stylesheet" href="style.css">
- <link rel="apple-touch-icon" sizes="180x180" href="data/favicon/apple-touch-icon.png">
- <link rel="icon" type="image/png" sizes="32x32" href="data/favicon/favicon-32x32.png">
- <link rel="icon" type="image/png" sizes="16x16" href="data/favicon/favicon-16x16.png">
- <link rel="manifest" href="data/favicon/site.webmanifest">
- <style>
- code {
- border: 1px solid grey;
- border-radius: 3px;
- color: #434C5E;
- padding: 1.5px;
- }
- pre {
- background: #f4f4f4;
- border: 1px solid #grey;
- color: #434C5E;
- padding-top: 20px;
- padding-left: 20px;
- overflow: auto;
- }
- </style>
- </head>
- <body>
- <a style="text-decoration: none;" href="content.html"><--</a>
- <h2>Some bits & bobs</h2>
- <h5>2023-11-14</h5>
- Here lives some miscellaneous things I reference one or one hundred
- times and figure they should be gathered somewhere.
- <h3>WPA Supplicant</h3>
- Frequently forgotten usage of the <code>wpa_cli</code> tool
- <pre>
-> scan
-...
-<3>CTRL-EVENT-SCAN-RESULTS
-> scan_results # run once above event appears
-bssid / freq / sig lvl / flags / ssid
-...
-> add_network
-#
-> set_network # ssid "network"
-> set_network # psk "psswd"
-# or if no password:
-> set_network # key_mgmt NONE
-> enable_network #
-> save_config
- </pre>
- <h3>GPG key signing with Git</h3>
- Sometime ago I spent hours on this. When signing a
- commit, this error would appear
- <pre>
-gpg: skipped "Foo Bar <Foo_Bar@baz>": No secret key[GNUPG:] INV_SGNR 9 Foo Bar <Foo_Bar@baz>[GNUPG:] FAILURE sign 17
-gpg: signing failed: No secret key
- </pre>
- After much searching I came up empty handed. Finally, one thing
- stood out. The name and email in <code>~/.gitconfig</code> must
- match exactly to the name and email associated with the GPG key
- <pre>
-$ gpg --list-secret-keys --keyid-format=long
-/home/foo/.gnupg/pubring.kbx
------------------------------
-sec rsa4096/FC53C827D09C7050 2019-03-24 [SC]
- ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
-uid [ultimate] <b>Foo Bar <Foo_Bar@baz></b>
-ssb rsa4096/2EE67124D597BB00 2019-03-24 [E]
-
-$ head -n 4 .gitconfig
-[user]
- <b>name = Foo Bar
- email = Foo_Bar@baz</b>
- signingkey = FC53C827D09C7050
- </pre>
- <h3>SSH agent for password-less login</h3>
- I have numerous machines I frequently log in to and from via SSH. Typing
- in a password every time is tiresome and a password-less key is not
- an option. A solution is an SSH agent running in the background, which
- prompts for a password once at log in, and stores it for the duration
- of the session (until reboot). The following can live in your shell's
- startup file (e.g. <code>~/.zshrc</code>)
- <pre>
-if [ ! -S ~/.ssh/ssh_auth_sock ]; then
- eval "$(ssh-agent)"
- ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
-fi
-export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
-ssh-add -l > /dev/null || ssh-add
- </pre>
- Then, just copy the needed key between machines with <code>ssh-copy-id -i ~/.ssh/id_xxx.pub name@host</code>
- <h3>Configuration file manager</h3>
- Across the aforementioned machines, I also have various configuration
- files that I like to keep track of for the sake of backing
- them up in case of data loss. I use <a href="https://github.com/TheLocehiliosan/yadm" target="_blank">yadm</a>
- to achieve this. Mostly for it's ease of use (yadm is quite simply
- an alias for git) and minimal system footprint, which consists mostly
- of a git directory living out of sight in <code>~/.local/share/yadm/repo.git</code>.
- Since it's just Git under the hood, a standard <code>.gitignore</code>
- file can be used to ignore which ever files you choose in your home directory.
- By default, yadm only manages files within your home directory. While not
- conventional, it can also be used to track system-level files by creating
- an alias like <code>sysyadm="sudo yadm --yadm-dir /etc/yadm --yadm-data /etc/yadm/data"</code>,
- then used like normal.
- <pre>
-# sysyadm init -w /
-# sysyadm add foo.conf
-# sysyadm commit -m "foo"
- </pre>
- </body>
-</html>
diff --git a/gpg_key_git.html b/gpg_key_git.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <title>GPG key signing with Git</title>
+ <script src="header.js"></script>
+ </head>
+ <body>
+ <a style="text-decoration: none" href="content.html"><--</a>
+ <h2>GPG key signing with Git</h2>
+ <p><i>2023-11-14</i></p>
+ <hr />
+ <p>
+ I spent much time trying to figure out the following error when trying to
+ sign a commit:
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block">
+ gpg: skipped "Foo Bar <FooBar@baz>": No secret key[GNUPG:] INV_SGNR 9 FooBar <FooBar@baz>[GNUPG:] FAILURE sign 17
+ gpg: signing failed: No secret key
+ </div>
+ <p>
+ After searching and coming up empty handed, one thing stood out. The name
+ and email in <code>~/.gitconfig</code> must match exactly to the name and
+ email associated with the GPG key:
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block language-shell">
+ $ gpg --list-secret-keys --keyid-format=long
+ /home/foo/.gnupg/pubring.kbx
+ -----------------------------
+ sec rsa4096/FC53C827D09C7050 2019-03-24 [SC]
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
+ uid [ultimate] <b>Foo Bar <Foo_Bar@baz></b>
+ ssb rsa4096/2EE67124D597BB00 2019-03-24 [E]
+
+ $ head -n 4 .gitconfig
+ [user]
+ <strong>name = Foo Bar
+ email = Foo_Bar@baz</strong>
+ signingkey = FC53C827D09C7050
+ </div>
+ <script src="frame.js"></script>
+ </body>
+</html>
diff --git a/hardware_key.html b/hardware_key.html
@@ -0,0 +1,121 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <title>Linux Hardware Authenticator</title>
+ <script src="header.js"></script>
+ </head>
+ <body>
+ <a style="text-decoration: none" href="content.html"><--</a>
+ <h2>Hardware security key for authentication on Linux</h2>
+ <p><i>2024-03-01</i></p>
+ <hr />
+ <p>
+ Typing in a rather long password each time I log into my computer or need
+ to complete a privileged task can be bothersome. Sometime ago I came
+ across
+ <a href="https://github.com/solokeys" target="_blank">Solokeys</a>, which
+ are open source hardware and firmware security keys. I chose to build the
+ <a href="https://github.com/solokeys/solo-hw" target="_blank">Solo 1</a>
+ (or five because that's the MOQ from most PCB manufacturers). Note, at the
+ time of writing this, the
+ <a href="https://github.com/solokeys/solo1-cli" target="_blank"
+ >solo1-cli</a
+ >
+ tool is somewhat broken with the latest FIDO2 library, meaning it must be
+ installed explicitly at 0.9.3.
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block language-shell">
+ $ pip install solo1
+ $ pip install fido2==0.9.3
+ </div>
+ <p>
+ After building, I didn't use it much, as many services don't support
+ security keys quite yet, or required a paid subscription (I.e. Bitwarden).
+ I found
+ <a href="https://github.com/Yubico/pam-u2f" target="_blank"
+ >Yubico's PAM for U2F</a
+ >, which is a PAM module to provide authentication from a U2F device.
+ </p>
+ <p>
+ To use this, first ensure the kernel parameters
+ <code>CONFIG_HIDRAW</code> and <code>CONFIG_USB_HIDDEV</code> are enabled.
+ Next, obtain the module via package manager or compiling from source and
+ generate the authorisation mapping with your key inserted. The created
+ directory must be named <code>Yubico</code>, even if not using a Yubico
+ key. It can be overridden in
+ <a
+ href="https://github.com/Yubico/pam-u2f/blob/ffdef7df696ee6054cccd8e2302731b036d9cf64/util.h#L16"
+ target="_blank"
+ >util.h</a
+ >
+ if you choose however.
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block language-shell">
+ $ mkdir ~/.config/Yubico
+ $ pamu2fcfg > ~/.config/Yubico/u2f_keys
+ Enter PIN for /dev/hidraw2:
+ </div>
+ <p>
+ Assuming all has been successful, you can configure PAM services to use
+ the device. The following configures
+ <a href="https://github.com/Duncaen/OpenDoas" target="_blank">Doas</a> to
+ utilise the U2F module in the <code>/etc/pam.d/doas</code> file. The same
+ line can be added in other files where needed (eg. display manager,
+ <code>system-local-login</code>, etc.)
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block language-shell">
+ auth sufficient pam_u2f.so cue pinverification=0
+ auth include system-auth
+ ...
+ </div>
+ <p>
+ Above, <strong>sufficient</strong> indicates that authentication from the
+ device alone is enough to fully authenticate. Use
+ <strong>required</strong> instead if you want both password and device
+ authentication to be required. <strong>cue</strong> simply displays a
+ prompt to press the button on the device when needed to authenticate.
+ <strong>pinverification=0</strong> disables the need to entre the
+ passphrase associated with your security key. Note, this means your system
+ can be accessed only with your key, and no password entry of any type. Set
+ the parameter to <strong>1</strong> if you'd like otherwise.
+ </p>
+ <p>
+ Another thing of interest was locking/unlocking my system automatically
+ when the key is removed/inserted, respectively. This can be achieved via a
+ custom Udev rule that executes a script when a device matching the key's
+ VID/PID is plugged in. This script will use
+ <a href="https://pamtester.sourceforge.net" target="_blank">pamtester</a>
+ to test for authentication success.
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block language-shell">
+ #!/bin/bash
+
+ if [ "$1" == "lock" ]; then
+ # lock system (e.g. gtklock -d)
+ else
+ if [ echo "" | pamtester login >user< authenticate ]; then
+ # kill lock program
+ fi
+ fi
+ exit 0
+ </div>
+ <p>
+ Now, a custom udev rule that lives in
+ <code>/etc/udev/rules.d/70-solokey.rules</code>
+ and looks for a matching VID/PID and executes this script when found with
+ the appropriate argument.
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block language-shell">
+ ACTION::"remove", ENV{DEVTYPE}::"usb_device", ENV{PRODUCT}::"0483/a2Ca", RUN+:"/usr/local/sbin/keyauth.sh lock"
+ ACTION::"add", ENV{DEVTYPE}::"usb_device", ENV{ID_BUS}::"usb", ENV{PRODUCT}::"0483/a2Ca", RUN+:"/usr/local/sbin/keyauth.sh unlock"
+ </div>
+ <script src="frame.js"></script>
+ </body>
+</html>
diff --git a/index.html b/index.html
@@ -33,10 +33,10 @@
</center>
<h3>Contact & Platforms</h3>
<div class="header">
- <p>
- Email:
- <!-- prettier-ignore -->
- <span class="email">
+ <p>
+ Email:
+ <!-- prettier-ignore -->
+ <span class="email">
_ _ ____
(_) __ _ ___| | __/ __ \ _ __ _ __ __ _ _ _ ___ _ __ __ _
| |/ _` |/ __| |/ / / _` | '_ \| '_ \ / _` | | | | / _ \| '__/ _` |
@@ -44,51 +44,27 @@
_/ |\__,_|\___|_|\_\ \__,_| .__/|_| |_|\__, |\__,_(_)___/|_| \__, |
|__/ \____/|_| |___/ |___/
</span
- ><br />
- PGP:
- <a
- href="https://keys.openpgp.org/vks/v1/by-fingerprint/CF27648C14B46FAA922F62D7FC53C827D09C7050"
- target="_blank"
- >CF27648C14B46FAA922F62D7FC53C827D09C7050</a
- ><br />
- Libera.chat: <code>/whois tomatofan87</code>
- <br>
- Github: <a href="https://github.com/waffle87" target="_blank">waffle87</a>
- <br />
- Leetcode: <a href="https://leetcode.com/0x6A73" target="_blank">0x6A73</a>
- <br />
- </p>
+ ><br />
+ PGP:
+ <a
+ href="https://keys.openpgp.org/vks/v1/by-fingerprint/CF27648C14B46FAA922F62D7FC53C827D09C7050"
+ target="_blank"
+ >CF27648C14B46FAA922F62D7FC53C827D09C7050</a
+ ><br />
+ Libera.chat: <code>/whois tomatofan87</code>
+ <br />
+ Github:
+ <a href="https://github.com/waffle87" target="_blank">waffle87</a>
+ <br />
+ Leetcode:
+ <a href="https://leetcode.com/0x6A73" target="_blank">0x6A73</a>
+ <br />
+ </p>
</div>
<hr />
- <h3>Content & Postings</h3>
- <h4>Computers</h4>
- <ul>
- <li>Gentoo Desktop</li>
- <ul>
- <li>Kernel Configuration</li>
- </ul>
- <li>Artix Laptop</li>
- <li>macOS Laptop</li>
- </ul>
- <h4>Keyboards</h4>
- <ul>
- <li>QMK Firmware</li>
- <li>Designs</li>
- </ul>
- <h4>Projects</h4>
- <ul>
- <li>Leetcode</li>
- <li>Cryptopals</li>
- <li>Advent of Code</li>
- <li>Synacor Challenge</li>
- </ul>
- <h4>Miscellaneous</h4>
- <ul>
- <li>WPA Supplicant</li>
- <li>GPG key signing with Git</li>
- <li>SSH agent for password-less login</li>
- <li>Configuration file manager</li>
- </ul>
+ <center>
+ <a href="content.html">more...</a>
+ </center>
<script src="frame.js"></script>
</body>
</html>
diff --git a/kernel.html b/kernel.html
@@ -1,26 +1,14 @@
<html lang="en">
<head>
- <meta charset="UTF-8" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Kernel Configuration</title>
- <link rel="stylesheet" href="style.css" />
- <link rel="apple-touch-icon" sizes="180x180" href="data/favicon/apple-touch-icon.png">
- <link rel="icon" type="image/png" sizes="32x32" href="data/favicon/favicon-32x32.png">
- <link rel="icon" type="image/png" sizes="16x16" href="data/favicon/favicon-16x16.png">
- <link rel="manifest" href="data/favicon/site.webmanifest">
- <style>
- code {
- color: #505050;
- font-size: 10px;
- border: 1px solid grey;
- border-radius: 3px;
- padding: 1.75px;
- }
- </style>
+ <script src="header.js"></script>
</head>
<body>
- <a style="text-decoration: none" href="content.html"><--</a>
+ <a style="text-decoration: none" href="content.html"><--</a>
<h2>Kernel Configuration Pseudo Guide</h2>
- <h5>2024-04-08</h5>
+ <p><i>2024-08-14</i></p>
<h4>
Current base:
<a
@@ -29,22 +17,25 @@
>Linux 6.9.y</a
>
</h4>
- This aims to be a guide for configuring a Linux kernel for a modern x86_64
- machine containing hardware commonly found in laptops, desktops, and other
- consumer computers. Note, this guide will sway more minimally, meaning some
- features that are not strictly required will not be enabled. All features
- will be built directly into kernel, no modules. This article will not
- attempt to cover all possible configuration options, as it omits entire
- sections that are not relevant on such systems, as well as some
- hardware-specific configuration. Please also refer to the kernel's help text
- for further information on respective options. I am not a kernel developer
- and nothing here is guaranteed to be functionally accurate. If you feel
- anything mentioned is wrong or should be switched around, please contact me.
- This article assumes some prior knowledge of your system (eg. lspci, lscpu,
- lsusb, dmidecode, <code>/proc/devices</code>, etc.) and general kernel
- configuration/installation, such as obtaining source, generating and
- maintaining <code>.config</code>, methods of configuration, compilation, and
- installation. Throughout, the following acronyms will be used
+ <p>
+ This aims to be a guide for configuring a Linux kernel for a modern x86_64
+ machine containing hardware commonly found in laptops, desktops, and other
+ consumer computers. Note, this guide will sway more minimally, meaning
+ some features that are not strictly required will not be enabled. All
+ features will be built directly into kernel, no modules. This article will
+ not attempt to cover all possible configuration options, as it omits
+ entire sections that are not relevant on such systems, as well as some
+ hardware-specific configuration. Please also refer to the kernel's help
+ text for further information on respective options. I'm not a kernel
+ developer and comments here are not guaranteed to be functionally
+ accurate. If you feel anything mentioned is wrong or should be switched
+ around, reach out. This article assumes some prior knowledge of your
+ system (eg. lspci, lscpu, lsusb, dmidecode, <code>/proc/devices</code>,
+ etc.) and general kernel configuration/installation, such as obtaining
+ sources, generating and maintaining <code>.config</code>, methods of
+ configuration, compilation, and installation. Throughout, the following
+ acronyms will be used:
+ </p>
<ul>
<li>
STD: recommended/standard feature that generally should be enabled
@@ -2409,5 +2400,6 @@
</ul>
</ul>
</div>
+ <script src="frame.js"></script>
</body>
</html>
diff --git a/projects.html b/projects.html
@@ -1,283 +0,0 @@
-<html lang="en">
- <head>
- <title>Personal Projects</title>
- <link rel="stylesheet" href="style.css" />
- <link rel="apple-touch-icon" sizes="180x180" href="data/favicon/apple-touch-icon.png">
- <link rel="icon" type="image/png" sizes="32x32" href="data/favicon/favicon-32x32.png">
- <link rel="icon" type="image/png" sizes="16x16" href="data/favicon/favicon-16x16.png">
- <link rel="manifest" href="data/favicon/site.webmanifest">
- <style>
- code {
- color: #505050;
- font-size: 10px;
- border: 1px solid grey;
- border-radius: 3px;
- padding: 1.75px;
- }
-
- pre {
- background: #f4f4f4;
- color: #505050;
- padding: 20px 0px 0px 20px;
- overflow: auto;
- }
- </style>
- </head>
- <body>
- <a style="text-decoration: none" href="content.html"><--</a>
- <h2>Personal Projects</h2>
- <h3>Synacor Challenge</h3>
- <h5>2024-07-25</h5>
- After participating in
- <a href="https://adventofcode.com" target="_blank">Advent of Code</a> for a
- few years now, I have grown a fan of Eric Wastl's puzzles. This is a
- multi-part challenge that involves implementing a virtual machine to
- interpret and run the supplied binary file. You are also given a document
- outlining the
- <a
- href="https://git.pngu.org/synacor_challenge/tree/arch-spec"
- target="_blank"
- >architecture specification</a
- >
- of the machine that can run the binary file. Once completed and the
- self-tests are passed, you're taken on text-based adventure as the program
- runs, that is very similar to AoC stories. The goal is to find 8 codes while
- completing various puzzles in the program. Before the original
- <a href="https://challenge.synacor.com" target="_blank">site</a> was taken
- down (pretty sure Eric doesn't work at Synacor anymore), you could validate
- the codes found on the site, but since it is no longer up, The codes can be
- manually verified. Thanks to
- <a href="https://github.com/Aneurysm9/vm_challenge" target="_blank"
- >Aneurysm9/vm_challenge</a
- >
- for providing a binary file and matching checksums for the codes. I wrote a
- <a
- href="https://git.pngu.org/synacor_challenge/tree/tools/validate.py"
- target="_blank"
- >small script</a
- >
- to validate them from a text file. I chose to implement my solution in C
- with a simple stack data structure, as that seems most fitting for the task
- at hand. My implementation and related tools can be found
- <a href="https://git.pngu.org/synacor_challenge" target="_blank"
- >here</a
- >
- for those interested. The rest of what's here is likely to be spoilers...
- <h4>Code 1</h4>
- This one is found in plain text in the <code>arch-spec</code> file.
- <pre>
-== hints ==
-- Start with operations 0, 19, and 21.
-- Here's a code for the challenge website: <CODE>
- </pre>
- <h4>Code 2</h4>
- After implementing a basic interpreter that supports the first subset of
- opcodes (<code>out</code>, <code>noop</code>, and <code>halt</code>), this
- one is found in the output.
- <pre>
-Welcome to the Synacor OSCON 2012 Challenge!
-Please record your progress by putting codes like
-this one into the challenge website: <CODE>
- </pre>
- Just for fun, this one can also be spotted early on in the hexdump of the
- binary file:
- <pre>
-00000210 13 00 20 00 13 00 49 00 13 00 6d 00 13 00 6f 00 |.. ...I...m...o.|
-00000220 13 00 46 00 13 00 7a 00 13 00 74 00 13 00 57 00 |..F...z...t...W.|
-00000230 13 00 51 00 13 00 43 00 13 00 76 00 13 00 78 00 |..Q...C...v...x.|
-00000240 13 00 6a 00 13 00 0a 00 13 00 0a 00 13 00 45 00 |..j.............|
- </pre>
- <h4>Code 3</h4>
- To retrieve this code, the interpreter must be fully implemented and must
- pass the initial self-tests. If those conditions are met, the third code is
- printed.
- <pre>
-Executing self-test...
-
-self-test complete, all tests pass
-The self-test completion code is: <CODE>
- </pre>
- <h4>Code 4</h4>
- Now, the adventure aspect of the challenge begins. Pay attention to the
- things of interest, and <code>take</code>/<code>use</code> them as needed,
- like the tablet here.
- <pre>
-What do you do?
-take tablet
-
-Taken.
-
-What do you do?
-use tablet
-
-You find yourself writing <CODE> on the tablet. Perhaps it's some
-kind of code?
- </pre>
- <h4>Code 5</h4>
- This puzzle appears to be a maze after several entries of south, north,
- west, etc. I decided to map my steps with pen and paper. After not too long,
- I arrive at the next code, but not without getting lost and eaten by grues
- numerous times.
- <pre>
-What do you do?
-east
-
-Chiseled on the wall of one of the passageways, you see:
-
- <CODE>
- </pre>
- <h4>Code 6</h4>
- The next puzzle is a maths problem. There will be some coins each with a
- numeric value that you can inspect to see. The coins must be arranged in a
- specific order to satisfy the equation on the wall.
- <pre>
-There is a strange monument in the center of the hall with circular slots and unusual symbols. It reads:
-
-_ + _ * _^2 + _^3 - _ = 399
- </pre>
- <ul>
- <li>Red coin: 2</li>
- <li>Blue coin: 9</li>
- <li>Shiny coin: 5</li>
- <li>Concave coin: 7</li>
- <li>Corroded coin: 3</li>
- </ul>
- This is easy enough to be by hand, but why not make another
- <a
- href="https://git.pngu.org/synacor_challenge/tree/tools/coin.py"
- target="_blank"
- >script</a
- >
- to do it. Looks like <code>9 + 2*5^2 + 7^3 - 3 = 399</code>
- will do it, so arrange the coins in order blue, red, shiny, concave,
- corroded. After completing this, a previously locked door opens and our next
- code is revealed.
- <pre>
-What do you do?
-use teleporter
-
-You activate the teleporter! As you spiral through time and space, you think you see a pattern in the stars...
-
- <CODE>
- </pre>
- <h4>Code 7</h4>
- This is by far the most clever puzzle in this challenge. There's a strange
- book that contains some information about using the teleporter. Some
- provision to log instructions and register values is crucial for this
- puzzle. It appears we must set the 8th register to a certain value. We can
- set the register to a non-zero value to progress in the program, but it will
- not provide the correct code, thus we need to find the correct value. The
- underlying algorithm is a variation of the
- <a href="https://en.wikipedia.org/wiki/Ackermann_function" target="_blank"
- >Ackermann function</a
- >. The modified function can be found in the
- <a
- href="https://git.pngu.org/synacor_challenge/tree/tools/ackermann.c"
- target="_blank"
- >program</a
- >
- used to find the register value. Python proved to be a bit too slow to
- compute this. Once set to the correct value (25734 in my case), the seventh
- code is shown.
- <pre>
-You wake up on a sandy beach with a slight headache. The last thing you remember is activating that teleporter... but now you can't find it anywhere in your pack. Someone seems to have drawn a message in the sand here:
-
- <CODE>
-
-It begins to rain. The message washes away. You take a deep breath and feel firmly grounded in reality as the effects of the teleportation wear off.
- </pre>
- <h4>Code 8</h4>
- This looks to be some sort of arrangement of tiles, each with a number of
- arithmetic operation. By moving from one tile to another, you are
- constructing an expression that must evaluate to the number on the door: 30.
- This is a BFS application to construct the shortest path to the door. I made
- another
- <a
- href="https://git.pngu.org/synacor_challenge/tree/tools/orb_maze.py"
- target="_blank"
- >script</a
- >
- to achieve this. After inputting the appropriate cardinal directions, we see
- the final code in a mirror. Of course, it is entered in reverse.
- <pre>
-You gaze into the mirror, and you see yourself gazing back.
-But wait!
-It looks like someone wrote on your face while you were unconscious on the beach!
-Through the mirror, you see <CODE> scrawled in charcoal on your forehead.
-
-Congratulations; you have reached the end of the challenge!
- </pre>
- <h3>Hardware security key for authentication on Linux</h3>
- <h5>2024-03-01</h5>
- Typing in a rather long password each time I log into my computer
- or need to complete a privileged task can be bothersome. A couple
- years ago I came across <a href="https://github.com/solokeys" target="_blank">solokeys</a>,
- which are fully open source hardware and firmware security keys. I
- chose to build the <a href="https://github.com/solokeys/solo-hw" target="_blank">Solo 1</a>
- (or five because that's the MOQ from most PCB manufacturers). Note,
- at the time of writing this, the <a href="https://github.com/solokeys/solo1-cli" target="_blank">solo1-cli</a>
- tool is currently broken with the latest FIDO2 library, meaning
- it must be installed explicitly at 0.9.3.
- <pre>
-$ pip install solo1
-$ pip install fido2==0.9.3
- </pre>
- After building, I didn't use it much, as many services don't support
- security keys quite yet, or required a paid subscription (I'm looking
- at you, Bitwarden). Come a few months ago, I found <a href="https://github.com/Yubico/pam-u2f" target="_blank">Yubico's PAM for U2F</a>. This is a PAM module to provide authentication from a U2F device.
- To use this, first ensure the <code>CONFIG_HIDRAW</code> and
- <code>CONFIG_USB_HIDDEV</code> options are set in your kernel.
- Next, obtain the module via package manager or compiling from source
- and generate the authorisation mapping with your key inserted. The
- created directory must be named <code>Yubico</code>, even if not
- using a Yubico key. It can be overridden in <a href="https://github.com/Yubico/pam-u2f/blob/main/util.h#L14" target="_blank">util.h</a>
- if you so choose.
- <pre>
-$ mkdir ~/.config/Yubico
-$ pamu2fcfg > ~/.config/Yubico/u2f_keys
-Enter PIN for /dev/hidraw2:
- </pre>
- Assuming all has been successful, you can configure PAM services
- to use the device. The following configures doas to utilise the
- U2F module in the <code>/etc/pam.d/doas</code> file. The same line
- can be added in other files where needed (eg. display manager,
- <code>system-local-login</code>, etc.)
- <pre>
-auth sufficient pam_u2f.so cue pinverification=0
-auth include system-auth
-...
- </pre>
- Above, <b>sufficient</b> indicates that authentication from the device
- alone is enough to fully authenticate. Use <b>required</b> instead
- if you want both password and device authentication to be required.
- <b>cue</b> simply displays a prompt to press the button on the device
- when needed to authenticate. <b>pinverification=0</b> disables the need
- to entre the passphrase associated with your security key. Note, this
- means your system can be accessed only with your key, and no password entry
- of any type. Set the parameter to 1 if you'd like otherwise. Another
- thing of interest was locking/unlocking my system automatically when
- the key is removed/inserted, respectively. This can be achieved via
- a custom udev rule that executes a script when a device matching
- our key's VID/PID is plugged in. This script will use <a href="https://pamtester.sourceforge.net" target="_blank">pamtester</a>
- to test for authentication success.
- <pre>
-#!/bin/bash
-if [ "$1" == "lock" ]; then
- # lock system
-else
- if [ echo "" | pamtester login <user> authenticate ]; then
- # kill lock program
- fi
-fi
-exit 0
- </pre>
- Now, a custom udev rule that lives in <code>/etc/udev/rules.d/70-solokey.rules</code>
- and looks for a matching VID/PID and executes this script when
- found with the appropriate argument.
- <pre>
-ACTION::"remove", ENV{DEVTYPE}::"usb_device", ENV{PRODUCT}::"0483/a2Ca", RUN+:"/usr/local/sbin/keyauth.sh lock"
-ACTION::"add", ENV{DEVTYPE}::"usb_device", ENV{ID_BUS}::"usb", ENV{PRODUCT}::"0483/a2Ca", RUN+:"/usr/local/sbin/keyauth.sh unlock"
- </pre>
-
- </body>
-</html>
diff --git a/ssh_agent.html b/ssh_agent.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <title>SSH Agent in Background</title>
+ <script src="header.js"></script>
+ </head>
+ <body>
+ <a style="text-decoration: none" href="content.html"><--</a>
+ <h2>SSH agent for password-less login</h2>
+ <p><i>2021-01-17</i></p>
+ <hr />
+ <p>
+ I have numerous machines I frequently log in to and from via SSH. Typing
+ in a password every time is tiresome and a password-less key is not an
+ option. A solution is an SSH agent running in the background, which
+ prompts for a password once at log in, and stores it for the duration of
+ the session (until reboot). The following can live in your shell's startup
+ file (e.g.
+ <code>~/.zshrc</code>).
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block language-shell">
+ if [ ! -S $HOME/.ssh/ssh_auth_sock ]; then
+ eval "$(ssh-agent)"
+ ln -sf "$SSH_AUTH_SOCK" $HOME/.ssh/ssh_auth_sock
+ fi
+
+ export SSH_AUTH_SOCK=$HOME/.ssh/ssh_auth_sock
+ ssh-add -l > /dev/null || ssh-add
+ </div>
+ <p>
+ Then, just copy the needed key between machines with
+ <code>ssh-copy-id -i ~/.ssh/id_xxx.pub name@host</code>.
+ </p>
+ <p>
+ MacOS however, has its own provision for this. The following can simply be
+ added to your <code>~/.ssh/config</code> file:
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block">
+ Host *
+ UseKeychain yes
+ AddKeysToAgent yes
+ IdentityFile ~/.ssh/id_ed25519
+ </div>
+ <script src="frame.js"></script>
+ </body>
+</html>
diff --git a/style.css b/style.css
@@ -3,12 +3,14 @@
body {
max-width: 65%;
margin: auto;
- line-height: 1.0;
+ line-height: 1;
padding: 15px 0px;
font-size: 12pt;
}
-.header { line-height: 1.5; }
+.header {
+ line-height: 1.5;
+}
.email {
font-size: 25%;
@@ -19,14 +21,23 @@ body {
vertical-align: middle;
}
-.code {
+code {
+ font-family: "JetBrains Mono", monospace;
font-size: smaller;
- background-color: grey;
+ border: 0.5px solid grey;
+ border-radius: 3px;
+ color: darkgrey;
+}
+
+.code-block {
font-family: "JetBrains Mono", monospace;
+ font-size: smaller;
white-space: pre;
width: inherit;
overflow-x: auto;
overflow-y: hidden;
line-height: 1;
display: block;
+ padding-top: 10px;
+ padding-bottom: 10px;
}
diff --git a/synacor.html b/synacor.html
@@ -0,0 +1,225 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <title>Synacor Challenge</title>
+ <script src="header.js"></script>
+ </head>
+ <body>
+ <a style="text-decoration: none" href="content.html"><--</a>
+ <h2>Synacor Challenge</h2>
+ <p><i>2024-07-25</i></p>
+ <hr />
+ <p>
+ After participating in
+ <a href="https://adventofcode.com" target="_blank">Advent of Code</a> for
+ a few years now, I have grown a fan of Eric Wastl's puzzles. This is a
+ multi-part challenge that involves implementing a virtual machine to
+ interpret and run the supplied binary file. You are also given a document
+ outlining the
+ <a
+ href="https://git.pngu.org/synacor_challenge/tree/arch-spec"
+ target="_blank"
+ >architecture specification</a
+ >
+ of the machine that can run the binary file. Once completed and the basic
+ functionality tests are passed, you're taken through a text-based game as
+ the program runs, that is very similar to AoC stories. The goal is to find
+ 8 codes while completing various puzzles in the program. Before the
+ original
+ <a href="https://challenge.synacor.com" target="_blank">site</a> was taken
+ down, it could be used to validate the codes you found, but since it is no
+ longer up, The codes can be manually verified. Thanks to
+ <a href="https://github.com/Aneurysm9/vm_challenge" target="_blank"
+ >Aneurysm9/vm_challenge</a
+ >
+ for providing a binary file and matching checksums for the codes. I wrote
+ a
+ <a
+ href="https://git.pngu.org/synacor_challenge/tree/tools/validate.py"
+ target="_blank"
+ >small script</a
+ >
+ to validate them from a text file. I chose to implement my solution in C
+ with a simple stack data structure, as that seems most fitting for this
+ project. My implementation and related tools can be found
+ <a href="https://git.pngu.org/synacor_challenge" target="_blank">here</a>.
+ The rest of what's on this page is likely to be spoilers of the challenge.
+ </p>
+ <h4>Code 1</h4>
+ <p>This one is found in plain text in the <code>arch-spec</code> file.</p>
+ <!-- prettier-ignore -->
+ <div class="code-block">
+ == hints ==
+ - Start with operations 0, 19, and 21.
+ - Here's a code for the challenge website: <CODE>
+ </div>
+ <h4>Code 2</h4>
+ <p>
+ After implementing a basic interpreter that supports the first subset of
+ opcodes (<code>out</code>, <code>noop</code>, and <code>halt</code>), this
+ one is found in the output of program itself.
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block">
+ Welcome to the Synacor OSCON 2012 Challenge!
+ Please record your progress by putting codes like
+ this one into the challenge website: <CODE>
+ </div>
+ <p>
+ Just for fun, this one can also be spotted early on in the hexdump of the
+ binary file:
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block">
+ 00000210 13 00 20 00 13 00 49 00 13 00 6d 00 13 00 6f 00 |.. ...I...m...o.|
+ 00000220 13 00 46 00 13 00 7a 00 13 00 74 00 13 00 57 00 |..F...z...t...W.|
+ 00000230 13 00 51 00 13 00 43 00 13 00 76 00 13 00 78 00 |..Q...C...v...x.|
+ 00000240 13 00 6a 00 13 00 0a 00 13 00 0a 00 13 00 45 00 |..j.............|
+ </div>
+ <h4>Code 3</h4>
+ <p>
+ To retrieve this code, the interpreter must be fully implemented and must
+ pass the initial self-tests. If those conditions are met, the third code
+ is printed.
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block">
+ Executing self-test...
+
+ self-test complete, all tests pass
+ The self-test completion code is: <CODE>
+ </div>
+ <h4>Code 4</h4>
+ <p>
+ Now, the adventure aspect of the challenge begins. Pay attention to the
+ things of interest, and <code>take</code>/<code>use</code> them as needed,
+ like the tablet here.
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block">
+ What do you do?
+ take tablet
+
+ Taken.
+
+ What do you do?
+ use tablet
+
+ You find yourself writing <CODE> on the tablet. Perhaps it's some
+ kind of code?
+ </div>
+ <h4>Code 5</h4>
+ <p>
+ This appears to be a maze puzzle after several entries of some cardinal
+ directions. I mapped my steps with pen and paper and after not too long, I
+ arrive at the next code, but not without getting lost and eaten by
+ <a href="https://zork.fandom.com/wiki/Grue" target="_blank">Grue's</a>
+ numerous times.
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block">
+ What do you do?
+ east
+
+ Chiseled on the wall of one of the passageways, you see:
+
+ <CODE>
+ </div>
+ <h4>Code 6</h4>
+ <p>
+ The next puzzle is a maths problem. There will be some coins each with a
+ numeric value that you can inspect to see. The coins must be arranged in a
+ specific order to satisfy the equation on the wall.
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block">
+ There is a strange monument in the center of the hall with circular slots and unusual symbols. It reads:
+
+ _ + _ * _^2 + _^3 - _ = 399
+ </div>
+ <ul>
+ <li>Red coin: 2</li>
+ <li>Blue coin: 9</li>
+ <li>Shiny coin: 5</li>
+ <li>Concave coin: 7</li>
+ <li>Corroded coin: 3</li>
+ </ul>
+ <p>
+ This is easy enough to be by hand, but why not make another
+ <a
+ href="https://git.pngu.org/synacor_challenge/tree/tools/coin.py"
+ target="_blank"
+ >script</a
+ >
+ to do it. Looks like <code>9 + 2*5^2 + 7^3 - 3 = 399</code> will do, so
+ arrange the coins in order blue, red, shiny, concave, corroded. After
+ completing this, a previously locked door opens and our next code is
+ revealed.
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block">
+ What do you do?
+ use teleporter
+
+ You activate the teleporter! As you spiral through time and space, you think you see a pattern in the stars...
+
+ <CODE>
+ </div>
+ <h4>Code 7</h4>
+ <p>
+ This is by far the most clever puzzle in this challenge. There's a strange
+ book that contains some information about using the teleporter. Some way
+ of logging instructions and register values is crucial for this puzzle. It
+ appears we must set the 8th register to a certain value. We can set the
+ register to a non-zero value to progress in the program, but it will not
+ provide the correct code, thus we need to find the correct value. The
+ underlying algorithm is a variation of the
+ <a href="https://en.wikipedia.org/wiki/Ackermann_function" target="_blank"
+ >Ackermann function</a
+ >. The modified function can be found in the
+ <a
+ href="https://git.pngu.org/synacor_challenge/tree/tools/ackermann.c"
+ target="_blank"
+ >program</a
+ >
+ used to find the register value. Python proved to be a too slow to compute
+ this. Once set to the correct value (25734 in my case), the seventh code
+ is shown.
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block">
+ You wake up on a sandy beach with a slight headache. The last thing you remember is activating that teleporter... but now you can't find it anywhere in your pack. Someone seems to have drawn a message in the sand here:
+
+ <CODE>
+
+ It begins to rain. The message washes away. You take a deep breath and feel firmly grounded in reality as the effects of the teleportation wear off.
+ </div>
+ <h4>Code 8</h4>
+ <p>
+ This puzzle looks to be some sort of arrangement of tiles, each with a
+ number of arithmetic operation. By moving from one tile to another, you
+ are constructing an expression that must evaluate to the number on the
+ door: 30. This is a BFS application to construct the shortest path to the
+ door. I made another
+ <a
+ href="https://git.pngu.org/synacor_challenge/tree/tools/orb_maze.py"
+ target="_blank"
+ >script</a
+ >
+ to achieve this. After inputting the appropriate cardinal directions, we
+ see the final code in a mirror. Of course, it is entered in reverse.
+ </p>
+ <!-- prettier-ignore -->
+ <div class="code-block">
+ You gaze into the mirror, and you see yourself gazing back.
+ But wait!
+ It looks like someone wrote on your face while you were unconscious on the beach!
+ Through the mirror, you see <CODE> scrawled in charcoal on your forehead.
+
+ Congratulations; you have reached the end of the challenge!
+ </div>
+ <script src="frame.js"></script>
+ </body>
+</html>
diff --git a/template.html b/template.html
@@ -7,12 +7,13 @@
<script src="header.js"></script>
</head>
<body>
- <a style="text-decoration: none" href="index.html"><--</a>
+ <a style="text-decoration: none" href="content.html"><--</a>
<h2>Page Header</h2>
<p><i>2026-01-14</i></p>
- Some text on a web page.
+ <hr />
+ <p>Some text on a web page.</p>
<!-- prettier-ignore -->
- <div class="code language-c">
+ <div class="code-block language-c">
int function(int x) {
return x * x;
}
diff --git a/wpa_supplicant.html b/wpa_supplicant.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <title>WPA Supplicant Usage</title>
+ <script src="header.js"></script>
+ </head>
+ <body>
+ <a style="text-decoration: none" href="content.html"><--</a>
+ <h2>WPA Supplicant Usage</h2>
+ <p><i>2022-11-26</i></p>
+ <hr />
+ <p>Frequently forgotten usage of the <code>wpa_cli</code> tool.</p>
+ <!-- prettier-ignore -->
+ <div class="code-block language-shell">
+ $ wpa_cli
+ > scan
+ ...
+ <3>CTRL-EVENT-SCAN-RESULTS # wait for this to appear
+ > scan_results
+ bssid / freq / sig lvl / flags / ssid
+ ...
+ > add_network
+ 5
+ > set_network 5 ssid "network"
+ > set_network 5 psk "psswd"
+ # or if no password:
+ > set_network 5 key_mgmt NONE
+ > enable_network 5
+ > save_config
+ </div>
+ <p>
+ However, one should strongly consider moving
+ <a
+ href="https://archive.kernel.org/oldwiki/iwd.wiki.kernel.org"
+ target="_blank"
+ >iwd</a
+ >...
+ </p>
+ <script src="frame.js"></script>
+ </body>
+</html>