As you might know, I left Google in spring to try and make the concept of a professional Open Source maintainer a thing. I'm staying on as a maintainer of the Go cryptography standard library, and I am going to seek funding from companies that rely on it, want to ensure its security and reliability, and would like to get a direct line to the maintainers of their critical business infrastructure. (If this sounds like you, reply to this email!)
In the meantime, though, the Go development cycle progresses inexorably, with the Go 1.20 feature freeze coming at the beginning of November. Once the main Go tree freezes, I plan to work on
age, but in the meantime I have a few things I am excited about for Go 1.20.
The most visible change will be the landing the new
crypto/ecdh package I proposed and implemented earlier this year. The package provides a safe,
byte-based, easy to use API for Elliptic Curve Diffie-Hellman over Curve25519 and NIST curves (P-256 and company, but no P-224 if we can get away with it).
crypto/ecdh was made possible by a long-running refactor of the elliptic curve implementations in the standard library. Between Go 1.17 and Go 1.19, most critical code was moved to safer low-level APIs under
crypto/internal/edwards25519, large pieces were replaced with code generated from fiat-crypto's formally verified models, making every curve constant time, most group logic was replaced with modern complete formulas, and even the assembly was massaged to implement the same functions on all architectures and fit the nistec API. Some assembly is gone, actually!
(Here are all the changes. A couple nifty uses of generics in there if you're curious.)
The goal of the package is to replace the major use case for the now-deprecated
crypto/elliptic API, which has a hardcoded dependency on the variable-time, large, and complex
crypto/elliptic is now no more than a compatibility wrapper. Any more advanced uses of
crypto/elliptic can switch to filippo.io/nistec which is an exported version of
crypto/internal/nistec, or filippo.io/edwards25519 which is an exported version of
What's left to do in Go 1.20 then?
First, actually landing the new package, which is already submitted! Then, adding and reviewing new tests (including Wycheproof integration by Roland), which actually revealed there are fewer (!!) edge cases than I had originally documented. Finally, reviewing the BoringCrypto integration by Russ.
math/big out of the security perimeter
There is an even broader goal behind this work: moving
math/big out of the security perimeter entirely, meaning making it unreachable from attacker-exposed cryptographic APIs and protocols.
math/big is a general-purpose big integer library, it's not constant time, and it's full of complex code that while unnecessary for cryptography has repeatedly led to security vulnerabilities in crypto packages. While it was a convenient way to bootstrap the Go crypto standard library,
math/big does not belong in crypto code in 2022.
crypto/ecdh lets us deprecate
crypto/elliptic, and lets us bypass
crypto/tls's ECDHE implementation.
The next step is modifying
crypto/ecdsa to use
crypto/internal/nistec for the group operations on known curves, deprecate the use of custom curves, and replace the scalar field operations with... something. That something might be fiat-crypto field implementations for each scalar field (P-256's, P-384's, and P-521's) with the wide reduction trick we talked about in Cryptography Dispatches, or using a minimal bigint implementation shared with
crypto/rsa unavoidably needs a lightweight bigint implementation to replace its dependency on
math/big. The good news is that we can make that one constant-time, simple, and tightly scoped for its purposes, which should make it much easier to maintain and keep secure. Lucas contributed one that needs review, and Thomas Pornin offered a Go port of BearSSL's one. This will be a significant amount of assessment, review, and testing work, but it's the last real hurdle.
Finally, we need to worry about the places where
big.Int is exposed in public APIs, mainly
crypto/ecdsa key types. An idea is making the
(*Int).FillBytes round-trip constant-time so it can be used as just an annoying way to carry around the
byte encoding of the key values. The problems with that are how to handle (or check in constant time) any manual modification to the
big.Int, and how to store zero-padded values (which we can't unpad in constant time) without breaking the normalization invariant of
big.nat. I welcome suggestions!
If we do go the route of keeping a select subset of
math/big exposed, we'll want to lock it in to ensure we can keep it constant time and well reviewed. For that I have a WIP test that does static analysis to ensure only expected functions are reachable from crypto packages.
More elliptic curves
Aside from the
math/big-related efforts, there are a couple other Go 1.20 tasks that have to do with elliptic curves.
First, landing a rewrite of the edwards25519 scalar field that replaces the last bits of unreadable ref10 code with fiat-crypto generated code. You can read more on a previous Cryptography Dispatches issue, and there's an overview of the overall edwards25519 rewrite in the CL that landed it after years out-of-tree.
Second, finally landing support for Ed25519ph (the pre-hashed variant of Ed25519) in
Finally, as a stretch goal in case elliptic curve work leaves some space for other things, I collected a couple batches of
crypto/tls work. (I find it more efficient to work in topic-scoped batches, so I can load context on a protocol and codebase once and use it to land multiple changes.)
One batch revolves around session resumption: exposing a way to provide external PSKs in TLS 1.3 (which are the underlying mechanism of session tickets in TLS 1.3), maybe implementing PSK modes, implementing Session IDs, making sessions serializable/exportable.
Here's a list of related issues. (The one about forward secrecy by default was already mostly addressed by work we landed somewhat quietly with Katie in Go 1.15, which I'm hoping to write about for the Go blog, as it sets Go significantly apart from any other TLS stack I know about.)
- crypto/tls: TLS session resumption re-verifies the client's certificate chain
- crypto/tls: make ClientSessionState serializable
- proposal: crypto/tls: implement Session IDs resumption
- proposal: crypto/tls: SessionTicketWrapper and Forward Secrecy by default
- crypto/tls: add PSK support
- proposal: crypto/tls: expose a session identifier
The second batch is a miscellaneous list of crypto/tls work. If you have anything else TLS-related you care about, now is a good time to ping me on it.
- crypto/tls: customisable max TLS record size
- crypto/tls: improve default performance of SupportsCertificate
- crypto/tls: add VersionName function to return a string version of the TLS Version
- crypto/tls: expose all presented certs in error type on handshake failure
- crypto/tls: support ECDHE key exchanges when ec_point_formats is missing in ClientHello extension
- crypto/tls: make maxHandshake larger or configurable
- crypto/tls: run BoringSSL test suite (BoGo)
- proposal: crypto/tls: implement RFC7627
DEF CON was a blast (we won a Black Badge with the Scavenger Hunt!) and systematically eating outdoors and wearing a P100 respirator spared me from COVID. Las Vegas is hell but pretty.
If you want to stay up to date with my Open Source work, consider following me on Twitter or subscribing to this newsletter if you haven't already! If your company depends on Go and its cryptography libraries, or any other of my Open Source projects, consider sponsoring my maintenance work. Reply to this email, introduce me to the right people, and I'll work with your accounting department to make it happen!