Filippo Valsorda
banner
filippo.abyssdomain.expert
Filippo Valsorda
@filippo.abyssdomain.expert
RC F'13, F2'17
Cryptogopher / Go cryptography maintainer
Professional open source maintainer
https://filippo.io / https://github.com/FiloSottile
https://mkcert.dev / https://age-encryption.org
https://sunlight.dev / https://filippo.io/newsletter
MacWhisper just transcribed a video with Parakeet v3 at 66.2x realtime on my 2022 MacBook Air.

I know technology gets better but... excuse me? 66.2x locally on a laptop!?

For context, when I bought this laptop, OpenAI's Whisper didn't exist yet.
November 18, 2025 at 8:47 PM
The IETF/CFRG HPKE post-quantum hybrid KEMs ended up specified over four documents.

I found it difficult to chase down definitions, disambiguate overlapping terms, ignore irrelevant alternatives, and cut through abstraction layers, so I wrote a condensed spec.

It's 235 lines. filippo.io/hpke-pq
November 16, 2025 at 7:31 PM
The Italian equivalent of the IRS sent me one paragraph of text (to tell me my audit passed!).

It arrived as an email with a .eml attachment which in turn has a .p7m attachment, which contains a .pdf file.
November 13, 2025 at 2:13 PM
Reposted by Filippo Valsorda
I gave an opening keynote at the FIDO Alliance’s “Authenticate” conference a few weeks ago! My goal was to explain, as clearly as I can, why passkeys are important and how we should use them to reduce the harm that passwords cause. [1/2]

YouTube link: www.youtube.com/watch?v=otOb...
Authenticate 2025 Keynote | Ricky Mondello, Apple | Get the Most Out of Passkeys
YouTube video by FIDO Alliance
www.youtube.com
November 7, 2025 at 1:51 PM
November 9, 2025 at 10:47 AM
Just killed the most annoying bug. I was doing

SELECT v FROM t WHERE k = ?

and then

UPDATE t SET v = ? WHERE k = ? AND v = ?

and the UPDATE was not applying?

Turns out I was storing nil → NULL, and then reading []byte(stmt.GetText("v")) → []byte(""). NULL and the empty BLOB don't compare equal.
internal/ctlog: fix SQLite LockBackend for nil values · FiloSottile/sunlight@96fb74b
When passing nil to Create or Replace, it was stored as NULL, but then was fetched as []byte("") by Fetch, which then didn't compare equal to NULL in Replace, making it always fail. ...
github.com
November 8, 2025 at 12:21 AM
Reposted by Filippo Valsorda
Yes, the only real Go targets are

linux/amd64
linux/arm64
darwin/arm64
windows/amd64

(“Things you should be very concerned about the crypto maintainer saying,” if you deploy to any others 😬)
November 7, 2025 at 11:21 PM
As a final side-product of the new Go ML-DSA implementation, here is a set of messages that when signed cause a statistically representative distribution of rejections, allowing accurate benchmarking. github.com/C2SP/CCTV/tr...

This is the same technique as words.filippo.io/rsa-keygen-b....
November 5, 2025 at 12:57 AM
Ok, honest question: should I get a LinkedIn account and cross-post technical posts there, too?

Are there actually useful professional conversations to be had, or people to be reached?

(I don’t anticipate needing it for work, just asking how it is as an audience essentially.)
November 4, 2025 at 7:27 PM
While implementing ML-DSA I found:

- broken NIST test vectors groups.google.com/a/list.nist....
- a bug in a formally verified Rust library (!!) github.com/cryspen/libc...
- missing test coverage in Wycheproof github.com/C2SP/wychepr...

I'd like the TODO to start getting shorter instead of longer.
Incorrect ML-DSA output on Alpine Linux and Ampere Altra · Issue #1220 · cryspen/libcrux
I tried using libcrux-ml-dsa v0.0.3 to generate accumulated test vectors for ML-DSA. Since I wanted to generate a 60M iteration test vector, I cross-compiled the code to run on an Alpine Linux serv...
github.com
November 3, 2025 at 10:21 PM
Sign44-8 494µ ± 74%
Verify44-8 109µ ± 1%
Keygen44-8 132µ ± 1%

± 74%... ah, right, ML-DSA signing does rejections (i.e. it tries again if the sig is not good a random no. of times).

We'll need deterministic benchmark targets that reject a statistically avg. number of times, like for RSA keygen.
Benchmarking RSA Key Generation
RSA key generation is conceptually simple, but extremely tricky. Even benchmarking involves math: we generated a stable but representative “average case” instead of using the ordinary statistical…
words.filippo.io
November 2, 2025 at 2:08 AM
I had a bug in my new ML-DSA implementation that caused Verify to reject all signatures. I gave up after half an hour. On a whim, I threw Claude Code at it. Surprisingly (to me!) it one-shotted it in 5 minutes.

A small case study of useful AI tasks that aren't generating code that requires review.
Claude Code Can Debug Low-level Cryptography
Surprisingly (to me) Claude Code debugged my new ML-DSA implementation faster than I would have, finding the non-obvious low-level issue that was making Verify fail.
words.filippo.io
November 1, 2025 at 6:26 PM
I am about to send a newsletter about how Claude Code debugged a very non-obvious issue in my new ML-DSA implementation.

I trust everyone will be very normal about this, right?
November 1, 2025 at 5:07 PM
Seeing AI turn my community first pro-copyright and now pro-defamation law is going to stick with me.
November 1, 2025 at 12:47 PM
Aaaaaaaaa I found the bug that was causing ML-DSA signature generation to spin forever.

Now I want to go back on the livestream recording to find how I generated the wrong constants. I blame Python.
October 30, 2025 at 12:33 PM
Reposted by Filippo Valsorda
So excited to finally share what we've been building at CUE Labs!

Proud to be on this mission with @mpvl.io, @myitcv.io, @rog.bsky.social, @hylomorphism.bsky.social, and @dominikdm.bsky.social.
A World Without Configuration Chaos: The Configuration Control Plane
Imagine a world where you can answer, with absolute confidence, the critical question: “What is the full impact of this change?” A world where configuration isn’t a source of fear, but a source of rel...
cue.dev
October 30, 2025 at 11:50 AM
If I ever interact with the CFRG again or try to rely on it to get actually useful work done, somebody please slap me.

I knew this. I managed to remember it for a year or so. And then.

They are now re-re-re-re-litigating the invisible strings to hash with hybrid KEMs. age PQ is blocked on that.
This is not the first time the CFRG slows things down to the point they are too late for most of their useful applications.

The PAKE selection process started in 2019 and the two winners (OPAQUE and CPace) are still drafts.

Hedged ECDSA has been a draft since 2019.

ristretto255 took five years.
October 30, 2025 at 10:21 AM
Reposted by Filippo Valsorda
New blog post: I'm Independently Verifying Go's Reproducible Builds: www.agwa.name/blog/post/ve...
I'm Independently Verifying Go's Reproducible Builds
Introducing Source Spotter, a Go Checksum Database auditor and Go toolchain reproducer
www.agwa.name
October 29, 2025 at 6:06 PM
This is the fantastic outcome of two decades of work by so many people.

Firesheep used to be a thing! Your ISP used to know everything you did online! The web is so much safer than it was just 10 years ago.

Especially happy that this will kill off invisible links to HTTP-to-HTTPS redirects.
October 29, 2025 at 11:20 AM
Extremely happy to see Source Spotter, a Go Checksum Database monitor and Go toolchain reproducer by @agwa.name.

These use the transparency logs we built into the Go supply chain to keep the Google-operated services honest.
Source Spotter - Supply Chain Security for Go
Source Spotter is a sumdb auditor, module monitor, toolchain reproducer, and telemetry config tracker.
sourcespotter.com
October 27, 2025 at 1:07 PM
I've added an appendix to my "Enough Polynomials and Linear Algebra to Implement Kyber" article with the little extra needed to implement Dilithium/ML-DSA.

Maybe I'll stream an ML-DSA implementation tomorrow at www.twitch.tv/filosottile.
Enough Polynomials and Linear Algebra to Implement Kyber
How much linear algebra and polynomials do you need to know to implement Kyber? Turns out, very little!
words.filippo.io
October 26, 2025 at 12:55 AM
I got frustrated with how GitHub Actions lets workflows with read-only permissions poison the cache of read/write workflows (!!??!?), so yesterday night I put together an Action that runs commands in a gVisor sandbox.
GitHub - geomys/sandboxed-step: A GitHub Action that runs a command in a gVisor sandbox
A GitHub Action that runs a command in a gVisor sandbox - geomys/sandboxed-step
github.com
October 24, 2025 at 12:59 PM
As professional maintainers we can invest in making our projects safer and more reliable. To that end, here's a draft of the Geomys Standard of Care.

It covers general maintenance, stability & reliability, dependency management, account and CI security, vulnerability handling, licensing, and more.
The Geomys Standard of Care
Introducing the set of standards that Geomys maintainers strive to uphold in our professional activity as open source maintainers.
words.filippo.io
October 23, 2025 at 2:05 PM
Serious take: the solution to Safe Browsing false positives like the Immich one is passkeys.

Phishing regularly upends people's lives. The Safe Browsing cat-and-mouse with all its opaque false positives will be necessary until we roll out phishing-resistant auth.
October 23, 2025 at 12:34 PM
Reposted by Filippo Valsorda
This is a funny short story about contributing to internet standards in unexpected ways, like drawing ASCII art. Thanks to @filippo.abyssdomain.expert firstly for the work you do in cryptography and the opportunity to uniquely contribute to PQC :)

Read more: sethmlarson.dev/drawing-an-a...
October 22, 2025 at 4:26 PM