HNHacker News
TopNewBestAskShowJobs

FiloSottile

10,859 karma · joined May 9, 2012

https://filippo.io

[ my public key: https://keybase.io/filippo; my proof: https://keybase.io/filippo/sigs/c51KtcfccPH0D3jG9PtQBZZh6AqhvB5MHIz2YmkupAc ]

submissionscomments
FiloSottile··on Benchmarking RSA Key Generation
There's extremely small (like 2⁻²⁰, the chance of winning $50 000 with a $2 Powerball ticket [1]), and then there's cryptographically negligible (like 2⁻¹²⁰, the false negative chance of our primality test). The chance of something cryptographically negligible happening is about the same as the chance of the attacker guessing your key on the first try, or of a cosmic ray flipping a CPU flag inverting the result of "if !signature.verified { return err }".

[1]: https://www.powerball.com/powerball-prize-chart

FiloSottile··on Benchmarking RSA Key Generation
> Rule of thumb: Want a 1024-bit prime? Try 1024 1024-bit candidates and you'll probably find one.

Where probably is 76% [1], which is not that high depending on what you are doing. For example, you wouldn't be ok with GenerateKey failing 24% of the time.

To get a better than even chance, 491 [2] 1024-bit candidates are enough.

[1]: https://www.wolframalpha.com/input?i=1+-+%281+-+li%282%5E102... (using li(x) as a slightly better approximation of π(x) than x/ln(x), see [3])

[2]: https://www.wolframalpha.com/input?i=1+-+%281+-+li%282%5E102...

[3]: https://en.wikipedia.org/wiki/Prime-counting_function

FiloSottile··on Hyrum’s Law in Golang
We have gotten a liiiiittle more liberal ever since we introduced the new GODEBUG feature flag mechanism.

I've been meaning to write a "how to safely update Go" post for a while, because the GODEBUG mechanism is very powerful but not well-known and we could build a bit of tooling around it.

In short, you can upgrade your toolchain without changing the go.mod version, and these things will keep working like they did, and set a metric every time the behavior would have changed, but didn't. (Here's where we could build a bit of tooling to check that metric in prod/tests/CLIs more easily.) Then you can update the go.mod version, which updates the default set of GODEBUGs, and if anything breaks, try reverting GODEBUGs one by one.

FiloSottile··on Hyrum’s Law in Golang
> You will be forced to lug this broken behavior with you forever

Yep, welcome to my life.

FiloSottile··on Hyrum’s Law in Golang
Hah, I wrote the crypto/rsa comments. We take Hyrum's Law (and backwards compatibility [1]) extremely seriously in Go. Here are a couple more examples:

- We randomly read an extra byte from random streams in various GenerateKey functions (which are not marked like the ones in OP) with MaybeReadByte [2] to avoid having our algorithm locked in

- Just yesterday someone reported that a private ECDSA key with a nil public key used to work, and now it doesn't, so we probably have to make it work again [3]

- Iterating over a map uses a randomized order to avoid exposing the internals

- The output of rand.Rand is considered part of the compatibility promise, so we had to go to great lengths to improve it [4]

- We discuss all the time what commitments to make in docs and what behaviors to disclaim, knowing we can never change something documented and probably something that's not explicitly documented as "this may change" [6]

[1]: https://go.dev/doc/go1compat

[2]: https://pkg.go.dev/crypto/internal/randutil#MaybeReadByte

[3]: https://go.dev/issue/70468

[4]: https://go.dev/blog/randv2

[5]: https://go.dev/blog/chacha8rand

[6]: https://go-review.googlesource.com/c/go/+/598336/comment/5d6...

FiloSottile··on Writing secure Go code
> Does it know which part of a dependency has a vulnerability and check, if the execution reaches _that_ part?

Yes, govulncheck does symbol-level reachability static analysis, and the vulndb is manually annotated with affected symbols for each vulnerability.

(So glad to see a comment about this at the top, I have sometimes feared we made a mistake in designing a low-noise vulnerability scanner, because I've often seen complaints that "it doesn't work" because it doesn't show as many vulnerabilities as its more popular, less accurate alternatives.)

FiloSottile··on CRLF is obsolete and should be abolished
Hrm, this is what I get for logging in to HN from my phone. It’s possible I am confusing this with one of the other exploitable HTTP/1.1 header parser alignment issues.

Maybe this was so widespread that ~everything already handles it because non-malicious stuff breaks if you don’t. In that case, my bad, but I still would like to make a general plea as an implementer for sticking strictly to specified behavior in this sort of protocols.

FiloSottile··on CRLF is obsolete and should be abolished
Exactly. Please DO NOT mess with protocols, especially legacy critical protocols based on in-band signaling.

HTTP/1.1 was regrettably but irreversibly designed with security-critical parser alignment requirements. If two implementations disagree on whether `A:B\nC:D` contains a value for C, you can build a request smuggling gadget, leading to significant attacks. We live in a post-Postel world, only ever generate and accept CRLF in protocols that specify it, however legacy and nonsensical it might be.

(I am a massive, massive SQLite fan, but this is giving me pause about using other software by the same author, at least when networks are involved.)

FiloSottile··on Age is a simple, modern and secure file encryption tool, format, and Go library
My age v2 note for padding says “use Padmé, see Colm’s comments” :)

I’m not really sold on the UR part of PURBs, though: age wants to avoid asking for a passphrase if the file is not passphrase encrypted, and age-plugin-yubikey wants to avoid asking for a PIN if it’s for the wrong YubiKey. These are tradeoffs and it’s not obvious the very end of the spectrum (uniform random) is the right spot.

FiloSottile··on Age is a simple, modern and secure file encryption tool, format, and Go library
Identity files can be passphrase encrypted and cmd/age will transparently ask for the passphrase before using them. Is that what you meant?

https://github.com/FiloSottile/age?tab=readme-ov-file#passph...

FiloSottile··on Age is a simple, modern and secure file encryption tool, format, and Go library
Assuming that implementation never skip verifying the second signature, and compare the signing keys, that should be ok.
FiloSottile··on Age is a simple, modern and secure file encryption tool, format, and Go library
Thanks for sharing, always happy when my projects inspire alternatives addressing different parts of the design space. Here are a few quick comments based on skimming the documentation, let me know if I misinterpreted anything.

- signing support

This has always been a non-goal for age. It makes the UX significantly more complex, but it's good if different tools have different goals.

I can't quite make out from https://www.kryptor.co.uk/specification if it does proper signcryption, sign-then-encrypt (vulnerable to signature stripping and re-signing), or encrypt-then-sign (vulnerable to decrypt-reencrypt-forward, like OpenPGP). If the latter two, it's a missed opportunity to offer more security than age+minisign can offer and I encourage the author to look into it!

- sender authentication

I wrote about this. tl;dr age has authentication, but I am not sure what a non-sharp UX around it would be, so I don't advertise it. https://words.filippo.io/dispatches/age-authentication/

- post-quantum security

As https://www.kryptor.co.uk/security-limitations#post-quantum-... acknowledges, "the asymmetric algorithms in Kryptor aren't post-quantum secure". There is support for adding a pre-shared symmetric key, although I did not find the pre-shared key in the usage section, but I would argue that is not asymmetric encryption.

In this sense, I would actually argue that Kryptor is just as post-quantum secure as age: age's symmetric encryption (the passphrase mode) is post-quantum (see https://words.filippo.io/dispatches/post-quantum-age/). We don't support adding a pre-shared symmetric key to asymmetric encryption, but if you have a secure channel to establish a pre-shared key, you should just use passphrase mode.

age does have a third-party fully post-quantum asymmetric encryption plugin (https://github.com/keisentraut/age-plugin-sntrup761x25519) and I plan to make an ML-KEM one once the standard is out.

- key commitment

This is a pretty wonky topic. age as a whole is key committing (you can't make a file that decrypts with two age identities as different plaintexts, some academic researchers tried!). Our file key encryption is not (https://github.com/FiloSottile/age/commit/2194f6962c8bb3bca8...) which means that if you host an online service that accepts an age file and decrypts it with a passphrase and returns an error if it's incorrect, an attacker can do a bruteforce two passphrases at a time instead of one at a time. Given the online oracle is already unusual as a setting, I am not interested in adding complexity to solve this one.

- private key encryption

age supports that! https://github.com/FiloSottile/age?tab=readme-ov-file#passph...

It's not the default because most threat models don't need it: if you have FDE, who's an attacker that can read files from your disk but not replace the age binary in $PATH?

- indistinguishability from random

Not an age goal, actually we very intentionally put "age-encryption.org/v1" in the header so you can run file(1), and specify the type of the recipients to help plugins disambiguate files. The default recipient type doesn't leak any other metadata (i.e. you can't link age files encrypted to the same recipient).

- size padding

This is a good idea and slated for age v2.

FiloSottile··on Age is a simple, modern and secure file encryption tool, format, and Go library
_o/ hi all, age author here! age is the one of my projects that grew most organically into an ecosystem. It's always great to see what people build with it. Happy to answer any questions.

Here are some previous discussions

132 points on Feb 26, 2023 | 77 comments | https://news.ycombinator.com/item?id=34936504

126 points on Sept 26, 2022 | 54 comments | https://news.ycombinator.com/item?id=32980141

113 points on June 11, 2022 | 33 comments | https://news.ycombinator.com/item?id=31705670

494 points on Sept 6, 2021 | 88 comments | https://news.ycombinator.com/item?id=28435613

466 points on Dec 27, 2019 | 199 comments | https://news.ycombinator.com/item?id=21895671

and here some related resources

- a list of age ecosystem projects https://github.com/FiloSottile/awesome-age

- the format specification https://c2sp.org/age

- the Go library docs https://pkg.go.dev/filippo.io/age

- the CLI man page https://filippo.io/age/age.1

- the large reusable test suite (which I should write about!) https://c2sp.org/CCTV/age

- an interoperable Rust implementation by @str4d https://github.com/str4d/rage

- an official TypeScript implementation https://github.com/FiloSottile/typage (based on libsodium.js in the latest version, and on pure-js Noble libraries on main)

- a YubiKey plugin by @str4d https://github.com/str4d/age-plugin-yubikey

- the plugin protocol specification https://c2sp.org/age-plugin

- a Windows GUI by @spieglt https://github.com/spieglt/winage

- a discussion of the authentication properties of age https://words.filippo.io/dispatches/age-authentication/

- a discussion of the plugin architecture https://words.filippo.io/dispatches/age-plugins/

- a discussion of a potential post-quantum plugin https://words.filippo.io/dispatches/post-quantum-age/

- a password-store fork that uses age instead of gpg https://github.com/FiloSottile/passage (see also: how I use it with a YubiKey https://words.filippo.io/dispatches/passage/)

FiloSottile··on Rustgo: Calling Rust from Go with near-zero overhead (2017)
That exist(ed)! c2goasm would compile C and then decompile it into Go asm.

https://github.com/minio/c2goasm

FiloSottile··on Elligator: Elliptic-curve points indistinguishable from uniform random strings (2013)
Elligator is a bidirectional map from random bytes to elliptic curve points, which is mainly useful for censorship resistance. Its state-of-the-art protocol integration as far as I know is obfs4 (https://gitlab.com/yawning/obfs4), one of the Tor circumvention pluggable transports (https://tb-manual.torproject.org/circumvention/). The others rely on disguising as other protocols rather than looking random.

Elligator implementations have a history of subtle bugs, arguably because there was not a spec, only a paper, although it looks like there are some third-party test vectors now.

In general the "inverse map" from random bytes to point is used only for censorship-resistance use cases, but the "direct map" turning random bytes (like a CSPRNG output or a hash) into a point is useful for a number of purposes in cryptography, like VRFs. That led to the direct map being specified more rigorously, like in https://www.rfc-editor.org/rfc/rfc9496.html#name-element-der... and https://datatracker.ietf.org/doc/html/rfc9380.

IMHO a map from a fixed amount of random bytes should be part of the fundamental group abstraction, and that's what Ristretto provides. The CFRG approach is slightly different, providing full domain-separated hash "suites" that go straight into a curve point.

FiloSottile··on RegreSSHion: RCE in OpenSSH's server, on glibc-based Linux systems
It appears you’ve not read past the topmost reply to the topmost comment, and left with the wrong impression.
FiloSottile··on RegreSSHion: RCE in OpenSSH's server, on glibc-based Linux systems
The ones you link are the "minimal patches for those can't/don't want to upgrade". The commit I am linking to is taken straight from the advisory.

    On June 6, 2024, this signal handler race condition was fixed by commit
    81c1099 ("Add a facility to sshd(8) to penalise particular problematic
    client behaviours"), which moved the async-signal-unsafe code from
    sshd's SIGALRM handler to sshd's listener process, where it can be
    handled synchronously:

      https://github.com/openssh/openssh-portable/commit/81c1099d22b81ebfd20a334ce986c4f753b0db29

    Because this fix is part of a large commit (81c1099), on top of an even
    larger defense-in-depth commit (03e3de4, "Start the process of splitting
    sshd into separate binaries"), it might prove difficult to backport. In
    that case, the signal handler race condition itself can be fixed by
    removing or commenting out the async-signal-unsafe code from the
    sshsigdie() function
The cleverness here is that this commit is both "a previously-announced feature for dealing with junk connections", and a mitigation for the exploit class against similar but unknown vulnerabilities, and a patch for the specific vulnerability because it "moved the async-signal-unsafe code from sshd's SIGALRM handler to sshd's listener process, where it can be handled synchronously".

The cleverness is that it fixes the vulnerability as part of doing something that makes sense on its own, so you wouldn't know it's the patch even looking at it.

FiloSottile··on RegreSSHion: RCE in OpenSSH's server, on glibc-based Linux systems
Interestingly, the RCE fix was "smuggled" in public almost a month ago.

    When PerSourcePenalties are enabled, sshd(8) will monitor the exit
    status of its child pre-auth session processes. Through the exit
    status, it can observe situations where the session did not
    authenticate as expected. These conditions include when the client
    repeatedly attempted authentication unsucessfully (possibly indicating
    an attack against one or more accounts, e.g. password guessing), or
    when client behaviour caused sshd to crash (possibly indicating
    attempts to exploit sshd).

    When such a condition is observed, sshd will record a penalty of some
    duration (e.g. 30 seconds) against the client's address.
https://github.com/openssh/openssh-portable/commit/81c1099d2...

It's not really a reversable patch that gives anything away to attackers: it changes the binary architecture in a way that has the side-effect of removing the specific vulnerability and also mitigates the whole exploit class, if I understand it correctly. Very clever.

FiloSottile··on The XAES-256-GCM extended-nonce AEAD
Assuming you’re referring to the birthday bound on blocks (https://sweet32.info) that’s a limit on blocks encrypted with a single key. XAES derives large keys per message, so it achieves what are commonly referred to as “better-than-birthday” bounds.
FiloSottile··on The XAES-256-GCM extended-nonce AEAD
There is no space for 256 bits: 192 bits is 96 bits from the underlying nonce space, and 96 bits that go into the 128-bit CMAC block (along with the necessary prefix). We could make the CMAC input longer, but then we'd have to run the AES-256 block function more times (and we'd hit some annoying key control issues in the CMAC KDF).

This is actually similar to why XChaCha20Poly1305 has 192-bit nonces, and consistency with the other major extended-nonce AEAD is another mild advantage.

FiloSottile··on The XAES-256-GCM extended-nonce AEAD
I don't disagree, actually. I was copying the NIST source document notation with 0¹²⁸ and 0¹²⁰10000111, but it probably does more harm than good. `X` was just me being too clever. (In my defense, `X` is formatted differently from variables in the original, and all variables are defined.)

Done. https://github.com/C2SP/C2SP/pull/86/files

FiloSottile··on Telegram has launched a pretty intense campaign to malign Signal as insecure
“All of them” in what sense?

I use WhatsApp dozens of times a day, and interact with business accounts every couple months at most.

FiloSottile··on Post-quantum cryptography is too damn big
That’s the first TLS change suggestion, under the “Intermediate elision” heading.
FiloSottile··on Post-quantum cryptography is too damn big
What’s wrong with P curves?
FiloSottile··on GoFetch: New side-channel attack using data memory-dependent prefetchers
> you should either be writing your code such that it is timing agnostic, or you could read the platform documentation rather than making assumptions

Have you even read the paper? Especially the part where the attack applies to everyone’s previous idea of “timing agnostic” code, and the part where Apple does not respect the (new) DIT flag on M1/M2?

FiloSottile··on GoFetch: New side-channel attack using data memory-dependent prefetchers
> download random programs onto their computers and run them at random

To be clear that includes what we're all doing by downloading and running Javascript to read HN.

Maybe I can say "don't run adversarial code on my same CPU" and only care about over-the-network CPU side-channels (of which there are still some), because I write Go crypto, but it doesn't sound like something my colleagues writing browser code can do.

FiloSottile··on GoFetch: New side-channel attack using data memory-dependent prefetchers
Names are critical to enable discussion.

The "marketing" page is where documentation is. Summaries that don't require reading a whole academic papers are a good thing, and they are the place where all the different links are collected. Same reason software has READMEs.

Logos... are cute and take 10-60 minutes? If you spend months on some research might as well take the satisfaction of giving it a cute logo, why not.

FiloSottile··on GoFetch: New side-channel attack using data memory-dependent prefetchers
Speaking as a cryptography implementer, yes, these drive us up the wall.

However, crypto coprocessors would be a tremendously disruptive solution: we'd need to build mountains of scaffolding to allow switching to and off these cores, and to share memory with them, etc.

Even more critically, you can't just move the RSA multiplication to those cores and call it a day. The key is probably parsed from somewhere, right? Does the parser need to run on a crypto core? What if it comes over the network? And if you even manage to protect all the keys, what if a CPU side channel leaks the message you encrypted? Are you ok with it just because it's not a key? The only reason we don't see these attacks against non-crypto code is that finding targets is very application specific, while in crypto libraries everyone can agree leaking a key is bad.

No, processor designers "just" need to stop violating assumptions, or at least talk to us before doing it.

FiloSottile··on Sunlight, a Certificate Transparency log implementation
We considered this design and rejected it because it requires an ultimately unwinnable cat-and-mouse game of fingerprint resistance.

Things the log can use to partition the users include their Tor version, HTTP library behavior, contact periodicity... the list goes on and on, and keeps restricting the use cases where it can be deployed securely even just in theory.

Witness cosigning is secure even if the way you fetch the proofs is completely attacker-controlled, which is closer to user expectations of regular digital signatures.

FiloSottile··on Sunlight, a Certificate Transparency log implementation
Purely coincidental! ;-)
← PreviousPage 4 of 22Next →