site

Website Content
git clone https://git.pngu.org/site
Log | Files | Refs | README

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:
Acontent.html | 42++++++++++++++++++++++++++++++++++++++++++
Dextra.html | 110-------------------------------------------------------------------------------
Agpg_key_git.html | 46++++++++++++++++++++++++++++++++++++++++++++++
Ahardware_key.html | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mindex.html | 70+++++++++++++++++++++++-----------------------------------------------
Mkernel.html | 58+++++++++++++++++++++++++---------------------------------
Dprojects.html | 283-------------------------------------------------------------------------------
Assh_agent.html | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Mstyle.css | 19+++++++++++++++----
Asynacor.html | 225+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtemplate.html | 7++++---
Awpa_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">&lt;--</a> + <h3>Content &amp; Postings</h3> + <h4>Computers</h4> + <ul> + <li>Gentoo Desktop</li> + <li>Artix Laptop</li> + <li>macOS Laptop</li> + <li>Programs &amp; 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 &ltFoo_Bar@baz&gt": No secret key[GNUPG:] INV_SGNR 9 Foo Bar &ltFoo_Bar@baz&gt[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 &ltFoo_Bar@baz&gt</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">&lt;--</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 &ltFooBar@baz&gt": No secret key[GNUPG:] INV_SGNR 9 FooBar &ltFooBar@baz&gt[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 &ltFoo_Bar@baz&gt</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">&lt;--</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 &gt;user&lt; 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 &amp; 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 &amp; 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">&lt;--</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: &ltCODE&gt - </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: &ltCODE&gt - </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: &ltCODE&gt - </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 &ltCODE&gt 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: - - &ltCODE&gt - </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... - - &ltCODE&gt - </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: - - &ltCODE&gt - -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 &ltCODE&gt 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">&lt;--</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">&lt;--</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: &ltCODE&gt + </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: &ltCODE&gt + </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: &ltCODE&gt + </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 &ltCODE&gt 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: + + &ltCODE&gt + </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... + + &ltCODE&gt + </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: + + &ltCODE&gt + + 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 &ltCODE&gt 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">&lt;--</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">&lt;--</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 + &gt; scan + ... + &lt;3&gt;CTRL-EVENT-SCAN-RESULTS # wait for this to appear + &gt; scan_results + bssid / freq / sig lvl / flags / ssid + ... + &gt; add_network + 5 + &gt; set_network 5 ssid "network" + &gt; set_network 5 psk "psswd" + # or if no password: + &gt; set_network 5 key_mgmt NONE + &gt; enable_network 5 + &gt; 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>