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 Go Cryptography State of the Union
It's not that simple! What about intermediate values during arithmetic computations? What about registers spilling during signal handling?

I honestly thought it could not be done safely, but the runtime/secret proposal discussion proved me wrong.

FiloSottile··on Go Cryptography State of the Union
You might find this proposal and the upcoming runtime/secret package interesting.

https://github.com/golang/go/issues/21865

FiloSottile··on Go Cryptography State of the Union
> I don't know why the standard library crypto packages insist on passing around `[]byte` for things like a seed value

These are actually very deliberate choices, based on maybe unintuitive experience.

We use []byte instead of e.g. [32]byte because generally you start with a []byte that's coming from somewhere: the network, a file format, a KDF.

Then you have two options to get a [32]byte: cast or copy. They both have bad failure modes. If you do a ([32]byte)(foo) cast, you risk a panic if the file/packet/whatever is not the size you expected (e.g. because it's actually attacker controlled). If you do a copy(seed, foo) it's WAY WORSE, because you risk copying only 5 bytes and leaving the rest to zero and not noticing.

Instead, we decided to move the length check into the library everywhere we take bytes, so at worst you get an error, which presumably you know how to handle.

> why we can't just pass in a seed value to a single unambiguous constructor when generating asymmetric keys

I am not sure what you are referring to here. For e.g. ML-KEM, you pass the seed to NewDecapsulationKey768 and you get an opaque *DecapsulationKey768 to pass around. We've been moving everything we can to that.

> Or how the constructor for a key pair could possibly return an error, when the algorithm is supposed to be deterministic.

Depends. If it takes a []byte, we want to return an error to force handling of incorrect lengths. If the key is not a seed (which is only an option for private keys), it can also be invalid, deterministic or not. (This is why I like seeds. https://words.filippo.io/ml-kem-seeds/)

> removing all dependencies on rand would make it obvious where the entropy must be coming from (the seed parameter)

Another place where experience taught us otherwise. Algorithms that take a well-specified seed should indeed just take that (like NewDecapsulationKey768 does!), but where the spec annoyingly takes "randomness from the sky" (https://words.filippo.io/avoid-the-randomness-from-the-sky/) in an unspecified way, taking a io.Reader gave folks the wrong impression that they could use that for deterministic key generation, which then breaks as soon as we change the internals.

There is only one place to get entropy from in a Go program, anyway: crypto/rand. Anything else is a testing need, and it can be handled with test affordances like the upcoming crypto/mlkem/mlkemtest or testing/cryptotest.SetGlobalRandom.

FiloSottile··on Switching from GPG to Age
128 bits of symmetric keys are enough for post-quantum security. See https://words.filippo.io/post-quantum-age/.

The public key algorithm has been frustratingly blocked on the IETF and CFRG, which are taking more than 15 months since FIPS 203 to stabilize a simple hash-based hybrid combiner.

FiloSottile··on A modern approach to preventing CSRF in Go
No, in CSRF the browser is not the adversary, it is a confused deputy, and it’s perfectly reasonable to collaborate with it against the attacker (which is another site).

You might want to read https://words.filippo.io/csrf.

FiloSottile··on Bluesky: Updated Terms and Policies
> Users can move their follows, followers and posts to zeppelin.social fron BlueSky transparently?

Yes, even if Bluesky was down (as long as they have a backup) which is not the case for ActivityPub.

FiloSottile··on Cross-Site Request Forgery
For CSRF (and for SameSite), you are not looking at what cookies are sent to attacker.example.com, but what cookies are sent to target.example.com if a request is originated from attacker.example.com (or from attacker.com).
FiloSottile··on Cross-Site Request Forgery
Same-Site cookies are, well, same-site. Not same-origin. This is already a deal-breaker for many deployments, because they don't trust blog.example.com and partner.example.com as much as admin.example.com (both in the strict sense of trust, and in the senso of not having XSS vulnerabilities the attacker can pivot off).

Worse, by the original definition http://foo.example.com and https://admin.example.com are same-site, and unless the site uses HSTS with includeSubDomains, any network attacker controls the former. Chrome changed that with Schemeful Same-Site in 2020, but Firefox and Safari never deployed it.

FiloSottile··on There is no memory safety without thread safety
I have never seen real Go code (i.e. not code written purposefully to be exploitable) that was exploitable due to a data race.

This doesn’t prove a negative, but is probably a good hint that this risk is not something worth prioritizing for Go applications from a security point of view.

Compare this with C/C++ where 60-75% of real world vulnerabilities are memory safety vulnerabilities. Memory safety is definitely a spectrum, and I’d argue there are diminishing returns.

FiloSottile··on The FIPS 140-3 Go Cryptographic Module
Thomas and I are both talking about the Go cryptographic library overall, not about the ChaCha20 implementation in particular. Anyway, I don’t find arguing semantics around the “soup-to-nuts” expression particularly productive.

We avoided the DIV by deliberately not using a modulus operation and doing Barrett reduction instead.

FiloSottile··on The FIPS 140-3 Go Cryptographic Module
Well, ML-KEM has zero assembly and was written entirely from scratch, for example, so it must be more than you'd think if you think we "reuse the same machine code for this that you'd find in everybody else's implementation." In fact, almost everyone else's was found to be producing a variable-time DIV instruction, while ours was unaffected.

Porting the assembly to higher-level generators has nothing to do with lawyers (??), the goals are stated in https://go.dev/wiki/AssemblyPolicy.

The idea that one day we'll write All Of The Cryptography Code Once And For All In The Perfect Language and reuse that across languages comes up pretty regularly, and has never panned out.

FiloSottile··on The FIPS 140-3 Go Cryptographic Module
Yes, it calls out to OpenSSL on Linux and to CNG on Windows. I think, but I am not certain, that at least the OpenSSL cgo bindings are derived from the Go+BoringCrypto ones (which makes sense, since the BoringSSL and OpenSSL APIs are still very similar).
FiloSottile··on The FIPS 140-3 Go Cryptographic Module
Off the top of my head, there might be some old assembly by Andy Polyakov and by Vlad Krasnov that was contributed to both Go and OpenSSL. Even there, we’ve been working for years to port hand-written assembly to higher level generators, and there’s not as much as you’d think. Everything else is original.

Besides integrating properly with Go applications, this lets us optimize for readability and correctness, with IMHO excellent empirical results.

https://words.filippo.io/a-literate-go-implementation-of-pol...

https://go.dev/blog/tob-crypto-audit

https://www.youtube.com/watch?v=lkEH3V3PkS0

FiloSottile··on The FIPS 140-3 Go Cryptographic Module
[ Big I am a cryptographer, not your cryptographer disclaimer ]

It depends, but if you are targeting Security Level 1 (which is what most folks think about when they think about FIPS 140) you generally don't need your entire application to be validated, only the cryptographic module.

So (again, depending on your requirements and on the Operating Environment you deploy to and on what algorithms you use and how) setting GOFIPS140 might actually be all you need to do.

FiloSottile··on The FIPS 140-3 Go Cryptographic Module
To nitpick, there is no special crypto/fips140 package. (Ok, there is, but it just has an Enabled() bool function.)

FIPS 140-3 mode is enabled by building with GOFIPS140=v1.0.0 (or similar, see https://go.dev/doc/security/fips140), but it shares 99% of the code with non-FIPS mode.

Still, your message is right, just GOFIPS140=off (the default!), not GOFIPS140=v1.0.0.

FiloSottile··on The FIPS 140-3 Go Cryptographic Module
No, the Go 1.24 native module effort that they talk about in https://devblogs.microsoft.com/go/go-1-24-fips-update/ is this effort, which Microsoft was not involved in. We simply decided to delay the official announcement until the module reached the In Process list.

The system libraries approach used by Microsoft Go is cgo based IIUC, and I think derived from Go+BoringCrypto. I understand they are working on migrating their bindings to fit better downstream of the new native mode.

FiloSottile··on The FIPS 140-3 Go Cryptographic Module
> Applications that have no need for FIPS 140-3 compliance can safely ignore [this page], and should not enable FIPS 140-3 mode.

https://go.dev/doc/security/fips140

Yup.

FiloSottile··on Encrypting files with passkeys and age
You'll never believe what I (and a bunch of folks) have been working on for years :)

https://www.sigsum.org

https://github.com/FiloSottile/torchwood/tree/main/cmd/apt-t...

https://www.youtube.com/watch?v=SOfOe_z37jQ

https://c2sp.org/tlog-tiles

FiloSottile··on Encrypting files with passkeys and age
Huh, iCloud Keychain supports the prf extension when used with Chrome, so I had assumed they added support to Safari as well, but I just tested it and sure enough, you're right.

Edit: well https://webauthn-passkeys-prf-demo.explore.corbado.com/ works with an iCloud Keychain passkey on Safari on macOS 15.5, but Typage doesn't work with a YubiKey 5, so there is some support (the MDN data is out of date) but also something weird.

FiloSottile··on Running a Certificate Transparency log
That instead was a draft that should have not gone out yet, but the API filter didn’t work :)

I’ll mail that one towards the end of the week.

FiloSottile··on Running a Certificate Transparency log
I added a footnote about it. It’s indeed read traffic, so it’s (certificate volume x number of monitors x compression ratio) on average. But then you have to let new monitors catch up, so you need burst.

It’s unfortunately an estimate, because right now we see 300 Mbps peaks, but as Tuscolo moves to Usable and more monitors implement Static CT, 5-10x is plausible.

It might turn out that 1 Gbps is enough and the P95 is 500 Mbps. Hard to tell right now, so I didn’t want to get people in trouble down the line.

Happy to discuss this further with anyone interested in running a log via email or Slack!

FiloSottile··on Running a Certificate Transparency log
My bad! This is what I get for doing a deploy to fix the layout while the post is on HN. Back up now.
FiloSottile··on Shell-secrets – GPG-encrypted environment variables
Team sharing with a non-technical person, mostly.

I still have high-value passwords and CLI credentials in passage + age-plugin-yubikey.

FiloSottile··on LLM-fragments-go: LLM plugin for pulling Go package docs with go
Currently it just fetches latest if a version is not specified. It should be pretty easy to use the current project version if available, assuming llm plugins stay in the working directory of the main call. PRs welcome :)

Once the module version is in GOMODCACHE, it's extremely fast, not even noticeable.

FiloSottile··on Feds Link Cyberheist to 2022 LastPass Hacks
1Password truly doesn’t get enough credit for the choice to encrypt every vault with a high entropy secret key passed device to device. It surely costs them in UX and support load, but it would have made a breach like this essentially inconsequential.
FiloSottile··on Privacy Pass Authentication for Kagi Search
Privacy Pass is an anonymous credential scheme that does exactly what you describe.
FiloSottile··on Microsoft Go 1.24 FIPS changes
I'm not involved in the OpenSSL/CNG-based Microsoft Go fork.

I've managed and implemented—along with Daniel McCarney, Roland Shoemaker, and Russ Cox—the native upstream Go validation mentioned in the intro, which is shipping in Go 1.24 and will be certified on Linux (amd64, arm64, ppc64le, s390x), Windows (amd64, arm64), macOS (arm64), and FreeBSD (amd64). The Linux operating environments were funded by various stakeholders, the rest were funded by Geomys for the benefit of the Go community.

There are some details now at https://go.dev/doc/security/fips140, but we're going to write a proper blog post once the module gets on the CMVP In Process list.

tl;dr is that it should soon take a single environment variable to transparently build against a FIPS 140-3 validated module which is just a slightly out of date version of the same Go standard library everyone else is using. (AFAIK this is the first non-JVM memory safe FIPS 140 module!)

FiloSottile··on Benchmarking RSA Key Generation
You're asking why not apply the formula for adversarially selected candidates even if we are randomly selecting candidates. There is simply no reason to, except "maybe we made a mistake" but then why would we not think we made a mistake also in calculating the 1/4 value, or in any other part of the code?

Phrased another way, do you have an argument for why run the conservative 60 round test, instead of asking for an argument for why not run it?

Again, you are "very unlikely" to win the Powerball jackpot. Rounds 6-60 have a cryptographically negligible chance of rejecting a composite. It's different, otherwise we'd have to worry about the "very unlikely" chance of the attacker guessing an AES-128 key on the first try.

(I don't follow you on the key sizes, if you apply the 1/4 probability, the candidate size is irrelevant.)

FiloSottile··on Benchmarking RSA Key Generation
Why not do 120 then? We can show that the chance of false negative of 5 rounds is cryptographically negligible, so 5, 60, and 120 are all the same. If the only argument for 60 is that it's more and this is a really important rare operation, doesn't it also apply to 120?

I'm not trying to be glib, there is no rational stopping point if we reject the objective threshold.

FiloSottile··on Benchmarking RSA Key Generation
The number of Miller-Rabin rounds has to be bounded, so if you're not going to base your bound on reaching a cryptographically negligible change of false positives, what are you going to base it on? Should we do 10? 15?

The problem with "x should be enough, but why not do more?" arguments is that they can be applied recursively, and never answer the question "ok so when should we stop?"

← PreviousPage 3 of 22Next →