10,859 karma · joined May 9, 2012
[ my public key: https://keybase.io/filippo; my proof: https://keybase.io/filippo/sigs/c51KtcfccPH0D3jG9PtQBZZh6AqhvB5MHIz2YmkupAc ]
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...
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.
Yep, welcome to my life.
- 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...
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.)
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.
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.)
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.
https://github.com/FiloSottile/age?tab=readme-ov-file#passph...
- 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.
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/)
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.
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.
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.
This is actually similar to why XChaCha20Poly1305 has 192-bit nonces, and consistency with the other major extended-nonce AEAD is another mild advantage.
I use WhatsApp dozens of times a day, and interact with business accounts every couple months at most.
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?
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.
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.
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.
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.