Sorry

This feed does not validate.

In addition, interoperability with the widest range of feed readers could be improved by implementing the following recommendations.

Source: https://www.maths.tcd.ie/%7Efionn/misc/feed.atom

  1. <?xml version='1.0' encoding='UTF-8'?>
  2. <feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  3.  <id>https://www.maths.tcd.ie/~fionn/misc/feed.atom</id>
  4.  <title>misc</title>
  5.  <updated>2024-08-23T16:13:11.630615+00:00</updated>
  6.  <author>
  7.    <name>Fionn Fitzmaurice</name>
  8.    <email>fionn@this.domain</email>
  9.  </author>
  10.  <link href="https://www.maths.tcd.ie/~fionn/misc/feed.xml" rel="self"/>
  11.  <link href="https://www.maths.tcd.ie/~fionn/misc/" rel="alternate"/>
  12.  <contributor>
  13.    <name>Fionn Fitzmaurice</name>
  14.    <email>fionn@this.domain</email>
  15.  </contributor>
  16.  <generator version="0.1">fionn-feed</generator>
  17.  <icon>https://www.maths.tcd.ie/favicon.ico</icon>
  18.  <logo>https://www.maths.tcd.ie/~fionn/me.jpg</logo>
  19.  <subtitle>Fionn has no mouth but he must scream</subtitle>
  20.  <entry>
  21.    <id>https://www.maths.tcd.ie/~fionn/misc/fido_ssh/</id>
  22.    <title>Biometric FIDO2/U2F SSH Keys</title>
  23.    <updated>2022-09-21T00:00:00+00:00</updated>
  24.    <author>
  25.      <name>Fionn Fitzmaurice</name>
  26.      <email>fionn@this.domain</email>
  27.    </author>
  28.    <content type="CDATA"><![CDATA[<p>
  29.      Smartcards have traditionally supported SSH public key authentication using two
  30.      methods: PIV and PGP.
  31.      </p>
  32.      <p>
  33.      In PIV mode, you end up hacking around with <code>opensc</code> to get
  34.      <code>ssh-agent</code> to use the certificate as a key.
  35.      This also doesn’t play well with <code>gpg-agent</code>, which tends to acquire
  36.      a lock on the smartcard.
  37.      </p>
  38.      <p>
  39.      In PGP mode, you have to ditch <code>ssh-agent</code> and use
  40.      <code>gpg-agent</code> instead, which is a significantly degraded experience.
  41.      </p>
  42.      <h3 id="openssh"><a class="anchor" href="#openssh"></a>OpenSSH</h3>
  43.      <p>
  44.      As of <a href="https://www.agwa.name/blog/post/ssh_signatures">OpenSSH version
  45.      8.0</a> you can use SSH keys to sign arbitrary data.
  46.      </p>
  47.      <p>
  48.      As of <a href="https://www.openssh.com/txt/release-8.2">OpenSSH version 8.2</a>
  49.      you can use SSH keys derived from the FIDO2 application on smartcards, using
  50.      either Ed25519 or ECDSA.
  51.      </p>
  52.      <h3 id="yubikeys"><a class="anchor" href="#yubikeys"></a>YubiKeys</h3>
  53.      <p>
  54.      Yubico manufacture a few different smartcards (YubiKeys, from here on out). The
  55.      <a href="https://www.yubico.com/products/yubikey-5-overview/">YubiKey 5
  56.      series</a> support all of the above modes, whereas the <a
  57.      href="https://www.yubico.com/products/security-key/">YubiKey Security Key</a>
  58.      only supports FIDO2 (since it’s designed just for 2FA on websites and so on).
  59.      The Security Key is also significantly cheaper.
  60.      </p>
  61.      <p>
  62.      There’s also the <a
  63.      href="https://www.yubico.com/products/yubikey-bio-series/">YubiKey Bio</a>,
  64.      which has the same support as the Security Key, but has a fingerprint reader and
  65.      comes in at a little over 3 times the price.
  66.      </p>
  67.      <p>
  68.      I held off on buying the Bio because I store my PGP key on my YubiKey and wanted
  69.      to retain this functionality. But I finally decided to try it out, for several
  70.      reasons:
  71.      </p>
  72.      <ul>
  73.      <li>I can use it for SSH,</li>
  74.      <li>I can use that SSH key for signing files and <a
  75.      href="https://calebhearth.com/sign-git-with-ssh">Git commits</a>,</li>
  76.      <li>I can secure the SSH key with a passphrase and a fingerprint,</li>
  77.      <li>I expensed it to my employer,</li>
  78.      <li>nobody sends me <a href="/~fionn/contact/#email">PGP-encrypted emails</a>
  79.      any more anyway 🙁.</li>
  80.      </ul>
  81.      <h2 id="fingerprint"><a class="anchor" href="#fingerprint"></a>Adding a
  82.      Fingerprint</h2>
  83.      <p>
  84.      Out of the box, when I plugged it in it was flashing orange. I don’t know why.
  85.      </p>
  86.      <pre class="shell">
  87. ykman info
  88. Device type: YubiKey C Bio - FIDO Edition
  89. Serial number: 17244581
  90. Firmware version: 5.5.6
  91. Form factor: Bio (USB-C)
  92. Enabled USB interfaces: FIDO
  93.  
  94. Applications
  95. FIDO2       Enabled
  96. OTP         Not available
  97. FIDO U2F     Enabled
  98. OATH         Not available
  99. YubiHSM Auth Not available
  100. OpenPGP     Not available
  101. PIV         Not available
  102. </pre>
  103.      <p>
  104.      To add a fingerprint, we first have to set a PIN.
  105.      The PIN can be alphanumeric (extended ASCII) and relatively long (63
  106.      characters).
  107.      </p>
  108.      <pre class="shell">
  109. ykman fido access change-pin
  110. Enter your new PIN:
  111. Repeat for confirmation:
  112. </pre>
  113.      <p>
  114.      Then add a fingerprint.
  115.      </p>
  116.      <pre class="shell">
  117. ykman fido fingerprints add "right-index"
  118. Enter your PIN:
  119. Place your finger against the sensor now...
  120. 4 more scans needed.
  121. Place your finger against the sensor now...
  122. 3 more scans needed.
  123. Place your finger against the sensor now...
  124. 2 more scans needed.
  125. Place your finger against the sensor now...
  126. 1 more scans needed.
  127. Place your finger against the sensor now...
  128. Capture complete.
  129. </pre>
  130.      <p>
  131.      We can then list the fingerprints.
  132.      </p>
  133.      <pre class="shell">
  134. ykman fido fingerprints list
  135. Enter your PIN:
  136. ID: c83b (right-index)
  137. </pre>
  138.      <p>
  139.      I remain optimistic that revealing which finger I’ve enrolled doesn’t put me at
  140.      significantly greater risk of losing it. If your threat model includes this,
  141.      rest easy knowing that the list is protected by the PIN.
  142.      </p>
  143.      <h2 id="key-generation"><a class="anchor" href="#key-generation"></a>Generating
  144.      a Resident Ed25519 SSH Key</h2>
  145.      <p>
  146.      There are <a
  147.      href="https://developers.yubico.com/SSH/Securing_SSH_with_FIDO2.html#_discoverable_vs_non_discoverable_credentials">two
  148.      types</a> of FIDO2 SSH keys: resident and non-resident.
  149.      </p>
  150.      <p>
  151.      I’m using a resident key because the PIN/fingerprint access control is good
  152.      enough for me and I value the ability to move the YubiKey between different
  153.      devices.
  154.      </p>
  155.      <p>
  156.      We generate the key with <code>ssh-keygen -t ed25519-sk</code>. This will fail
  157.      if your YubiKey’s firmware is <a
  158.      href="https://www.yubico.com/blog/whats-new-in-yubikey-firmware-5-2-3/">older
  159.      than 5.2.3</a>, before they supported Ed25519 curves.
  160.      If so, you can fall back to <code>ecdsa-sk</code>, or get a new YubiKey (<a
  161.      href="https://safecurves.cr.yp.to/">recommended</a>).
  162.      </p>
  163.      <p>
  164.      The below command makes a key that requires not just user presence (a touch) but
  165.      also verification. This means a PIN for normal non-biometric YubiKeys but,
  166.      despite the <a
  167.      href="https://man.archlinux.org/man/ssh-keygen.1#verify-required"><code>ssh-keygen</code>
  168.      documentation</a> insisting otherwise, the Bio will accept a fingerprint to
  169.      unlock the key.
  170.      </p>
  171.      <blockquote cite="https://man.archlinux.org/man/ssh-keygen.1#verify-required">
  172.      <strong><code>verify-required</code></strong>
  173.      <br/>
  174.          Require signatures made using this key indicate that the user was first
  175.      verified.
  176.          This option only makes sense for the FIDO authenticator algorithms
  177.      <code>ecdsa-sk</code> and <code>ed25519-sk</code>.
  178.          Currently PIN authentication is the only supported verification method, but
  179.      other methods may be supported in the future.
  180.      </blockquote>
  181.      <p>
  182.      I also increase the key derivation rounds and add a comment.
  183.      </p>
  184.      <pre class="shell">
  185. ssh-keygen -t ed25519-sk -O resident -O verify-required -a 128 -C 17244581
  186. Generating public/private ed25519-sk key pair.
  187. You may need to touch your authenticator to authorize key generation.
  188. Enter PIN for authenticator:
  189. Enter file in which to save the key (/home/fionn/.ssh/id_ed25519_sk):
  190. Enter passphrase (empty for no passphrase):
  191. Enter same passphrase again:
  192. Your identification has been saved in /home/fionn/.ssh/id_ed25519_sk
  193. Your public key has been saved in /home/fionn/.ssh/id_ed25519_sk.pub
  194. The key fingerprint is:
  195. SHA256:2fl1x8+ACfUB2UA3eV5mXLJY5Wr04K93N7nH6iN4OoY 17244581
  196. The key's randomart image is:
  197. +[ED25519-SK 256]-+
  198. |           .==*++|
  199. |           ..=o**|
  200. |          . . ==o|
  201. |         o o = =.|
  202. |        S o o * =|
  203. |           . o =o|
  204. |         . ..  .=|
  205. |        E + o .+*|
  206. |         ..+ o+=*|
  207. +----[SHA256]-----+
  208. </pre>
  209.      <h2 id="connecting"><a class="anchor" href="#connecting"></a>Using the FIDO2 SSH
  210.      Key</h2>
  211.      <p>
  212.      Now test it out. I usually use GitHub for this. Upload
  213.      <code>~/.ssh/id_ed25519_sk.pub</code>, add
  214.      </p>
  215.      <p>
  216.      </p>
  217.      <pre>
  218. Host github.com
  219.    User git
  220.    PubkeyAuthentication yes
  221.    IdentityFile ~/.ssh/id_ed25519_sk
  222. </pre>
  223.      <p>
  224.      to <code>~/.ssh/config</code> and try to connect.
  225.      </p>
  226.      <pre class="shell">
  227. ssh -T github.com
  228. Enter passphrase for key '/home/fionn/.ssh/id_ed25519_sk':
  229. Confirm user presence for key ED25519-SK SHA256:2fl1x8+ACfUB2UA3eV5mXLJY5Wr04K93N7nH6iN4OoY
  230. User presence confirmed
  231. Hi <a href="https://github.com/fionn" rel="me">fionn</a>! You've successfully authenticated, but GitHub does not provide shell access.
  232. </pre>
  233.      <p>
  234.      Then try to connect again and notice that <code>ssh-agent</code> has cached the
  235.      passphrase.
  236.      </p>
  237.      <p>
  238.      To use it on another machine, plug it into the new machine and run
  239.      </p>
  240.      <pre class="shell">
  241. ssh-keygen -K
  242. Enter PIN for authenticator:
  243. You may need to touch your authenticator to authorize key download.
  244. Enter passphrase (empty for no passphrase):
  245. Enter same passphrase again:
  246. Saved ED25519-SK key to id_ed25519_sk_rk
  247. </pre>
  248.      <p>
  249.      to download the key handles to the working directory. Move them to
  250.      <code>~/.ssh/</code> and connect like usual.
  251.      </p>
  252.      ]]></content>
  253.    <link href="https://www.maths.tcd.ie/~fionn/misc/fido_ssh/"/>
  254.    <summary>Smartcards have traditionally supported SSH public key authentication using two methods: PIV and PGP. […]</summary>
  255.    <published>2022-09-21T00:00:00+00:00</published>
  256.  </entry>
  257.  <entry>
  258.    <id>https://www.maths.tcd.ie/~fionn/misc/feed/</id>
  259.    <title>RSS and Atom Feeds</title>
  260.    <updated>2018-09-18T00:00:00+00:00</updated>
  261.    <author>
  262.      <name>Fionn Fitzmaurice</name>
  263.      <email>fionn@this.domain</email>
  264.    </author>
  265.    <content type="CDATA"><![CDATA[<p>
  266.                  I read <a
  267.      href="https://twobithistory.org/2018/09/16/the-rise-and-demise-of-rss.html">The
  268.      Rise and Demise of RSS</a> and was motivated to syndicate this <a
  269.      href="../">list of things I write here</a>.
  270.                  </p>
  271.      <p>
  272.                  One of the challenges is that typically people use some sort of
  273.      publishing platform which generates RSS feeds for you. Since this site is
  274.      entirely static (well, aside from some PHP to keep things tidy on the server
  275.      side), I have to generate the feed myself. Since it’s just XML, I could in
  276.      principle do it by hand. However, the pain-point that that would introduce every
  277.      time I (occasionally) add to this list would almost guarantee that I wouldn’t
  278.      update it.
  279.                  </p>
  280.      <p>
  281.                  To solve this, I wrote a pretty basic script that scrapes this page,
  282.      grabs all the articles and figures out how to turn them into feed entries. Then
  283.      it generates a feed with all the relevant metadata and adds each one. The
  284.      process is still manual, but reduced to a “one-click” deployment.
  285.                  </p>
  286.      <p>
  287.                  The code is <a href="https://github.com/fionn/feed">here</a>. This
  288.      page is publishing syndicated feeds; you should be able to see it if your
  289.      browser knows what to do with them. (Firefox looks to be deprecating its live
  290.      bookmarks functionality. Get <a
  291.      href="https://addons.mozilla.org/en-US/firefox/addon/awesome-rss/">Awesome
  292.      RSS</a> to add the RSS feed back in the address bar.)
  293.                  </p>
  294.      <p>
  295.                  Subscribe via <a href="../feed.xml">RSS</a> or <a
  296.      href="../feed.atom">Atom</a>. Or don’t. But do subscribe to other things. It’s
  297.      such a shame that this technology is going out of favour, but also no accident.
  298.      We have to fight for the internet we want.
  299.                  </p>
  300.      <p>
  301.                  (<em>Syndication feeds validate for <del>both</del> <a
  302.      href="https://www.feedvalidator.org/check.cgi?url=https%3A%2F%2Fwww.maths.tcd.ie%2F%257Efionn%2Fmisc%2Ffeed.xml">RSS</a>
  303.      <del>and <a
  304.      href="https://www.feedvalidator.org/check.cgi?url=https%3A%2F%2Fwww.maths.tcd.ie%2F%257Efionn%2Fmisc%2Ffeed.atom">Atom</a></del>.</em>)
  305.                  </p>
  306.      ]]></content>
  307.    <link href="https://www.maths.tcd.ie/~fionn/misc/feed/"/>
  308.    <summary>I think decentralised syndication is a good thing so I made RSS and Atom feeds for this pseudo-blog</summary>
  309.    <published>2018-09-18T00:00:00+00:00</published>
  310.  </entry>
  311.  <entry>
  312.    <id>https://www.maths.tcd.ie/~fionn/misc/encrypt_volume/</id>
  313.    <title>Encrypting a Volume</title>
  314.    <updated>2018-05-24T00:00:00+00:00</updated>
  315.    <author>
  316.      <name>Fionn Fitzmaurice</name>
  317.      <email>fionn@this.domain</email>
  318.    </author>
  319.    <content type="CDATA"><![CDATA[<p>
  320.      It’s really easy. Let’s assume <code>sdc</code> is the drive (because it is for
  321.      me). Open up <code>gdisk</code>, make a new GPT and fill the disk with a
  322.      partition of type <code>FD00</code> (this is Linux RAID, which allegedly is
  323.      conventional).
  324.      </p>
  325.      <pre>
  326. Number  Start (sector)    End (sector)  Size       Code  Name
  327.   1            2048       124735454   59.5 GiB    FD00  Linux RAID
  328. </pre>
  329.      <p>
  330.      You can also rename the partition to LUKS or something.
  331.      </p>
  332.      <p>
  333.      <code>cryptsetup</code> <em>should</em> be compiled with sane defaults (you can
  334.      check with <code>--help</code>), so encryption is done with
  335.      </p>
  336.      <pre class="root-shell">
  337. cryptsetup -v --verify-passphrase luksFormat /dev/sdc1
  338. </pre>
  339.      <p>
  340.      (which can be elaborated on if the compiled defaults are not to your liking).
  341.      </p>
  342.      <p>
  343.      Open the LUKS container with
  344.      </p>
  345.      <pre class="root-shell">
  346. cryptsetup open /dev/sdc1 <em>luks_volume</em>
  347. </pre>
  348.      <p>
  349.      (where <code><em>luks_volume</em></code> is the unimaginative name of the
  350.      container).
  351.      </p>
  352.      <pre>
  353. sdc                  8:32   1  59.5G  0 disk
  354. └─sdc1               8:33   1  59.5G  0 part
  355.  └─<em>luks_volume</em>     254:2   0  59.5G  0 crypt
  356. </pre>
  357.      <p>
  358.      This creates a handle in <code>/dev/mapper/<em>luks_volume</em></code>. It’s not
  359.      a filesystem yet, though.
  360.      </p>
  361.      <p>
  362.      </p>
  363.      <pre class="root-shell">
  364. mkfs.ext4 /dev/mapper/<em>luks_volume</em>
  365. </pre>
  366.      <p>
  367.      Now we can mount it! See <a href="../mount_encrypted_volume/"><em>Mounting an
  368.      encrypted LUKS volume</em></a> for how to do that.
  369.      </p>
  370.      ]]></content>
  371.    <link href="https://www.maths.tcd.ie/~fionn/misc/encrypt_volume/"/>
  372.    <summary>It’s really easy. Let’s assume sdc is the drive (because it is for me). Open up gdisk, make a new GPT and fill the disk with a partition of type FD00 (this is Linux RAID, which allegedly is conventional). […]</summary>
  373.    <published>2018-05-24T00:00:00+00:00</published>
  374.  </entry>
  375.  <entry>
  376.    <id>https://www.maths.tcd.ie/~fionn/misc/wg/</id>
  377.    <title>WireGuard</title>
  378.    <updated>2017-12-07T00:00:00+00:00</updated>
  379.    <author>
  380.      <name>Fionn Fitzmaurice</name>
  381.      <email>fionn@this.domain</email>
  382.    </author>
  383.    <content type="CDATA"><![CDATA[<p>
  384.      This is the future of VPNs, etc. Read about it <a
  385.      href="https://www.wireguard.com/">here</a>. It really is amazing. There’s also
  386.      manual configuration steps there, which you should do first.
  387.      </p>
  388.      <p>
  389.      It’s super easy to set up configurations for use with <code>wg-quick</code>.
  390.      Here’s a simple server + client configuration for tunnelling all traffic
  391.      throught the VPN.
  392.      </p>
  393.      <p>
  394.      Note that “server” and “client” are artificial terms here; really both machines
  395.      are peers, we’re imposing the server + client relationship on them to align with
  396.      traditional VPNs.
  397.      </p>
  398.      <p>
  399.      Generate private keys with <code>umask 077 &amp;&amp; wg genkey &gt;
  400.      private.key</code>. Corresponding public keys are derived from private ones with
  401.      <code>wg pubkey &lt; private.key &gt; public.key</code>. The preshared key is
  402.      used for post-quantum resilience, generated with <code>wg genpsk &gt;
  403.      preshared.key</code>.
  404.      </p>
  405.      <pre><code class="ini">
  406. # server wg0.conf
  407. [Interface]
  408. PrivateKey = [server private key]
  409. Address = 10.10.0.1/24, fd80::1/64
  410. ListenPort = 2307
  411. SaveConfig = true
  412. PostUp = iptables -A FORWARD -i wg0 -j ACCEPT &amp;&amp; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
  413. PostDown = iptables -D FORWARD -i wg0 -j ACCEPT &amp;&amp; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
  414.  
  415. [Peer]
  416. PublicKey = [client public key]
  417. PresharedKey = [preshared.key]
  418. AllowedIPs = 10.10.0.2/32, fd80::2/128
  419. </code></pre>
  420.      <p>
  421.      Not a whole lot is happening here. IP addresses and ports are just examples—here
  422.      we’re allocating <code>10.10.0.1</code> to the server and <code>10.10.0.2</code>
  423.      to the client. The <code>SaveConfig</code> line allows WireGuard to override
  424.      this file with its current state, so you can make manual, persistent changes as
  425.      it runs.
  426.      </p>
  427.      <pre><code class="ini">
  428. # client wg0.conf
  429. [Interface]
  430. PrivateKey = [client private key]
  431. Address = 10.10.0.2/24, fd80::2/64
  432. ListenPort = 2307
  433. DNS = 10.10.0.1
  434. PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
  435. PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
  436.  
  437. [Peer]
  438. PublicKey = [server public key]
  439. PresharedKey = [preshared.key]
  440. AllowedIPs = 0.0.0.0/0, ::/0
  441. Endpoint = [wireguard server]:2307
  442. </code></pre>
  443.      <p>
  444.      The ports match for NAT traversal, but it’s not strictly necessary. The client
  445.      allows its peer to send traffic from any IP, since it’s going to be proxying the
  446.      entire internet.
  447.      </p>
  448.      <p>
  449.      On both server and client, run <code>wg-quick up wg0</code>. This can also run
  450.      as a systemd service, with <code>systemctl start wg-quick@wg0.service</code>.
  451.      </p>
  452.      ]]></content>
  453.    <link href="https://www.maths.tcd.ie/~fionn/misc/wg/"/>
  454.    <summary>This is the future of VPNs, etc. Read about it here. It really is amazing. There’s also manual configuration steps there, which you should do first. […]</summary>
  455.    <published>2017-12-07T00:00:00+00:00</published>
  456.  </entry>
  457.  <entry>
  458.    <id>https://www.maths.tcd.ie/~fionn/misc/vim/</id>
  459.    <title>Vim Plugins, the Right Way</title>
  460.    <updated>2017-09-17T00:00:00+00:00</updated>
  461.    <author>
  462.      <name>Fionn Fitzmaurice</name>
  463.      <email>fionn@this.domain</email>
  464.    </author>
  465.    <content type="CDATA"><![CDATA[<p>
  466.      It’s good to be a software minimalist (and a minimalist in general). This is how
  467.      to be one when it comes to Vim plugins (aside from not using plugins, of
  468.      course).
  469.      </p>
  470.      <h2 id="why"><a class="anchor" href="#why"></a>Why Plugin Managers?</h2>
  471.      <p>
  472.      Vim’s directory hierarchy is traditionally something like this.
  473.      </p>
  474.      <pre>
  475. .vim/
  476. ├── autoload/
  477. ├── colors/
  478. ├── doc/
  479. ├── ftplugin/
  480. ├── indent/
  481. ├── plugin/
  482. ├── spell/
  483. ├── syntax/
  484. └── undo/
  485. </pre>
  486.      <p>
  487.      It looks quite sensible. Plugins follow this hierarchy, with their
  488.      <code>.vim</code> files going into <code>plugins/</code> (and sometimes
  489.      <code>autoload/</code>), help files in <code>doc/</code>, etc. This makes
  490.      uninstalling or updating plugins a real pain.
  491.      </p>
  492.      <p>Plugin managers solve this problem by abstracting this hierarchy, so you
  493.      don’t have to think about it.
  494.      </p>
  495.      <h2 id="howto"><a class="anchor" href="#howto"></a>How to Get Rid of Plugin
  496.      Managers?</h2>
  497.      <p>
  498.      Vim 8 introduced the notion of a <em>package</em> (see <a
  499.      href="https://vimhelp.org/repeat.txt.html#packages"><code>:h
  500.      packages</code></a>). Plugins (i.e. their entire directory hierarchy) can live
  501.      in <code>.vim/pack/plugins/start/<em>plugin_name</em>/</code> and Vim will add
  502.      this to its runtime path. (The <code>plugins/</code> directory can actually be
  503.      named however you like.)
  504.      </p>
  505.      <p>
  506.      This is pretty great, because now our plugins can be kept under version control.
  507.      Getting them is just a clone, they can be easily updated and they can be rolled
  508.      back.
  509.      </p>
  510.      <p>
  511.      However, the <code>.vim/</code> directory is probably already under version
  512.      control, along with the rest of the dotfiles.
  513.      </p>
  514.      <p>
  515.      To deal with this: instead of cloning, use <code><a
  516.      href="https://git-scm.com/book/en/v2/Git-Tools-Submodules">git submodule</a> add
  517.      <var>repository</var>.git</code>. Then just keep it up to date by pulling it
  518.      every so often. To update all plugins, <code>git submodule foreach git
  519.      pull</code>.
  520.      </p>
  521.      <p>
  522.      When cloning the dotfile repository, use the <code>--recursive</code> flag to
  523.      get the submodules as well. Alternatively, clone as normal and then initialise
  524.      and update the submodules with <code>git submodule init &amp;&amp; git submodule
  525.      update</code>.
  526.      </p>
  527.      <p>
  528.      Run <code>:helptags ALL</code> to generate helptags for all plugins.
  529.      </p>
  530.      <h2 id="right"><a class="anchor" href="#right"></a>Is This Really the Right
  531.      Way?</h2>
  532.      <p>
  533.      I think so. Some might disagree and argue for using <a
  534.      href="https://www.atlassian.com/git/tutorials/git-subtree"><code>git-subtree</code></a>
  535.      instead.
  536.      </p>
  537.      <h2 id="remove"><a class="anchor" href="#remove"></a>How to Remove a
  538.      Submodule?</h2>
  539.      <p>
  540.      There’s a lot of disinformation out there. Just <code>git rm
  541.      <var>path</var>/<var>to</var>/<var>submodule</var></code>, like the <a
  542.      href="https://git-scm.com/docs/gitsubmodules#_forms">docs say</a>.
  543.      </p>
  544.      <blockquote cite="https://git-scm.com/docs/gitsubmodules">
  545.      The deletion removes the superproject’s tracking data, which are both the
  546.      <code>gitlink</code> entry and the section in the <code>.gitmodules</code> file.
  547.      The submodule’s working directory is removed from the file system, but the Git
  548.      directory is kept around as <span class="sic">it</span> to make it possible to
  549.      checkout past commits without requiring fetching from another repository.
  550.      </blockquote>
  551.      <h2 id="dotfiles"><a class="anchor" href="#dotfiles"></a>Where Are Your
  552.      Dotfiles?</h2>
  553.      <p>
  554.      <code><a href="https://github.com/fionn/.dotfiles">.dotfiles</a>/vim/<a
  555.      href="https://github.com/fionn/.dotfiles/tree/master/vim/.vim">.vim</a>/<a
  556.      href="https://github.com/fionn/.dotfiles/tree/master/vim/.vim/vimrc">vimrc</a></code>.
  557.      </p>
  558.      ]]></content>
  559.    <link href="https://www.maths.tcd.ie/~fionn/misc/vim/"/>
  560.    <summary>It’s good to be a software minimalist (and a minimalist in general). This is how to be one when it comes to Vim plugins (aside from not using plugins, of course). […]</summary>
  561.    <published>2017-09-17T00:00:00+00:00</published>
  562.  </entry>
  563.  <entry>
  564.    <id>https://www.maths.tcd.ie/~fionn/misc/ec_vpn/</id>
  565.    <title>Elliptic Curves and OpenVPN</title>
  566.    <updated>2017-04-27T00:00:00+00:00</updated>
  567.    <author>
  568.      <name>Fionn Fitzmaurice</name>
  569.      <email>fionn@this.domain</email>
  570.    </author>
  571.    <content type="CDATA"><![CDATA[<p>
  572.      The standard OpenVPN installation uses RSA and a hefty Diffie-Hellman parameters
  573.      file. This is not ideal, but it’s possible to run OpenVPN using elliptic curves.
  574.      </p>
  575.      <p>
  576.      This was all done on OpenVPN 2.4.1. As far as I know, elliptic curve
  577.      cryptography support in OpenVPN is for 2.4.0+.
  578.      </p>
  579.      <h2>PKI</h2>
  580.      <p>
  581.      Get Easy-RSA and set up variables in the <code>vars</code> file.
  582.      </p>
  583.      <pre>
  584. set_var EASYRSA_ALGO     ec
  585. set_var EASYRSA_CURVE    secp521r1
  586. set_var EASYRSA_DIGEST   "sha512"
  587. </pre>
  588.      <p>
  589.      The choice of curve is a personal one. <code>secp521r1</code> is P-521. DJB <a
  590.      href="https://blog.cr.yp.to/20140323-ecdsa.html">considers it a nice prime</a>.
  591.      All supported curves are listed with <code>openvpn --show-curves</code> (<a
  592.      href="curves.txt">these are mine</a>).
  593.      </p>
  594.      <p>
  595.      There’s <a href="https://github.com/OpenVPN/easy-rsa/issues/111">a bug</a> in
  596.      Easy-RSA regarding sourcing this file. The workaround is to <code>export
  597.      EASYRSA_VARS_FILE=/etc/easy-rsa/vars</code> (or put it in <code>.bashrc</code>
  598.      or whatever).
  599.      </p>
  600.      <p>
  601.      Make the PKI and build the CA with <code>easyrsa init-pki</code>, <code>easyrsa
  602.      build-ca</code>.
  603.      </p>
  604.      <pre>
  605. <span class="root-shell">easyrsa gen-req <em>servername</em> nopass</span>
  606. <span class="root-shell">easyrsa sign-req server <em>servername</em></span>
  607. <span class="root-shell">easyrsa gen-req <em>clientname</em> [nopass]</span>
  608. <span class="root-shell">easyrsa sign-req client <em>clientname</em></span>
  609. </pre>
  610.      <p>We now have all the server files
  611.      </p>
  612.      <pre>
  613. pki/ca.crt
  614. pki/issued/<em>servername</em>.crt
  615. pki/private/<em>servername</em>.key
  616. </pre>
  617.      <p>
  618.      and all the client files
  619.      </p>
  620.      <pre>
  621. pki/ca.crt
  622. pki/issued/<em>clientname</em>.crt
  623. pki/private/<em>clientname</em>.key
  624. </pre>
  625.      <p>
  626.      (there’s some nonsense about 3DES-encrypting the client key, which I’m
  627.      ignoring).
  628.      </p>
  629.      <p>
  630.      If you didn’t set the <code>nopass</code> option but now regret it, run
  631.      <code>openssl ec -in <em>clientname</em>.key -out
  632.      <em>clientname</em>_nopass.key</code>, enter your password and rename the keys.
  633.      </p>
  634.      <h2>VPN</h2>
  635.      <p>
  636.      Copy the server and client files to their respective OpenVPN directories.
  637.      </p>
  638.      <p>
  639.      Here’s an example server configuration.
  640.      </p>
  641.      <pre>
  642. port 1194
  643. proto udp
  644. dev tun
  645.  
  646. ca ecc/ca.crt
  647. cert ecc/servername.crt
  648. key ecc/servername.key
  649.  
  650. dh none
  651.  
  652. server 10.8.0.0 255.255.255.0
  653. ifconfig-pool-persist ipp.txt
  654. push "redirect-gateway def1"
  655. push "dhcp-option DNS 1.2.3.4"
  656.  
  657. keepalive 10 120
  658.  
  659. tls-crypt ecc/tc.key
  660. auth SHA512
  661. keysize 256
  662. tls-server
  663. tls-version-min 1.2
  664. tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384
  665. cipher AES-256-GCM
  666. reneg-sec 360
  667. remote-cert-eku "TLS Web Client Authentication"
  668. script-security 2
  669. auth-user-pass-verify /etc/openvpn/server/auth/auth.py via-file
  670.  
  671. user nobody
  672. group nobody
  673.  
  674. persist-key
  675. persist-tun
  676.  
  677. status openvpn-status.log
  678. explicit-exit-notify 1
  679. </pre>
  680.      <p>
  681.      And a client configuration.
  682.      </p>
  683.      <pre>
  684. client
  685. dev tun
  686. proto udp
  687. remote serverurl 1194
  688. resolv-retry infinite
  689. nobind
  690. #user nobody
  691. #group nobody
  692. persist-key
  693. persist-tun
  694. tls-client
  695. mute-replay-warnings
  696. ca servername/ecc/ca.crt
  697. cert servername/ecc/clientname.crt
  698. key servername/ecc/clientname.key
  699. remote-cert-eku "TLS Web Server Authentication"
  700. verify-x509-name 'CN=servername' subject
  701. remote-cert-tls server
  702. tls-crypt servername/ecc/tc.key
  703. cipher AES-256-GCM
  704. auth SHA512
  705. tls-version-min 1.2
  706. tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384
  707. reneg-sec 360
  708. #comp-lzo
  709. verb 3
  710. #mute 20
  711.  
  712. auth-user-pass servername/secret.password
  713. redirect-gateway def1
  714. script-security 2
  715. up /etc/openvpn/client/servername/update-resolv-conf.sh
  716. down /etc/openvpn/client/servername/update-resolv-conf.sh
  717. </pre>
  718.      <p>
  719.      For several devices/users, managing certs, etc., can be tedious to do by hand. I
  720.      wrote some code to <a href="https://github.com/fionn/vpn-auth">automate it</a>.
  721.      </p>
  722.      ]]></content>
  723.    <link href="https://www.maths.tcd.ie/~fionn/misc/ec_vpn/"/>
  724.    <summary>The standard OpenVPN installation uses RSA and a hefty Diffie-Hellman parameters file. This is not ideal, but it’s possible to run OpenVPN using elliptic curves. […]</summary>
  725.    <published>2017-04-27T00:00:00+00:00</published>
  726.  </entry>
  727.  <entry>
  728.    <id>https://www.maths.tcd.ie/~fionn/misc/mt/</id>
  729.    <title>The Mersenne Twister</title>
  730.    <updated>2017-05-23T00:00:00+00:00</updated>
  731.    <author>
  732.      <name>Fionn Fitzmaurice</name>
  733.      <email>fionn@this.domain</email>
  734.    </author>
  735.    <content type="CDATA"><![CDATA[<p>
  736.      The Mersenne Twister is <a
  737.      href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/mt.pdf">a
  738.      623-dimensionally equidistributed uniform pseudorandom number generator</a>.
  739.      This is how it works.
  740.      </p>
  741.      <p>
  742.      The paper first defines a $k$-distribution as a very reasonable definition of
  743.      randomness. Read the paper first.
  744.      </p>
  745.      <h2 id="recurrence"><a class="anchor" href="#recurrence"></a>The Linear
  746.      Recurrence</h2>
  747.      <p>
  748.      Equation 2.1 in <em>M&amp;N</em> 1998 is the linear recurrence
  749.      $$
  750.      \mathbf{x}_{k + n} := \mathbf{x}_{k + m} \oplus (\mathbf{x}_k^u |
  751.      \mathbf{x}^l_{k + 1}) A
  752.      $$
  753.      ($k = 0, 1, \ldots$). The paper says the following.
  754.      </p>
  755.      <blockquote
  756.      cite="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/ARTICLES/mt.pdf#page=6">
  757.      We have several constants: an integer $n$, which is the degree of the
  758.      recurrence, an integer $r$ (hidden in the definition of $\mathbf{x}_k^u$), $0
  759.      \leq r \leq w - 1$, an integer $m$, $1 \leq m \leq n$, and a constant $w \times
  760.      w$ matrix $A$ with entries in $\mathbb{F}_2$.
  761.      </blockquote>
  762.      <p>
  763.      From the paper, $w$ is the “word length”, so $\mathbf{x}_i \, \in \,
  764.      \mathbb{F}_2^w$ are “word vectors” of length $w$.
  765.      </p>
  766.      <p>
  767.      On the right, we have this $\mathbf{x}_k^u | \mathbf{x}^l_{k + 1}$ term. This is
  768.      the concatonation of $\mathbf{x}_k^u$ with $\mathbf{x}^l_{k + 1}$.
  769.      $\mathbf{x}_k^u$ is the “upper $w - r$ bits” of $\mathbf{x}_k$ and
  770.      $\mathbf{x}^l_{k + 1}$ is the “lower $r$ bits” of $\mathbf{x}_{k + 1}$, i.e.
  771.      denoting
  772.      $$
  773.      \mathbf{x}_k = (x_{w - 1}, \ldots, x_{r}, x_{r - 1}, \ldots, x_0),
  774.      $$
  775.      then
  776.      $$
  777.      \mathbf{x}_k^u = (x_{w - 1}, \ldots, x_{r}), \qquad
  778.      \mathbf{x}_k^l = (x_{r - 1}, \ldots, x_0).
  779.      $$
  780.      </p>
  781.      <p>
  782.      Given $n$ initial seeds $\mathbf{x}_0, \ldots, \mathbf{x}_{n - 1}$, we can
  783.      generate
  784.      $$
  785.      \mathbf{x}_{n} := \mathbf{x}_{m} \oplus (\mathbf{x}_0^u | \mathbf{x}^l_{1}) A
  786.      $$
  787.      (where $k = 0$). The only constants here are $n$, $m$, $r$ and $A$.
  788.      </p>
  789.      <p>
  790.      $A$ is the sparse matrix
  791.      $$
  792.      A = \begin{pmatrix}
  793.      0 &amp; 1 &amp; 0 &amp; \cdots &amp; 0 \\
  794.      0 &amp; 0 &amp; 1 &amp;        &amp; 0 \\
  795.      \vdots &amp; \vdots &amp; &amp; \ddots &amp; \vdots \\
  796.      0 &amp; 0 &amp; &amp; &amp; 1 \\
  797.      a_{w - 1} &amp; a_{w - 2} &amp; a_{w - 3} &amp; \cdots &amp; a_0
  798.      \end{pmatrix}
  799.      $$
  800.      where we denote the bottom row as $\mathbf{a} = (a_{w - 1}, \ldots, a_0)$.
  801.      </p>
  802.      <p>
  803.      For $\mathbf{x} = (x_{w - 1}, \ldots, x_0)$,
  804.      $$
  805.      \mathbf{x}A = (x_0 a_{w - 1}, x_{w - 1} + x_0 a_{w - 2}, \ldots, x_1 + x_0 a_0).
  806.      $$
  807.      </p>
  808.      <p>
  809.      Notice that if $x_0 = 0$, this simplifies to
  810.      $$
  811.      \mathbf{x}A = (0, x_{w - 1}, \ldots, x_1)
  812.      $$
  813.      which amounts to a right bitshift, i.e. $\mathbf{x}A = \mathbf{x} \gg 1$.
  814.      If $x_0 = 1$ instead, then
  815.      $$
  816.      \mathbf{x}A = (a_{w - 1}, x_{w - 1} + a_{w - 2}, \ldots, x_1 + a_0)
  817.      $$
  818.      and this reduces to an addition of $\mathbf{a}$, i.e. $\mathbf{x}A = (\mathbf{x}
  819.      \gg 1) \oplus \mathbf{a}$. (Recall that this is an xor, since we are working in
  820.      $\mathbb{F}_2$.)
  821.      </p>
  822.      <p>
  823.      For MT19937, the parameters are $w = 32$, $n = 624$, $m = 397$, $r = 31$ and
  824.      $\mathbf{a} = \mathtt{0x9908B0DF}$ (<em>M&amp;N</em> 1998, Table II).
  825.      </p>
  826.      <h2 id="initialisation"><a class="anchor"
  827.      href="#initialisation"></a>Initialisation</h2>
  828.      <p>
  829.      There is an undocumented parameter $f$ which is used to initialise the internal
  830.      state as
  831.      $$
  832.      \mathbf{x}_i = f \cdot (\mathbf{x}_{i - 1} \oplus (\mathbf{x}_{i - 1} \gg (w -
  833.      2))) + i.
  834.      $$
  835.      This is <a href="https://eprint.iacr.org/2005/165.pdf#page=4">given the
  836.      value</a> $f = 1812433253$.
  837.      </p>
  838.      <h2 id="tempering"><a class="anchor" href="#tempering"></a>Tempering</h2>
  839.      <p>
  840.      The linear operator $T$ is a $w \times w$ invertible matrix. We define
  841.      “tempering” to be the operation
  842.      $$
  843.      \mathbf{x} \mapsto \mathbf{z} = \mathbf{x} T.
  844.      $$
  845.      $T$ consists of the following bitwise operations.
  846.      $$\begin{aligned}
  847.      \mathbf{y} &amp;:= \mathbf{x} \oplus (\mathbf{x} \gg u), \\
  848.      \mathbf{y} &amp;:= \mathbf{y} \oplus \bigl((\mathbf{y} \ll s) \otimes
  849.      \mathbf{b}\bigr), \\
  850.      \mathbf{y} &amp;:= \mathbf{y} \oplus \bigl((\mathbf{y} \ll t) \otimes
  851.      \mathbf{c}\bigr), \\
  852.      \mathbf{z} &amp;:= \mathbf{y} \oplus (\mathbf{y} \gg l)
  853.      \end{aligned}$$
  854.      (equations 2.2 to 2.5). These parameters are $u = 11$, $s = 7$, $\mathbf{b} =
  855.      \mathtt{0x9D2C5680}$, $t = 15$, $\mathbf{c} = \mathtt{0xEFC60000}$ and $l = 18$
  856.      (<em>M&amp;N</em> 1998, Table II).
  857.      </p>
  858.      <h2 id="implementation"><a class="anchor" href="#implementation"></a>An
  859.      Implementation</h2>
  860.      <p>
  861.      This is the Mersenne Twister in Python. The linear recurrence occurs in
  862.      <code>_twist</code> and the tempering in <code>temper</code>.
  863.      </p>
  864.      <pre><code class="language-python">
  865. #!/usr/bin/env python3
  866. """The Mersenne Twister"""
  867.  
  868. class MT19937:
  869.    u = 11
  870.    s, b = 7, 0x9d2c5680
  871.    t, c = 15, 0xefc60000
  872.    l = 18
  873.  
  874.    def __init__(self, seed: int) -&gt; None:
  875.        self.index = 624
  876.        self.state = [0] * 624
  877.        self.state[0] = seed &amp; 0xffffffff
  878.        for i in range(1, 624):
  879.            self.state[i] = 0x6c078965 \
  880.                            * (self.state[i - 1] ^ self.state[i - 1] &gt;&gt; 30) \
  881.                            + i &amp; 0xffffffff
  882.  
  883.    @staticmethod
  884.    def temper(y: int) -&gt; int:
  885.        y ^= y &gt;&gt; MT19937.u
  886.        y ^= y &lt;&lt; MT19937.s &amp; MT19937.b
  887.        y ^= y &lt;&lt; MT19937.t &amp; MT19937.c
  888.        y ^= y &gt;&gt; MT19937.l
  889.        return y
  890.  
  891.    def random(self) -&gt; int:
  892.        if self.index &gt;= 624:
  893.            self._twist()
  894.        y = self.temper(self.state[self.index])
  895.        self.index += 1
  896.        return y
  897.  
  898.    def _twist(self) -&gt; None:
  899.        for i in range(624):
  900.            y = (self.state[i] &amp; 0x80000000) \
  901.                + (self.state[(i + 1) % 624] &amp; 0x7fffffff)
  902.            self.state[i] = self.state[(i + 397) % 624] ^ y &gt;&gt; 1
  903.            if y % 2 != 0:
  904.                self.state[i] ^= 0x9908b0df
  905.        self.index = 0
  906.  
  907. def main() -&gt; None:
  908.    x = MT19937(5489)      # Seed from mt19937ar.c
  909.    for _ in range(1000):
  910.        print(x.random())
  911.  
  912. if __name__ == "__main__":
  913.    main()
  914. </code></pre>
  915.      <h2 id="untempering"><a class="anchor" href="#untempering"></a>Untempering</h2>
  916.      <p>
  917.      The Mersenne Twister is not cryptographically secure since the transformation
  918.      $T$ is bijective. Due to the existence of $T^{-1}$, we can create an
  919.      “untempering” function. If we can record $n$ consecutive outputs of the Mersenne
  920.      Twister and untemper them, this will give us the internal state of the random
  921.      number generator and allow us to predict all future values.
  922.      </p>
  923.      <pre><code class="language-python">
  924. #!/usr/bin/env python3
  925. """Clone an MT19937 RNG from its output"""
  926.  
  927. from mt import MT19937
  928.  
  929. def untemper(y: int) -&gt; int:
  930.    y ^= y &gt;&gt; MT19937.l
  931.    y ^= y &lt;&lt; MT19937.t &amp; MT19937.c
  932.    for _ in range(7):
  933.        y ^= y &lt;&lt; MT19937.s &amp; MT19937.b
  934.    for _ in range(3):
  935.        y ^= y &gt;&gt; MT19937.u
  936.    return y
  937.  
  938. def clone_mt(mt: MT19937) -&gt; MT19937:
  939.    mt_clone = MT19937(0)
  940.    for i in range(624):
  941.        mt_clone.state[i] = untemper(mt.random())
  942.    return mt_clone
  943.  
  944. def main() -&gt; None:
  945.    mt = MT19937(5489)
  946.    mt_clone = clone_mt(mt)
  947.  
  948.    for _ in range(2000):
  949.        assert mt_clone.random() == mt.random()
  950.  
  951.    print(mt_clone)
  952.  
  953. if __name__ == "__main__":
  954.    main()
  955. </code></pre>
  956.      <p>
  957.      See <code><a
  958.      href="https://github.com/fionn/cryptopals/blob/master/m21.py">m21.py</a></code>
  959.      and <code><a
  960.      href="https://github.com/fionn/cryptopals/blob/master/m23.py">m23.py</a></code>
  961.      on <a href="https://github.com/fionn">my GitHub account</a>.
  962.      </p>
  963.      ]]></content>
  964.    <link href="https://www.maths.tcd.ie/~fionn/misc/mt/"/>
  965.    <summary>The Mersenne Twister is a 623-dimensionally equidistributed uniform pseudorandom number generator. This is how it works. […]</summary>
  966.    <published>2017-05-23T00:00:00+00:00</published>
  967.  </entry>
  968.  <entry>
  969.    <id>https://www.maths.tcd.ie/~fionn/misc/symmetry/</id>
  970.    <title>Symmetry in Particle Physics</title>
  971.    <updated>2016-09-26T00:00:00+00:00</updated>
  972.    <author>
  973.      <name>Fionn Fitzmaurice</name>
  974.      <email>fionn@this.domain</email>
  975.    </author>
  976.    <content type="CDATA"><![CDATA[<p>
  977.                  A while ago, I wrote an article for non-physicists about symmetry
  978.      and the Standard Model.
  979.                  </p>
  980.      <br/>
  981.      ]]></content>
  982.    <link href="https://www.maths.tcd.ie/~fionn/misc/symmetry/"/>
  983.    <summary>A while ago, I wrote an article for non-physicists about symmetry and the Standard Model. […]</summary>
  984.    <published>2016-09-26T00:00:00+00:00</published>
  985.  </entry>
  986.  <entry>
  987.    <id>https://www.maths.tcd.ie/~fionn/misc/padding_oracle/</id>
  988.    <title>The Padding Oracle Attack</title>
  989.    <updated>2016-08-06T00:00:00+00:00</updated>
  990.    <author>
  991.      <name>Fionn Fitzmaurice</name>
  992.      <email>fionn@this.domain</email>
  993.    </author>
  994.    <content type="CDATA"><![CDATA[<p>
  995.      There are a bunch of writeups on this attack, such as
  996.      <a href="https://robertheaton.com/2013/07/29/padding-oracle-attack/">Robert
  997.      Heaton's blog post</a>,
  998.      <a
  999.      href="https://blog.skullsecurity.org/2013/padding-oracle-attacks-in-depth">SkullSecurity</a>
  1000.      (and their <a
  1001.      href="https://blog.skullsecurity.org/2013/a-padding-oracle-example#">follow-up</a>),
  1002.      <a
  1003.      href="https://blog.gdssecurity.com/labs/2010/9/14/automated-padding-oracle-attacks-with-padbuster.html">GDS</a>,
  1004.      <a href="https://github.com/mpgn/Padding-oracle-attack">mpgn</a>,
  1005.      <a
  1006.      href="https://grymoire.wordpress.com/2014/12/05/cbc-padding-oracle-attacks-simplified-key-concepts-and-pitfalls/">Grymoire</a>,
  1007.      this <a href="https://crypto.stackexchange.com/a/3772">crypto.SX post</a>
  1008.      and the <a
  1009.      href="https://www.iacr.org/archive/eurocrypt2002/23320530/cbc02_e02d.pdf">paper
  1010.      by Serge Vaudenay</a>.
  1011.      Dan Boneh has a <a
  1012.      href="https://www.youtube.com/watch?v=evrgQkULQ5U">lecture</a> on it
  1013.      and <a class="dead" title="https://www.youtube.com/watch?v=D-4mmc7frR4">this
  1014.      video</a> is good too.
  1015.      Here’s my digestion of it.</p>
  1016.      <p>Let there be $n$ blocks of plaintext, each of blocksize $k$. For $i \in [1,
  1017.      n]$,
  1018.      $$\begin{aligned}
  1019.      c_i &amp;= E(p_i \oplus  c_{i-1}), \\
  1020.      p_i &amp;= D(c_i) \oplus c_{i-1}
  1021.      \end{aligned}$$
  1022.      where $c_i$ is the $i$<sup>th</sup> cyphertext block, $p_i$ the $i$<sup>th</sup>
  1023.      plaintext block and $c_0$ the initialisation vector.
  1024.      </p>
  1025.      <p>
  1026.      Construct some block, which we will call $c'$. If we concatenate it with the
  1027.      last cyphertext block $c_n$, the corresponding plaintext of $c'|c_n$ would be
  1028.      $p_1'|p_2'$,
  1029.      $$\begin{aligned}
  1030.      p'_1 = D(c') \oplus c_0, \quad p'_2 &amp;= D(c_n) \oplus c' \\
  1031.      &amp;= D(E(p_n \oplus c_{n-1})) \oplus c' \\
  1032.      &amp;= p_n \oplus c_{n-1} \oplus c',
  1033.      \end{aligned}$$
  1034.      giving
  1035.      $$
  1036.      p_n = p_2' \oplus c' \oplus c_{n-1}.
  1037.      $$
  1038.      </p>
  1039.      <p>
  1040.      As $p_2'$ is at the end of our plaintext block it must have valid padding. This
  1041.      puts a constraint on $c'$. If only there was some way to tell if the plaintext
  1042.      had valid padding...
  1043.      </p>
  1044.      <h2>The Padding Oracle</h2>
  1045.      <p>
  1046.      For $p$ the plaintext corresponding to cyphertext $c$, define the padding oracle
  1047.      $\mathcal{O}$ as
  1048.      $$ \mathcal{O}(c) =
  1049.      \begin{cases}
  1050.      1 &amp; \text{if } p \text{ has valid padding}, \\
  1051.      0 &amp; \text{otherwise}.
  1052.      \end{cases}
  1053.      $$
  1054.      We can now construct $c'$ such that $p_2' = D(c_n) \oplus c'$ has valid padding,
  1055.      by submitting $c'|c_n$ to the oracle. If $\mathcal{O}(c'|c_n) = 1$, the padding
  1056.      in $p_2'$ is valid.
  1057.      </p>
  1058.      <h2>The Last Byte</h2>
  1059.      <p>
  1060.      Borrowing some programming notation, if we consider the last byte in $p_2'$ to
  1061.      be $p_2'[k] = \mathtt{\backslash x01}$, $p_2'$ will (trivially) have valid
  1062.      padding. If we can construct a $c'$ such that this is the case, we will know
  1063.      that the last byte of $p_2'$ is one.
  1064.      </p>
  1065.      <p>
  1066.      For such a $c'$, $c'_k$, say,
  1067.      $$\begin{aligned}
  1068.      p_n[k] &amp;= p_2'[k] \oplus c'_k[k] \oplus c_{n-1}[k] \\
  1069.             &amp;= 1 \oplus c'_k[k] \oplus c_{n-1}[k].
  1070.      \end{aligned}$$
  1071.      (Here $1 = \mathtt{\backslash x01}$. We’ll use this shorthand throughout.)
  1072.      </p>
  1073.      <p>
  1074.      To construct $c'_k$, it is enough to notice that since $p'_2 = D(c_n) \oplus
  1075.      c'_k$ and we are only interested in $p'_2[k] = D(c_n)[k] \oplus c'_k[k]$, we can
  1076.      let
  1077.      $$
  1078.      c'_k = (\mathtt{\backslash x00}, \mathtt{\backslash x00}, \ldots,
  1079.      \mathtt{\backslash x00}, b)$$
  1080.      (i.e. 15 bytes of zero, or whatever, and the final byte $c'_k[k] = b$).
  1081.      Iterating over all possible values of $b$ and submitting the cyphertext to the
  1082.      oracle will give us the value of $b$ that produces valid padding. Thus, we’ve
  1083.      found the last byte of the plaintext.
  1084.      </p>
  1085.      <h2>The Second-Last Byte</h2>
  1086.      <p>
  1087.      Another valid plaintext would be $p_2'[k] = p_2'[k-1] = \mathtt{\backslash
  1088.      x02}$.
  1089.      </p>
  1090.      <p>
  1091.      To construct $c'_{k-1}$, notice that $c'_{k-1}[k]$ will simply be the previous
  1092.      $c'_k[k]$ xored appropriately.
  1093.      $$\begin{aligned}
  1094.      p_2'[k] \oplus c'_k[k] &amp;= 1, \\
  1095.      p_2'[k] \oplus c'_k[k] &amp;\oplus 1 \oplus 2 = 2,
  1096.      \end{aligned}$$
  1097.      but
  1098.      $$
  1099.      p_2'[k] \oplus c'_{k-1}[k] = 2
  1100.      $$
  1101.      by definition of $c'_{k-1}$, so equating these we get
  1102.      $$
  1103.      p_2'[k] \oplus c'_{k-1}[k] = p_2'[k] \oplus c'_k[k] \oplus 1 \oplus 2,
  1104.      $$
  1105.      giving
  1106.      $$
  1107.      c'_{k-1}[k] = c'_k[k] \oplus 1 \oplus 2.
  1108.      $$
  1109.      </p>
  1110.      <p>$c'_{k-1}[k-1]$ is found by testing all possible values until
  1111.      $\mathcal{O}(c'_{k-1}|c_n) = 1$. Then the second-last byte is
  1112.      $$
  1113.      p_n[k-1] = 2 \oplus c'_{k-1}[k-1] \oplus c_{n-1}[k-1].
  1114.      $$
  1115.      </p>
  1116.      <h2>All the Bytes</h2>
  1117.      <p>
  1118.      In general, we get each byte of the plaintext block via
  1119.      $$
  1120.      p_n[k - i] = (i + 1) \oplus c_{k-i}'[k-i] \oplus c_{n-1}[k-i],
  1121.      $$
  1122.      for $i \in [0, k)$, where $c_i'$ is $c'$ constructed for the $i$<sup>th</sup>
  1123.      byte via
  1124.      $$
  1125.      c'_{k-i}[k - j] = c'_{k - i + 1}[k - j] \oplus i \oplus (i + 1)
  1126.      $$
  1127.      where $j \leq i$.
  1128.      </p>
  1129.      <h2>All the Blocks</h2>
  1130.      <p>
  1131.      This is repeated for each block, excluding the first (because we don’t know the
  1132.      initialisation vector).
  1133.      </p>
  1134.      <h2>Caveats</h2>
  1135.      <p>
  1136.      Notice that for finding the last byte $p_n[k]$ we iterated over all possible
  1137.      values of $c'[k] = b$ until $\mathcal{O}(c'|c_n) = 1$ and concluded then that
  1138.      $p_2'[k] = \mathtt{\backslash x01}$. However, there is a small probability
  1139.      ($\frac{1}{256}$) that $p_2'[k-1] = \mathtt{\backslash x02}$ and our oracle is
  1140.      satisfied because we’ve inadvertently found the cyphertext byte that corresponds
  1141.      to $p_2'[k] = \mathtt{\backslash x02}$.
  1142.      </p>
  1143.      <p>
  1144.      This could similarly happen if $p_2'[k-2] = p_2'[k-1] = \mathtt{\backslash
  1145.      x03}$, where we would get a positive result if $p_2' = \mathtt{\backslash x03}
  1146.      \neq \mathtt{\backslash x01}$, and so on. This becomes increasingly unlikely,
  1147.      but is easy to mitigate by instead approaching the problem from the left.
  1148.      </p>
  1149.      <p>
  1150.      Take $c_{n-1}|c_n$, which will obviously satisfy the oracle (and give $p_2' =
  1151.      p_n$). Then vary the bytes in $c_{n-1}$ from left to right and query the oracle
  1152.      each time. If the oracle returns false on the $i$<sup>th</sup> byte, then the
  1153.      remaining $k - i$ bytes are all equal to $k-i$. We also gain a substantial
  1154.      speedup on the last block as we get all the plaintext at once.
  1155.      </p>
  1156.      <p>
  1157.      Alternatively, we can check that when we determine the last byte it really is
  1158.      $\mathtt{\backslash x01}$. Then all the other bytes must be correct, too. To do
  1159.      this, vary the second last byte. If the padding is invalid, we know that we were
  1160.      wrong about the last byte so we try again. This only needs to be checked once
  1161.      per block. We lose the speedup advantage above, but it is simpler.
  1162.      </p>
  1163.      <h2>Code</h2>
  1164.      <p>
  1165.      I wrote a <a
  1166.      href="https://github.com/fionn/cryptopals/blob/master/m17.py">program</a> that
  1167.      does this.
  1168.      </p>
  1169.      <p>
  1170.      Here it is in action.
  1171.      </p>
  1172.      <noscript><p>
  1173.      You must enable JavaScript to see this :(
  1174.      </p></noscript>
  1175.      <asciinema-player author="Fionn Fitzmaurice"
  1176.      author-img-url="https://www.maths.tcd.ie/~fionn/me.jpg"
  1177.      author-url="https://www.maths.tcd.ie/~fionn/" cols="97" font-size="0.79em"
  1178.      poster="npt:1" rows="34" src="tyger.json" title="Padding Oracle Attack">
  1179.      </asciinema-player>
  1180.      <hr size="1"/>
  1181.      <p>
  1182.      Update: I gave a talk on this, the slides are <a
  1183.      href="padding_oracle.pdf">here</a>.
  1184.      </p>
  1185.      ]]></content>
  1186.    <link href="https://www.maths.tcd.ie/~fionn/misc/padding_oracle/"/>
  1187.    <summary>There are a bunch of writeups on this attack, such as
  1188. Robert Heaton's blog post,
  1189. SkullSecurity
  1190. (and their follow-up),
  1191. GDS,
  1192. mpgn,
  1193. Grymoire,
  1194. this crypto.SX post
  1195. and the paper by Serge Vaudenay.
  1196. Dan Boneh has a lecture on it
  1197. and this video is good too.
  1198. Here’s my digestion of it. […]</summary>
  1199.    <published>2016-08-06T00:00:00+00:00</published>
  1200.  </entry>
  1201.  <entry>
  1202.    <id>https://www.maths.tcd.ie/~fionn/misc/macbook/</id>
  1203.    <title>Arch on a MacBook</title>
  1204.    <updated>2016-05-22T00:00:00+00:00</updated>
  1205.    <author>
  1206.      <name>Fionn Fitzmaurice</name>
  1207.      <email>fionn@this.domain</email>
  1208.    </author>
  1209.    <content type="CDATA"><![CDATA[<p>
  1210.      This is what I did to put Arch Linux on my MacBook Pro <a
  1211.      href="https://support.apple.com/kb/sp715" title="Technical
  1212.      specifications">12,1</a> (A1502, 2015) with dm-crypt (LVM on LUKS). Much of the
  1213.      start is taken from <a
  1214.      href="https://loicpefferkorn.net/2015/01/arch-linux-on-macbook-pro-retina-2014-with-dm-crypt-lvm-and-suspend-to-disk/">this
  1215.      blog post</a>, but it’s reproduced here because of fear of link-rot.
  1216.      </p>
  1217.      <p>
  1218.      Here’s my hardware (from <code>lspci</code>).
  1219.      </p>
  1220.      <pre>
  1221. 00:00.0 Host bridge: Intel Corporation Broadwell-U Host Bridge -OPI (rev 09)
  1222. 00:02.0 VGA compatible controller: Intel Corporation Broadwell-U Integrated Graphics (rev 09)
  1223. 00:03.0 Audio device: Intel Corporation Broadwell-U Audio Controller (rev 09)
  1224. 00:14.0 USB controller: Intel Corporation Wildcat Point-LP USB xHCI Controller (rev 03)
  1225. 00:15.0 DMA controller: Intel Corporation Wildcat Point-LP Serial IO DMA Controller (rev 03)
  1226. 00:15.4 Serial bus controller [0c80]: Intel Corporation Wildcat Point-LP Serial IO GSPI Controller #1 (rev 03)
  1227. 00:16.0 Communication controller: Intel Corporation Wildcat Point-LP MEI Controller #1 (rev 03)
  1228. 00:1b.0 Audio device: Intel Corporation Wildcat Point-LP High Definition Audio Controller (rev 03)
  1229. 00:1c.0 PCI bridge: Intel Corporation Wildcat Point-LP PCI Express Root Port #1 (rev e3)
  1230. 00:1c.1 PCI bridge: Intel Corporation Wildcat Point-LP PCI Express Root Port #2 (rev e3)
  1231. 00:1c.2 PCI bridge: Intel Corporation Wildcat Point-LP PCI Express Root Port #3 (rev e3)
  1232. 00:1c.4 PCI bridge: Intel Corporation Wildcat Point-LP PCI Express Root Port #5 (rev e3)
  1233. 00:1c.5 PCI bridge: Intel Corporation Wildcat Point-LP PCI Express Root Port #6 (rev e3)
  1234. 00:1f.0 ISA bridge: Intel Corporation Wildcat Point-LP LPC Controller (rev 03)
  1235. 00:1f.3 SMBus: Intel Corporation Wildcat Point-LP SMBus Controller (rev 03)
  1236. 00:1f.6 Signal processing controller: Intel Corporation Wildcat Point-LP Thermal Management Controller (rev 03)
  1237. 02:00.0 Multimedia controller: Broadcom Corporation 720p FaceTime HD Camera
  1238. 03:00.0 Network controller: Broadcom Corporation BCM43602 802.11ac Wireless LAN SoC (rev 01)
  1239. 04:00.0 SATA controller: Samsung Electronics Co Ltd Device a801 (rev 01)
  1240. 05:00.0 PCI bridge: Intel Corporation DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013]
  1241. 06:00.0 PCI bridge: Intel Corporation DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013]
  1242. 06:03.0 PCI bridge: Intel Corporation DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013]
  1243. 06:04.0 PCI bridge: Intel Corporation DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013]
  1244. 06:05.0 PCI bridge: Intel Corporation DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013]
  1245. 06:06.0 PCI bridge: Intel Corporation DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013]
  1246. 07:00.0 System peripheral: Intel Corporation DSL5520 Thunderbolt 2 NHI [Falcon Ridge 4C 2013]
  1247. </pre>
  1248.      <p>
  1249.      This is the partition scheme we’ll end up with (45 GiB for OS X, 10 GiB for a
  1250.      shared HFS+ partition and the rest (~177.8 GiB) for a LVM container).
  1251.      </p>
  1252.      <pre class="shell">
  1253. sudo gdisk -l /dev/sda
  1254. GPT fdisk (gdisk) version 1.0.1
  1255.  
  1256. Partition table scan:
  1257.  MBR: hybrid
  1258.  BSD: not present
  1259.  APM: not present
  1260.  GPT: present
  1261.  
  1262. Found valid GPT with hybrid MBR; using GPT.
  1263. Disk /dev/sda: 490234752 sectors, 233.8 GiB
  1264. Logical sector size: 512 bytes
  1265. Disk identifier (GUID): XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
  1266. Partition table holds up to 128 entries
  1267. First usable sector is 34, last usable sector is 490234718
  1268. Partitions will be aligned on 8-sector boundaries
  1269. Total free space is 262150 sectors (128.0 MiB)
  1270.  
  1271. Number  Start (sector)    End (sector)  Size       Code  Name
  1272.   1              40          409639   200.0 MiB   EF00  EFI System Partition
  1273.   2          409640        94865191   45.0 GiB    AF05  Customer
  1274.   3        94865192        96134727   619.9 MiB   AB00  Recovery HD
  1275.   4        96396872       117368391   10.0 GiB    AF00  hfs
  1276.   5       117368392       490234718   177.8 GiB   8E00  archlinux
  1277. </pre>
  1278.      <p>
  1279.      It’s probably a good idea to make a backup first. I didn’t because I like to
  1280.      live on the edge. You can boot into recovery mode later if you need to with
  1281.      <kbd>⌘</kbd> + <kbd>R</kbd>.
  1282.      </p>
  1283.      <h2 id="osx"><a class="anchor" href="#osx"></a>OS X</h2>
  1284.      <p>
  1285.      Get an <a href="https://archlinux.org/download/">Arch image</a>, verify it and
  1286.      burn it to a USB key with something like
  1287.      </p>
  1288.      <pre class="root-shell">
  1289. dd if=archlinux-2016.05.01-dual.iso of=/dev/rdisk2 bs=4M &amp;&amp; sync
  1290. </pre>
  1291.      <p>
  1292.      where we use <code><b>r</b>disk2</code> to write to the raw disk and skip some
  1293.      buffering. Use <code>diskutil</code> to figure out which disk to use.
  1294.      </p>
  1295.      <p>
  1296.      Then resize the OS X partition and encrypt it with FileVault.
  1297.      </p>
  1298.      <h2 id="archlinux"><a class="anchor" href="#archlinux"></a>Arch Linux</h2>
  1299.      <p>
  1300.      Boot into Arch by holding the right <kbd>alt</kbd> key. To make the console font
  1301.      larger, use <code>setfont sun12x22</code> (the biggest one on the system).
  1302.      </p>
  1303.      <p>
  1304.      I had to set
  1305.      </p>
  1306.      <pre class="root-shell">
  1307. echo 0 &gt; /sys/module/hid_apple/parameters/iso_layout
  1308. </pre>
  1309.      <p>
  1310.      to fix the keyboard layout, swapping <kbd>`</kbd> and <kbd>~</kbd> with
  1311.      <kbd>&lt;</kbd> and <kbd>&gt;</kbd>. (See <a
  1312.      href="https://wiki.archlinux.org/title/Apple_Keyboard#%3C_and_%3E_have_changed_place_with_^_and_%C2%B0_(or_@_and_#,_or_%60_and_~)">aw:
  1313.      Apple Keyboard</a>.)
  1314.      </p>
  1315.      <p>
  1316.      Then run <code>timedatectl set-ntp true</code>, connect to the internet and
  1317.      update.
  1318.      </p>
  1319.      <h2 id="partitioning"><a class="anchor"
  1320.      href="#partitioning"></a>Partitioning</h2>
  1321.      <p>
  1322.      Apple <a
  1323.      href="https://developer.apple.com/library/archive/technotes/tn2166/_index.html">recommend</a>
  1324.      leaving a 128 MiB gap between partitions.
  1325.      </p>
  1326.      <blockquote
  1327.      cite="https://developer.apple.com/library/archive/technotes/tn2166/_index.html">
  1328.      We leave free space after each partition to make it easier for future system
  1329.      software to manipulate the partition map in ways that we can’t anticipate
  1330.      currently.
  1331.      </blockquote>
  1332.      <p>
  1333.      It’s debatable whether this is worthwhile.
  1334.      </p>
  1335.      <p>
  1336.      With <code>cgdisk</code>:
  1337.      </p>
  1338.      <ul>
  1339.      <li>delete the empty Apple partition;</li>
  1340.      <li>make a small future HFS/HFS+ (<code>af00</code>) partition starting with
  1341.      <code>+128M</code>;</li>
  1342.      <li>make a large LVM (<code>8e00</code>) partition for the rest of the
  1343.      disk;</li>
  1344.      <li>write.</li>
  1345.      </ul>
  1346.      <p>
  1347.      It should look like this in the end.
  1348.      </p>
  1349.      <pre>
  1350. Part. #     Size        Partition Type            Partition Name
  1351. ----------------------------------------------------------------
  1352.            3.0 KiB     free space
  1353.   1        200.0 MiB   EFI System                EFI System Partition
  1354.   2        45.0 GiB    Apple Core Storage        Customer
  1355.   3        619.9 MiB   Recovery HD               Recovery HD
  1356.            128.0 MiB   free space
  1357.   4        10.0 GiB    Apple HFS/HFS+            hfs
  1358.   5        177.8 GiB   Linux LVM                 archlinux
  1359. </pre>
  1360.      <h2 id="encrypting"><a class="anchor" href="#encrypting"></a>Encrypting</h2>
  1361.      <p>
  1362.      We’re going to encrypt <code>/dev/sdc5</code> with <a
  1363.      href="https://wiki.archlinux.org/title/Dm-crypt/Encrypting_an_entire_system#LVM_on_LUKS">LVM
  1364.      on LUKS</a>. These are approximately the results I got from <code>cryptsetup
  1365.      benchmark</code>.
  1366.      </p>
  1367.      <pre class="root-shell">
  1368. cryptsetup benchmark
  1369. # Tests are approximate using memory only (no storage IO).
  1370. PBKDF2-sha1      1213629 iterations per second for 256-bit key
  1371. PBKDF2-sha256    1354749 iterations per second for 256-bit key
  1372. PBKDF2-sha512    1100289 iterations per second for 256-bit key
  1373. PBKDF2-ripemd160  897753 iterations per second for 256-bit key
  1374. PBKDF2-whirlpool  666185 iterations per second for 256-bit key
  1375. #  Algorithm | Key |  Encryption |  Decryption
  1376.     aes-cbc   128b   601.2 MiB/s  2589.5 MiB/s
  1377. serpent-cbc   128b    78.5 MiB/s   511.4 MiB/s
  1378. twofish-cbc   128b   178.7 MiB/s   328.4 MiB/s
  1379.     aes-cbc   256b   443.6 MiB/s  1964.6 MiB/s
  1380. serpent-cbc   256b    79.6 MiB/s   511.2 MiB/s
  1381. twofish-cbc   256b   180.1 MiB/s   328.4 MiB/s
  1382.     aes-xts   256b  2194.5 MiB/s  2182.6 MiB/s
  1383. serpent-xts   256b   492.9 MiB/s   496.6 MiB/s
  1384. twofish-xts   256b   319.2 MiB/s   324.4 MiB/s
  1385.     aes-xts   512b  1703.8 MiB/s  1689.3 MiB/s
  1386. serpent-xts   512b   513.7 MiB/s   496.8 MiB/s
  1387. twofish-xts   512b   285.3 MiB/s   324.8 MiB/s
  1388. </pre>
  1389.      <p>
  1390.      First we must <a
  1391.      href="https://gitlab.com/cryptsetup/cryptsetup/-/wiki_pages/FrequentlyAskedQuestions#5-security-aspects">fill
  1392.      the partition</a> with random-looking data. There is a clever way to do this
  1393.      with dm-crypt.
  1394.      </p>
  1395.      <pre>
  1396. <span class="root-shell">cryptsetup open --type plain /dev/sdc5 container --key-file /dev/random</span>
  1397. <span class="root-shell">dd if=/dev/zero of=/dev/mapper/container bs=1M status=progress</span>
  1398. <span class="root-shell">cryptsetup close container</span>
  1399. </pre>
  1400.      <p>
  1401.      This took about 700 seconds. Next, encrypt the partition and put a logical
  1402.      volume on it.
  1403.      </p>
  1404.      <pre>
  1405. <span class="root-shell">cryptsetup -v --cipher aes-xts-plain64 --key-size 256 --hash sha256 --iter-time 2000 --use-urandom --verify-password luksFormat /dev/sdc5</span>
  1406. <span class="root-shell">cryptsetup luksOpen /dev/sdc5 lvm</span>
  1407. <span class="root-shell">pvcreate /dev/mapper/lvm</span>
  1408. <span class="root-shell">vgcreate vgcrypt /dev/mapper/lvm</span>
  1409. <span class="root-shell">lvcreate --extents 100%FREE -n root vgcrypt</span>
  1410. <span class="root-shell">mkfs.ext4 /dev/mapper/vgcrypt-root</span>
  1411. </pre>
  1412.      <p>
  1413.      Now we can mount the volume with
  1414.      </p>
  1415.      <pre>
  1416. <span class="root-shell">mount /dev/mapper/vgcrypt-root /mnt</span>
  1417. <span class="root-shell">mkdir /mnt/boot</span>
  1418. <span class="root-shell">mount /dev/sdc1 /mnt/boot</span>
  1419. </pre>
  1420.      <p>
  1421.      where <code>/dev/sdc1</code> is the EFI system partition.
  1422.      </p>
  1423.      <h2 id="chrooting"><a class="anchor" href="#chrooting"></a>Chrooting</h2>
  1424.      <p>
  1425.      The rest follows the <a
  1426.      href="https://wiki.archlinux.org/title/Installation_guide">wiki</a> quite
  1427.      closely.
  1428.      </p>
  1429.      <pre>
  1430. <span class="root-shell">pacstrap -i /mnt base base-devel</span>
  1431. <span class="root-shell">genfstab -U /mnt &gt;&gt; /mnt/etc/fstab</span>
  1432. </pre>
  1433.      <p>
  1434.      The <code>-U</code> flag tells <code>genfstab</code> to use UUIDs. Now would be
  1435.      a good time to edit the <code>fstab</code> to add the <em>discard</em> option
  1436.      for TRIM, but let’s hold off on that.
  1437.      </p>
  1438.      <pre>
  1439. <span class="root-shell">arch-chroot /mnt /bin/bash</span>
  1440. <span class="root-shell">echo <em>xyza</em> &gt; /etc/hostname</span>
  1441. </pre>
  1442.      <p>
  1443.      Edit <code>/etc/locale.gen</code> and uncomment <code>#en_IE.UTF-8</code>.
  1444.      </p>
  1445.      <pre>
  1446. <span class="root-shell">locale-gen</span>
  1447. <span class="root-shell">echo "LANG=en_IE.UTF-8" &gt; /etc/locale.conf</span>
  1448. <span class="root-shell">ln -s /usr/share/zoneinfo/Europe/Dublin /etc/localtime</span>
  1449. </pre>
  1450.      <p>
  1451.      Edit the <code>/etc/mkinitcpio.conf</code> <code>MODULES</code> and
  1452.      <code>HOOKS</code>
  1453.      </p>
  1454.      <pre>
  1455. MODULES="i915"    # for a smoother boot screen
  1456. HOOKS="base udev consolefont autodetect modconf block keymap keyboard encrypt lvm2 filesystems fsck"
  1457. </pre>
  1458.      <p>
  1459.      and build the initial ramdisk with <code>mkinitcpio -p linux</code>.
  1460.      </p>
  1461.      <p>
  1462.      Now set up the bootloader.
  1463.      </p>
  1464.      <pre>
  1465. <span class="root-shell">mkdir -p /boot/loader/entries</span>
  1466. <span class="root-shell">vi /boot/loader/loader.conf</span>
  1467. </pre>
  1468.      <p>
  1469.      and add
  1470.      </p>
  1471.      <pre>
  1472. default arch.conf
  1473. timeout 3
  1474. </pre>
  1475.      <p>
  1476.      Check that <code>dev/sdc1</code> is mounted properly with <code>findmnt
  1477.      /boot</code>. Then make and edit <code>/boot/loader/entries/arch.conf</code>.
  1478.      </p>
  1479.      <pre>
  1480. title       Arch Linux
  1481. linux       /vmlinuz-linux
  1482. initrd      /initramfs-linux.img
  1483. options     cryptdevice=/dev/sda5:vgcrypt:allow-discards root=/dev/mapper/vgcrypt-root rw
  1484. </pre>
  1485.      <p>
  1486.      Note that there are <a
  1487.      href="https://wiki.archlinux.org/title/Dm-crypt/Specialties#Discard.2FTRIM_support_for_solid_state_drives_.28SSD.29">security
  1488.      implications</a> with enabling TRIM/discards.
  1489.      </p>
  1490.      <pre>
  1491. <span class="root-shell">bootctl install</span>
  1492. <span class="root-shell">pacman -S iw wpa_supplicant dialog</span>
  1493. <span class="root-shell">passwd</span>
  1494. </pre>
  1495.      <p>
  1496.      Shutdown, remove the installation media and reboot.
  1497.      </p>
  1498.      <h2 id="configuration"><a class="anchor"
  1499.      href="#configuration"></a>Configuration</h2>
  1500.      <p>
  1501.      Let’s make some swap space.
  1502.      </p>
  1503.      <pre>
  1504. <span class="root-shell">fallocate -l 8G /swapfile</span>
  1505. <span class="root-shell">chmod 600 /swapfile</span>
  1506. <span class="root-shell">mkswap swapfile</span>
  1507. <span class="root-shell">swapon /swapfile</span>
  1508. </pre>
  1509.      <p>
  1510.      Check that this worked with <code>free -h</code> or <code>swapon --show</code>
  1511.      and add
  1512.      </p>
  1513.      <pre>
  1514. /swapfile none swap defaults 0 0
  1515. </pre>
  1516.      <p>
  1517.      to the <code>fstab</code>.
  1518.      </p>
  1519.      <p>
  1520.      For user management, make a new user and add them to the admin group.
  1521.      </p>
  1522.      <pre>
  1523. <span class="root-shell">useradd -m -G wheel -s /bin/bash <em>fionn</em></span>
  1524. <span class="root-shell">passwd <em>fionn</em></span>
  1525. </pre>
  1526.      <p>
  1527.      Then run <code>visudo</code>, uncomment <code># %wheel ALL=(ALL) ALL</code>, log
  1528.      out and then back in again as a regular user.
  1529.      </p>
  1530.      <pre class="shell">
  1531. sudo pacman -Syu bash-completion pkgfile
  1532. </pre>
  1533.      <p>
  1534.      Now would be a good time to import <a
  1535.      href="https://github.com/fionn/.dotfiles">.dotfiles</a>.
  1536.      </p>
  1537.      <p>
  1538.      To get <code>netctl</code> to automatically connect to networks, install
  1539.      <code>wpa_actiond</code> and enable <code>netctl-auto@wlp3s0.service</code>.
  1540.      </p>
  1541.      <p>
  1542.      The console font is <small><em>very small</em></small>. Install
  1543.      <code>terminus-font</code> and add the line
  1544.      </p>
  1545.      <pre>
  1546. FONT=ter-124n
  1547. </pre>
  1548.      <p>
  1549.      to <code>/etc/vconsole.conf</code>.
  1550.      </p>
  1551.      <h2 id="x11"><a class="anchor" href="#x11"></a>X11</h2>
  1552.      <p>
  1553.      <code>xf86-video-intel</code> seems to be necessary to avoid screen tearing
  1554.      (<code>xf86-video-modesetting</code> doesn’t seem to help here). Edit
  1555.      <code>/etc/X11/xorg.conf.d/20-intel.conf</code>.
  1556.      </p>
  1557.      <pre>
  1558. Section "Device"
  1559.   Identifier  "Intel Graphics"
  1560.   Driver      "intel"
  1561.   Option      "TearFree" "true"
  1562. EndSection
  1563. </pre>
  1564.      <p>
  1565.      There’s a lot of talk about <a
  1566.      href="https://github.com/BlueDragonX/xf86-input-mtrack"><code>xf86-input-mtrack</code></a>,
  1567.      but I find synaptics to be just fine. Here’s my <code>/etc/X11/xorg.conf.d/<a
  1568.      href="50-synaptics.conf">50-synaptics.conf</a></code>. (<code>1</code>,
  1569.      <code>2</code> and <code>3</code> correspond to left, middle and right.)
  1570.      </p>
  1571.      <pre>
  1572. # Example xorg.conf.d snippet that assigns the touchpad driver
  1573. # to all touchpads. See xorg.conf.d(5) for more information on
  1574. # InputClass.
  1575. # DO NOT EDIT THIS FILE, your distribution will likely overwrite
  1576. # it when updating. Copy (and rename) this file into
  1577. # /etc/X11/xorg.conf.d first.
  1578. # Additional options may be added in the form of
  1579. #   Option "OptionName" "value"
  1580. #
  1581. Section "InputClass"
  1582.        Identifier "touchpad catchall"
  1583.        Driver "synaptics"
  1584.        MatchIsTouchpad "on"
  1585.        Option "TapButton1" "0"   # 1, 2, 3 for tapping
  1586.        Option "TapButton2" "0"
  1587.        Option "TapButton3" "0"
  1588. # Custom options
  1589.        Option "ClickFinger2" "2"
  1590.        Option "ClickFinger3" "3"
  1591.        Option "HorizTwoFingerScroll" "1"
  1592.        Option "VertEdgeScroll" "1"
  1593.        Option "PalmDetect" "1"
  1594.        Option "RBCornerButton" "3"
  1595. # This option is recommend on all Linux systems using evdev, but cannot be
  1596. # enabled by default. See the following link for details:
  1597. # https://who-t.blogspot.com/2010/11/how-to-ignore-configuration-errors.html
  1598.        MatchDevicePath "/dev/input/event*"
  1599. EndSection
  1600.  
  1601. Section "InputClass"
  1602.        Identifier "touchpad ignore duplicates"
  1603.        MatchIsTouchpad "on"
  1604.        MatchOS "Linux"
  1605.        MatchDevicePath "/dev/input/mouse*"
  1606.        Option "Ignore" "on"
  1607. EndSection
  1608.  
  1609. # This option enables the bottom right corner to be a right button on clickpads
  1610. # and the right and middle top areas to be right / middle buttons on clickpads
  1611. # with a top button area.
  1612. # This option is only interpreted by clickpads.
  1613. Section "InputClass"
  1614.        Identifier "Default clickpad buttons"
  1615.        MatchDriver "synaptics"
  1616.        Option "SoftButtonAreas" "50% 0 82% 0 0 0 0 0"
  1617.        Option "SecondarySoftButtonAreas" "58% 0 0 15% 42% 58% 0 15%"
  1618. EndSection
  1619.  
  1620. # This option disables software buttons on Apple touchpads.
  1621. # This option is only interpreted by clickpads.
  1622. Section "InputClass"
  1623.        Identifier "Disable clickpad buttons on Apple touchpads"
  1624.        MatchProduct "Apple|bcm5974"
  1625.        MatchDriver "synaptics"
  1626.        #Option "SoftButtonAreas" "0 0 0 0 0 0 0 0"
  1627. EndSection
  1628. </pre>
  1629.      <p>
  1630.      To swap the function and media keys, edit
  1631.      <code>/etc/modprobe.d/hid_apple.conf</code>.
  1632.      </p>
  1633.      <pre>
  1634. options hid_apple iso_layout=0   # for the key swap earlier
  1635. options hid_apple fnmode=2
  1636. </pre>
  1637.      <p>
  1638.      To map the media keys to the hardware, install <code>xorg-xbacklight</code>,
  1639.      <code>alsa-utils</code> and, from the AUR, <a
  1640.      href="https://aur.archlinux.org/packages/kbdlight/"><code>kbdlight</code></a>.
  1641.      Edit <code>/etc/modprobe.d/snd_hda_intel.conf</code>.
  1642.      </p>
  1643.      <pre>
  1644. options snd_hda_intel index=1,0
  1645. </pre>
  1646.      <p>
  1647.      Bind the keys in <code>~/.i3/config</code> with something like this.
  1648.      </p>
  1649.      <pre>
  1650. bindsym XF86KbdBrightnessUp exec --no-startup-id kbdlight up
  1651. </pre>
  1652.      <h2 id="lid"><a class="anchor" href="#lid"></a>Lid</h2>
  1653.      <p>
  1654.      Edit <code>/etc/systemd/logind.conf</code> and set
  1655.      <code>HandleLidSwitch=Ignore</code> to stop the laptop from suspending whenever
  1656.      the lid is closed.
  1657.      </p>
  1658.      <h2 id="mirrors"><a class="anchor" href="#mirrors"></a>Mirrors</h2>
  1659.      <p>
  1660.      Grab a new mirrorlist with
  1661.      </p>
  1662.      <pre>
  1663. <span class="shell">cd /etc/pacman.d</span>
  1664. <span class="shell">sudo mv mirrorlist mirrorlist.bkup</span>
  1665. <span class="shell">sudo wget <a href="https://www.archlinux.org/mirrorlist/?country=all">https://www.archlinux.org/mirrorlist/?country=all</a> -O mirrorlist</span>
  1666. </pre>
  1667.      <p>
  1668.      and uncomment a mirror.
  1669.      </p>
  1670.      <h2 id="trim"><a class="anchor" href="#trim"></a>TRIM</h2>
  1671.      <p>
  1672.      TRIM the filesystem.
  1673.      </p>
  1674.      <pre class="shell">
  1675. sudo fstrim -v /
  1676. /: 163.5 GiB (175549890560 bytes) trimmed
  1677. </pre>
  1678.      <p>
  1679.      Then enable <code>fstrim.timer</code> to periodically issue discards.
  1680.      </p>
  1681.      <h2 id="dpp"><a class="anchor" href="#dpp"></a>DPP</h2>
  1682.      <p>
  1683.      Put <code>xrandr --dpi 144</code> in <code>~/.xinitrc</code>.
  1684.      </p>
  1685.      <p>
  1686.      GTK3+ is supposed to pick up the system DPP settings, but it doesn’t for me. The
  1687.      solution is to set the font size to around 16 (using e.g.
  1688.      <code>lxappearance-gtk3</code>). For Firefox, set
  1689.      <code>layout.css.devPixelsPerPixel=1.4</code> in <code>about:config</code>.
  1690.      </p>
  1691.      <p>
  1692.      For QT to pick up on the GTK theme, install <code>adwaita-qt5</code> from the
  1693.      AUR. <em>Also export QT_STYLE_OVERRIDE=GTK+?</em>
  1694.      </p>
  1695.      ]]></content>
  1696.    <link href="https://www.maths.tcd.ie/~fionn/misc/macbook/"/>
  1697.    <summary>This is what I did to put Arch Linux on my MacBook Pro 12,1 (A1502, 2015) with dm-crypt (LVM on LUKS). Much of the start is taken from this blog post, but it’s reproduced here because of fear of link-rot. […]</summary>
  1698.    <published>2016-05-22T00:00:00+00:00</published>
  1699.  </entry>
  1700.  <entry>
  1701.    <id>https://www.maths.tcd.ie/~fionn/misc/alarmpi_tor/</id>
  1702.    <title>A Raspberry Pi Tor Relay</title>
  1703.    <updated>1970-01-01T00:00:00+00:00</updated>
  1704.    <author>
  1705.      <name>Fionn Fitzmaurice</name>
  1706.      <email>fionn@this.domain</email>
  1707.    </author>
  1708.    <content type="CDATA"><![CDATA[<p>
  1709.      Make an <code>alarmpi</code> directory, <code>cd</code> to it and follow the
  1710.      Arch Linux ARM <a
  1711.      href="https://archlinuxarm.org/platforms/armv7/broadcom/raspberry-pi-2">installation
  1712.      instructions</a>. But in step 5, instead of just <code>wget</code>ting the
  1713.      tarball, also do
  1714.      </p>
  1715.      <pre>
  1716. <span class="shell">wget <a href="https://archlinuxarm.org/os/ArchLinuxARM-rpi-armv7-latest.tar.gz.md5">https://archlinuxarm.org/os/ArchLinuxARM-rpi-armv7-latest.tar.gz.md5</a></span>
  1717. <span class="shell">wget <a href="https://archlinuxarm.org/os/ArchLinuxARM-rpi-armv7-latest.tar.gz.sig">https://archlinuxarm.org/os/ArchLinuxARM-rpi-armv7-latest.tar.gz.sig</a></span>
  1718. </pre>
  1719.      <p>
  1720.      (note that there’s some TLS-stripping redirection). Compare the <code>md5</code>
  1721.      hash (<code>md5sum -c</code>) and verify the signature by getting the Arch Linux
  1722.      ARM <a href="https://archlinuxarm.org/about/package-signing">package signing
  1723.      key</a> (<a
  1724.      href="https://pgp.circl.lu/pks/lookup?op=vindex&amp;fingerprint=on&amp;search=0x68B3537F39A313B3E574D06777193F152BDBE6A6"><code>0x77193F152BDBE6A6</code></a>).
  1725.      </p>
  1726.      <p>
  1727.      Once we’re in the Pi, the first thing to do is set up package signing by <a
  1728.      href="https://archlinuxarm.org/about/package-signing">following these
  1729.      instructions</a>.
  1730.      </p>
  1731.      <p>
  1732.      Then update and grab some useful packages.
  1733.      </p>
  1734.      <pre>
  1735. <span class="root-shell">pacman -Syu</span>
  1736. <span class="root-shell">pacman -S sudo vim bash-completion</span>
  1737. </pre>
  1738.      <p>
  1739.      Now it’s time for some user management. First enable root login over SSH
  1740.      (temporarily) by editing <code>/etc/ssh/sshd_config</code> and adding
  1741.      </p>
  1742.      <pre>
  1743. PermitRootLogin yes
  1744. </pre>
  1745.      <p>
  1746.      and then reloading the dæmon. Log out and then back in as root. This is so we
  1747.      can change the <code>alarm</code> username.
  1748.      </p>
  1749.      <pre>
  1750. <span class="root-shell">usermod -l <em>username</em> alarm</span>
  1751. <span class="root-shell">usermod -d /home/<em>username</em> -m <em>username</em></span>
  1752. </pre>
  1753.      <p>
  1754.      Disallow SSH root logins again and reload the dæmon.
  1755.      </p>
  1756.      <p>
  1757.      (This isn’t necessary if you have a keyboard and screen. We’re strictly headless
  1758.      here.)
  1759.      </p>
  1760.      <p>
  1761.      Run <code>visudo</code> and uncomment the line
  1762.      </p>
  1763.      <pre>
  1764. # %wheel ALL=(ALL) ALL
  1765. </pre>
  1766.      <p>
  1767.      to add the user to the sudoers file.
  1768.      </p>
  1769.      <p>
  1770.      Now would be a good time to change the passwords. Do
  1771.      </p>
  1772.      <pre>
  1773. <span class="root-shell">passwd root</span>
  1774. <span class="root-shell">passwd <em>username</em></span>
  1775. </pre>
  1776.      <p>
  1777.      and log back in as the user.
  1778.      </p>
  1779.      <p>
  1780.      Now that the system is taking shape, let’s do some customising before we get to
  1781.      Tor.
  1782.      </p>
  1783.      <p>
  1784.      To make things a bit friendlier, download your <a href="../vim/">Vim
  1785.      configuration</a>.
  1786.      </p>
  1787.      <p>
  1788.      Next up, set the <a href="https://wiki.archlinux.org/title/Locale">locale</a>
  1789.      and <a
  1790.      href="https://wiki.archlinux.org/title/System_time#Time_zone">timezone</a> stuff
  1791.      (see the <a
  1792.      href="https://wiki.archlinux.org/title/Installation_guide#Configure_the_system">installation
  1793.      guide</a>).
  1794.      </p>
  1795.      <pre class="root-shell">
  1796. localectl set-locale LANG=en_IE.UTF-8
  1797. </pre>
  1798.      <p>
  1799.      Change the hostname with
  1800.      </p>
  1801.      <pre class="root-shell">
  1802. hostnamectl set-hostname <em>hostname</em>
  1803. </pre>
  1804.      <p>
  1805.      and edit <code>/etc/hosts</code> and <a
  1806.      href="https://wiki.archlinux.org/title/Network_configuration#Set_the_hostname">add
  1807.      the hostname to the end</a>.
  1808.      </p>
  1809.      <p>
  1810.      OK, now let’s get Tor (and <code>arm</code>).
  1811.      </p>
  1812.      <pre class="shell">
  1813. sudo pacman -S tor arm
  1814. </pre>
  1815.      <p>
  1816.      Edit <code>/etc/tor/torrc</code> to make it a relay. There might be some
  1817.      port-forwarding to be done for the ORPort (9001) and DirPort (9030) as well as
  1818.      SocksPort (9050). Note that we don’t need to run Tor as a dæmon — systemd takes
  1819.      care of that.
  1820.      </p>
  1821.      <p>
  1822.      To get <code>arm</code> working we need to open up the control port, but it’s
  1823.      not safe to do so without some authentication. Run
  1824.      </p>
  1825.      <pre class="shell">
  1826. tor --hash-password <em>password</em>
  1827. </pre>
  1828.      <p>
  1829.      and paste the hash into the <code>HashedControlPassword</code> line. Then open
  1830.      up the control port on port 9051.
  1831.      </p>
  1832.      <p>
  1833.      Start Tor and check its status. If all seems well, enable it. Run
  1834.      </p>
  1835.      <pre class="shell">
  1836. sudo -u tor arm
  1837. </pre>
  1838.      <p>
  1839.      to see how things are going.
  1840.      </p>
  1841.      <p>
  1842.      <del>The last thing to do for Tor is sign up for the <a class="dead"
  1843.      title="https://weather.torproject.org/">weather reports</a>.</del>
  1844.      </p>
  1845.      <p>
  1846.      We’re done! But wait. Our relay is vulnerable. Let’s beef up the security by <a
  1847.      href="https://blog.bigdinosaur.org/securing-ssh-with-iptables/">securing SSH
  1848.      with iptables</a>. You can move old iptables around with
  1849.      <code>iptables-save</code> and <code>iptables-restore</code>, but don’t forget
  1850.      to <a
  1851.      href="https://wiki.archlinux.org/title/Iptables#Configuration_and_usage">make
  1852.      them persistent</a>.
  1853.      </p>
  1854.      <p>
  1855.      The only internet-facing services should be Tor and an SSH dæmon. There’s
  1856.      nothing else to do for Tor, but we can make SSH much more secure.
  1857.      </p>
  1858.      <p>
  1859.      First of all, copy the <a
  1860.      href="https://wiki.archlinux.org/title/SSH_keys">public key</a> over with
  1861.      </p>
  1862.      <pre class="shell">
  1863. ssh-copy-id -i ~/.ssh/id_ed25519.pub 192.168.0.<em>x</em>
  1864. </pre>
  1865.      <p>
  1866.      and check if it worked. Probably you’ll have to edit <code>.ssh/config</code> if
  1867.      you’re disallowing public key identification in general (<a
  1868.      href="https://words.filippo.io/ssh-whoami-filippo-io/">which you probably should
  1869.      be</a>).
  1870.      </p>
  1871.      <p>
  1872.      Now you can harden the server by enforcing public key authentication and <a
  1873.      href="https://stribika.github.io/2015/01/04/secure-secure-shell.html">choosing
  1874.      good algorithms</a>.
  1875.      </p>
  1876.      <p>
  1877.      Edit <code>/etc/motd</code> to get rid of the boilerplate. It could be nice to
  1878.      print the ED25519 fingerprint here.
  1879.      </p>
  1880.      <p>
  1881.      Finally, set up <a href="../ssh_hidden_service/">SSH as a hidden service</a> so
  1882.      you can SSH to it from anywhere and have a static onion URL and all that.
  1883.      </p>
  1884.      ]]></content>
  1885.    <link href="https://www.maths.tcd.ie/~fionn/misc/alarmpi_tor/"/>
  1886.    <summary>Make an alarmpi directory, cd to it and follow the Arch Linux ARM installation instructions. But in step 5, instead of just wgetting the tarball, also do […]</summary>
  1887.    <published>1970-01-01T00:00:00+00:00</published>
  1888.  </entry>
  1889.  <entry>
  1890.    <id>https://www.maths.tcd.ie/~fionn/misc/recover_data/</id>
  1891.    <title>Recovering Deleted Data</title>
  1892.    <updated>1970-01-01T00:00:00+00:00</updated>
  1893.    <author>
  1894.      <name>Fionn Fitzmaurice</name>
  1895.      <email>fionn@this.domain</email>
  1896.    </author>
  1897.    <content type="CDATA"><![CDATA[<p>
  1898.      Here’s what I did.
  1899.      </p>
  1900.      <br/>
  1901.      <pre class="shell">
  1902. cp <em>file</em> ..
  1903. </pre>
  1904.      <p>
  1905.      Well, I already had a file called <code><em>file</em></code> in the parent
  1906.      directory. Whoops!
  1907.      </p>
  1908.      <p>
  1909.      Here’s what I did to fix it.
  1910.      </p>
  1911.      <pre class="root-shell">
  1912. grep -a -b "<em>text in the deleted file</em>" /dev/sda3
  1913. 530159385076:<em>some text in the deleted file</em>
  1914.  
  1915. <span class="root-shell">dd if=/dev/sda3 count=8 skip=$(expr 530159385076 / 512 - 4)</span>
  1916. </pre>
  1917.      <p>
  1918.      <code>/dev/sda3</code> is my <code>/home</code> partition, so I’m grepping the
  1919.      hard drive directly. That’s what the <code>-a</code> flag is for — it looks at
  1920.      binary as if it’s text. The <code>-b</code> flag prints the byte offset, so we
  1921.      know where on the drive it found the match.
  1922.      </p>
  1923.      <p>
  1924.      Then we use <code>dd</code> to grab the data. <code>count=<em>n</em></code>
  1925.      takes <code><em>n</em></code> blocks (512 bytes by default, can be changed with
  1926.      <code>bs=<em>n</em></code>) and <code>skip=<em>n</em></code> skips
  1927.      <code><em>n</em></code> blocks in. Here I go back 4 blocks and take 8, which was
  1928.      enough in my case. When/if it works, add <code>of=file</code> to get the file
  1929.      back. It might need editing to remove some binary.
  1930.      </p>
  1931.      <p>
  1932.      An alternative is to give grep the <code>-C200</code> flag. This gives 200 lines
  1933.      before and after the string for context. Maybe you can avoid <code>dd</code>
  1934.      then.
  1935.      </p>
  1936.      <p>
  1937.      This should work in most cases, unless the filesystem has already allocated the
  1938.      space to another file. It obviously won’t work on encrypted discs, or if you
  1939.      used something like <code>shred</code>. It has worked for me one out of two
  1940.      times (the other time it borked my terminal), so YMMV.
  1941.      </p>
  1942.      <p>
  1943.      It can take a really long time.
  1944.      </p>
  1945.      ]]></content>
  1946.    <link href="https://www.maths.tcd.ie/~fionn/misc/recover_data/"/>
  1947.    <summary>Here’s what I did. […]</summary>
  1948.    <published>1970-01-01T00:00:00+00:00</published>
  1949.  </entry>
  1950.  <entry>
  1951.    <id>https://www.maths.tcd.ie/~fionn/misc/ssh_hidden_service/</id>
  1952.    <title>How to Set Up an SSH Server as a Hidden Service</title>
  1953.    <updated>1970-01-01T00:00:00+00:00</updated>
  1954.    <author>
  1955.      <name>Fionn Fitzmaurice</name>
  1956.      <email>fionn@this.domain</email>
  1957.    </author>
  1958.    <content type="CDATA"><![CDATA[<p>
  1959.      This article assumes you’ve got an SSH dæmon on your host machine running on the
  1960.      clearnet and you use <a href="https://ed25519.cr.yp.to/">Ed25519 keys</a>. If
  1961.      you haven’t already, make your server secure: use <a
  1962.      href="https://blog.bigdinosaur.org/securing-ssh-with-iptables/">iptables</a> (or
  1963.      something equivalent) and <a
  1964.      href="https://stribika.github.io/2015/01/04/secure-secure-shell.html">choose
  1965.      good algorithms</a>.
  1966.      </p>
  1967.      <h2>
  1968.      For the Host
  1969.      </h2>
  1970.      <p>
  1971.      Add the following to <code>/etc/tor/torrc</code>.
  1972.      </p>
  1973.      <pre>
  1974. HiddenServiceDir /var/lib/tor/ssh/
  1975. HiddenServicePort 22 127.0.0.1:22
  1976. HiddenServiceAuthorizeClient stealth <em>clientname</em>
  1977. </pre>
  1978.      <p>
  1979.      The first two lines are obvious. The last line isn’t strictly necessary, but
  1980.      adds a fair bit of security by only allowing specified clients to connect. Read
  1981.      the <a
  1982.      href="https://2019.www.torproject.org/docs/tor-manual.html#HiddenServiceAuthorizeClient">man
  1983.      page entry</a>.
  1984.      </p>
  1985.      <p>
  1986.      Reload Tor and open
  1987.      <code>/var/lib<wbr>/tor<wbr>/ssh<wbr>/hostname</wbr></wbr></wbr></code>. It
  1988.      should look like this.
  1989.      </p>
  1990.      <pre>
  1991. <em>hostaddress</em>.onion <em>authcookie</em> # client: <em>clientname</em>
  1992. </pre>
  1993.      <p>
  1994.      That’s it.
  1995.      </p>
  1996.      <h2>
  1997.      For the Client
  1998.      </h2>
  1999.      <p>
  2000.      Now add
  2001.      </p>
  2002.      <pre>
  2003. HidServAuth <em>hostaddress</em>.onion <em>authcookie</em>
  2004. </pre>
  2005.      <p>
  2006.      to your local <code>/etc/tor/torrc</code> file (i.e. the contents of the
  2007.      <code>hostname</code> file becomes the value of <code>HidServAuth</code>). This
  2008.      is only relevant if you used
  2009.      <code>HiddenService<wbr>AuthorizeClient</wbr></code>. Again, read the <a
  2010.      href="https://2019.www.torproject.org/docs/tor-manual.html#HidServAuth">man page
  2011.      entry</a>.
  2012.      </p>
  2013.      <p>
  2014.      We can now check if this all worked. But wait! SSH mitigates man-in-the-middle
  2015.      attacks by displaying a fingerprint of its host key for you to verify. Before
  2016.      you connect over Tor, you should get a copy of this fingerprint to compare.
  2017.      </p>
  2018.      <pre class="shell">
  2019. ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
  2020. </pre>
  2021.      <p>
  2022.      It’s important to do this before you log in over Tor, but you can check after
  2023.      the fact by looking for the public key in <code>~/.ssh/known_hosts</code> (if
  2024.      you don’t obfuscate that file). It should obviously be the same over Tor and the
  2025.      clearnet.
  2026.      </p>
  2027.      <p>
  2028.      OK, let’s connect. Run
  2029.      </p>
  2030.      <pre class="shell">
  2031. torify ssh -i ~/.ssh/id_ed25519 <em>username</em>@<em>hostaddress</em>.onion
  2032. </pre>
  2033.      <p>
  2034.      and make sure the fingerprint matches what you expect.
  2035.      </p>
  2036.      <p>
  2037.      If this worked, we just need to streamline the process. Let’s edit
  2038.      <code>~/.ssh/config</code>. First, we need to get netcat to proxy SSH traffic.
  2039.      I’m using <code>openbsd-netcat</code>, the syntax is slightly different for
  2040.      <code>gnu-netcat</code>.
  2041.      </p>
  2042.      <pre>
  2043. Host <em>hostname</em>
  2044.    HostName <em>hostaddress</em>.onion
  2045.    Port 22
  2046.    User <em>username</em>
  2047.    PubkeyAuthentication yes
  2048.    IdentityFile ~/.ssh/id_ed25519
  2049.    VerifyHostKeyDNS no
  2050.    ProxyCommand nc -X 5 -x localhost:9050 %h %p
  2051. </pre>
  2052.      <ul>
  2053.      <li><code>VerifyHostKeyDNS no</code> is there to avoid a DNS leak. This is the
  2054.      default anyway, but DNS leaking is bad and you should make sure.</li>
  2055.      <li><code>ProxyCommand nc -X 5 -x localhost:9050 %h %p</code> does the work of
  2056.      <code>torify</code>. <code>-X 5</code> tells netcat to use SOCKS v5,
  2057.      <code>-x</code> sets the proxy address and port. <code>%h</code> is replaced by
  2058.      the value of <code>HostName</code> and <code>%p</code> by the value of
  2059.      <code>Port</code> (or else is just set to 22). This assumes Tor is using port
  2060.      9050, but it sometimes uses 9150 (if you’re using the TBB) — try both or check
  2061.      the value of <code>TorPort</code> in <code>/etc/tor/torsocks.conf</code>.</li>
  2062.      <li>You could also put the Tor-specific options under <code>Host
  2063.      *.onion</code>.</li>
  2064.      </ul>
  2065.      <h2>
  2066.      Finished
  2067.      </h2>
  2068.      <p>
  2069.      Now you can just run
  2070.      </p>
  2071.      <pre class="shell">
  2072. ssh <em>hostname</em>
  2073. </pre>
  2074.      <p>
  2075.      to connect to your server over Tor.
  2076.      </p>
  2077.      <p>
  2078.      Some other things:
  2079.      </p>
  2080.      <ul>
  2081.      <li>You can have as many hidden services as you like on the same machine.</li>
  2082.      <li>Use <a href="https://github.com/katmagic/Shallot">Shallot</a>, <a
  2083.      href="https://github.com/lachesis/scallion">Scallion</a>, etc. to generate
  2084.      vanity <code>.onion</code> addresses, if you’re into that kind of thing.</li>
  2085.      <li>Change the port for a bit of extra security through obscurity. You could
  2086.      also try <a href="https://wiki.archlinux.org/index.php/Port_knocking">port
  2087.      knocking</a>.</li>
  2088.      <li>If you’re running your hidden service on a relay, this will <a
  2089.      href="https://trac.torproject.org/projects/tor/ticket/8742">compromise your
  2090.      anonymity</a>. The same holds if your hidden service is also serving something
  2091.      on the clearnet.</li>
  2092.      </ul>
  2093.      ]]></content>
  2094.    <link href="https://www.maths.tcd.ie/~fionn/misc/ssh_hidden_service/"/>
  2095.    <summary>This article assumes you’ve got an SSH dæmon on your host machine running on the clearnet and you use Ed25519 keys. If you haven’t already, make your server secure: use iptables (or something equivalent) and choose good algorithms. […]</summary>
  2096.    <published>1970-01-01T00:00:00+00:00</published>
  2097.  </entry>
  2098.  <entry>
  2099.    <id>https://www.maths.tcd.ie/~fionn/misc/mount_encrypted_volume/</id>
  2100.    <title>Mounting an Encrypted LUKS Volume</title>
  2101.    <updated>1970-01-01T00:00:00+00:00</updated>
  2102.    <author>
  2103.      <name>Fionn Fitzmaurice</name>
  2104.      <email>fionn@this.domain</email>
  2105.    </author>
  2106.    <content type="CDATA"><![CDATA[<p>
  2107.      It’s really easy. Let’s assume <code>sdb2</code> is the encrypted LUKS device
  2108.      (because it is for me). <code>lsblk</code> shows the tree as this.
  2109.      </p>
  2110.      <pre>
  2111. sdb               8:16   1    29G  0 disk
  2112. ├─sdb1            8:17   1   2.5G  0 part
  2113. └─sdb2            8:18   1  26.5G  0 part
  2114. </pre>
  2115.      <p>
  2116.      Open the LUKS container with
  2117.      </p>
  2118.      <pre class="root-shell">
  2119. cryptsetup open /dev/sdb2 <em>luks_volume</em>
  2120. </pre>
  2121.      <p>
  2122.      (where <code><em>luks_volume</em></code> is the unimaginative name of the
  2123.      container).
  2124.      </p>
  2125.      <p>
  2126.      Now <code>lsblk</code> should show something like
  2127.      </p>
  2128.      <pre>
  2129. sdb               8:16   1    29G  0 disk
  2130. ├─sdb1            8:17   1   2.5G  0 part
  2131. └─sdb2            8:18   1  26.5G  0 part
  2132.  └─<em>luks_volume</em> 254:0    0  26.5G  0 crypt
  2133. </pre>
  2134.      <p>
  2135.      and we just have to mount it.
  2136.      </p>
  2137.      <pre>
  2138. <span class="root-shell">mkdir /mnt/<em>secrets</em>/</span>
  2139. <span class="root-shell">mount /dev/mapper/<em>luks_volume</em> /mnt/<em>secrets</em>/</span>
  2140. </pre>
  2141.      <p>
  2142.      That’s it. When done,
  2143.      </p>
  2144.      <pre>
  2145. <span class="root-shell">umount /mnt/<em>secrets</em></span>
  2146. <span class="root-shell">cryptsetup close <em>luks_volume</em></span>
  2147. <span class="root-shell">rm -r /mnt/<em>secrets</em>/</span>
  2148. </pre>
  2149.      <p>
  2150.      to remove the mapping and mount point and clear the key from memory.
  2151.      </p>
  2152.      ]]></content>
  2153.    <link href="https://www.maths.tcd.ie/~fionn/misc/mount_encrypted_volume/"/>
  2154.    <summary>It’s really easy. Let’s assume sdb2 is the encrypted LUKS device (because it is for me). lsblk shows the tree as this. […]</summary>
  2155.    <published>1970-01-01T00:00:00+00:00</published>
  2156.  </entry>
  2157. </feed>
  2158.  
Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda