aboutsummaryrefslogtreecommitdiff
path: root/content/posts
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2026-03-28 00:22:08 -0400
committerPaul Duncan <pabs@pablotron.org>2026-03-28 00:22:08 -0400
commit6e189ac3ffe2827e9625ae8b9c6df709d12b53a5 (patch)
tree35d5700fce0b80b71ed019e646000a80d1e42478 /content/posts
parent24d8775083264e5075cea439382a6c574d7ab14f (diff)
downloadpablotron.org-6e189ac3ffe2827e9625ae8b9c6df709d12b53a5.tar.xz
pablotron.org-6e189ac3ffe2827e9625ae8b9c6df709d12b53a5.zip
content/posts: add montgomerys-ladder draft and forgejo-setup-notes draft
Diffstat (limited to 'content/posts')
-rw-r--r--content/posts/2024-09-09-montgomerys-ladder.md96
-rw-r--r--content/posts/2026-03-09-forgejo-setup-notes.md34
2 files changed, 130 insertions, 0 deletions
diff --git a/content/posts/2024-09-09-montgomerys-ladder.md b/content/posts/2024-09-09-montgomerys-ladder.md
new file mode 100644
index 0000000..9ff976e
--- /dev/null
+++ b/content/posts/2024-09-09-montgomerys-ladder.md
@@ -0,0 +1,96 @@
+---
+slug: montgomerys-ladder
+title: "Montgomery's Ladder"
+date: "2024-09-09T02:00:29-04:00"
+draft: true
+---
+
+In response to a question in the comments of an [article][] I posted the
+comment below.
+
+----
+
+
+Short answer: To protect against timing side-channel attacks, the
+implementation should use a constant-time version of [Montgomery's
+ladder][montgomery's ladder].
+
+Longer answer...
+
+Definitions:
+
+- Inversion: a{{< sup "-1" >}}. Calculate the number *b* such that a * b = 1
+- Modular Inversion: a{{< sup "-1" >}} mod p. Calculate the number *b* such that a * b = 1 (mod p).
+
+
+From [Fermat's little theorem][], we know that if *p* is prime, then
+a{{< sup "p-1" >}} = 1 (mod p). Doing a bit of arithmetic:
+
+a{{< sup "p-1" >}} = 1 (mod p) \
+a * a{{< sup "p-2" >}} = 1 (mod p)
+
+So a{{< sup "p-2" >}} (mod p) is the multiplicative inverse of *a*, modulo
+*p*.
+
+**Example:** Calculate 2{{< sup "-1" >}} mod 5
+
+= 2{{< sup "-1" >}} mod 5 \
+= 2{{< sup "5-2" >}} mod 5 \
+= 2{{< sup "3" >}} mod 5 \
+= 8 mod 5 \
+= 3
+
+Check result by verifying a * a{{< sup "-1" >}} = 1 (mod 5):
+
+= 2 * 3 mod 5 \
+= 6 mod 5 \
+= 1
+
+The numbers used in cryptography are extremely large. For example, the
+primes for [Ed25519][] and [Poly1305][] are 2{{< sup "255" >}}-19 and
+2{{< sup "130" >}}-5, respectively ([djb][] naming :D). To do modular
+exponentation with large numbers you use a technique called
+[exponentation by squaring][].
+
+A common method of exponentation by squaring is [Montgomery's ladder][],
+but it is not constant-time. You can make Montgomery's ladder
+constant-time by changing the contents of the loop in Montgomery's
+ladder from this:
+
+> if n{{< sub "i" >}} = 0 then \
+> &nbsp;&nbsp;&nbsp;&nbsp;x{{< sub "2" >}} = x{{< sub "1" >}} * x{{< sub "2" >}}; x{{< sub "1" >}} = x{{< sub "1" >}}{{< sup "2" >}} \
+> else \
+> &nbsp;&nbsp;&nbsp;&nbsp;x{{< sub "1" >}} = x{{< sub "1" >}} * x{{< sub "2" >}}; x{{< sub "2" >}} = x{{< sub "2" >}}{{< sup "2" >}} \
+> end
+
+
+To something like this:
+
+> a = x{{< sub "1" >}} * x{{< sub "2" >}} \
+> b = x{{< sub "1" >}}{{< sup "2" >}} \
+> c = x{{< sub "2" >}}{{< sup "2" >}} \
+> d = is\_non\_zero(n{{< sub "i" >}})
+>
+> swap(x{{< sub "2" >}}, a, !d) \
+> swap(x{{< sub "1" >}}, b, !d) \
+> swap(x{{< sub "1" >}}, a, d) \
+> swap(x{{< sub "2" >}}, c, d)
+
+
+Where `swap()` is a constant-time function that swaps the values of the
+first two arguments if the third argument is true and does nothing if
+the third argument is false.
+
+Usually `swap()` is implemented with careful bitmasking to prevent
+overeager compilers from "optimizing" it.
+
+[article]: https://arstechnica.com/security/2024/09/yubikeys-are-vulnerable-to-cloning-attacks-thanks-to-newly-discovered-side-channel/
+[comment]: https://arstechnica.com/security/2024/09/yubikeys-are-vulnerable-to-cloning-attacks-thanks-to-newly-discovered-side-channel/?comments=1&comments-page=4
+[montgomery's ladder]: https://en.wikipedia.org/wiki/Exponentiation_by_squaring#Montgomery%27s_ladder_technique
+[fermat's little theorem]: https://en.wikipedia.org/wiki/Fermat%27s_little_theorem
+[ed25519]: https://en.wikipedia.org/wiki/EdDSA
+ "Edwards-curve Digital Signature Algorithm (EdDSA)"
+[poly1305]: https://en.wikipedia.org/wiki/Poly1305
+[exponentation by squaring]: https://en.wikipedia.org/wiki/Exponentiation_by_squaring
+[djb]: https://en.wikipedia.org/wiki/Daniel_J._Bernstein
+ "Daniel J. Bernstein"
diff --git a/content/posts/2026-03-09-forgejo-setup-notes.md b/content/posts/2026-03-09-forgejo-setup-notes.md
new file mode 100644
index 0000000..a0f3d6c
--- /dev/null
+++ b/content/posts/2026-03-09-forgejo-setup-notes.md
@@ -0,0 +1,34 @@
+---
+slug: forgejo-setup-notes
+title: "Forgejo Setup Notes"
+date: "2026-03-09T03:15:27-04:00"
+draft: true
+---
+
+pros:
+- great UI
+- most of the stuff i really care about, except gists
+- easier to set up than gitlab
+- much faster than gitlab
+- used by codeberg.org
+
+cons:
+- no gists
+- finicky runner setup
+- instructions are good, not great
+
+other:
+
+- see gist for notes about forgejo, and podman command
+- rootless podman runners on odroid n2l w/armbian, pi5, and
+ debian
+- runner running in rootless podman as runner user
+ - note about podman socket and enable-linger
+ - systemd service (plus config override)
+ - custom config to enable host networking
+ - armbian: install nft
+ - ubuntu-latest label (use ubuntu-act)
+- TODO: see notes/{pi,k3,x1}.txt
+- TODO: actions/cache <https://code.forgejo.org/actions/cache>
+- runner multi-connect:
+ <https://forgejo.org/2026-02-monthly-report/#forgejo-runner-v1270>