Repository: go
Issue: crypto/dsa: deprecate and remove from crypto/x509 and x/crypto/ssh
Labels: Proposal,Proposal-Accepted,NeedsFix,Proposal-Crypto

DSA is an obsolete, fragile, insecure, and mostly unused signature scheme. I'm proposing that we deprecate (but **not** remove) the `crypto/dsa` package, recommending a modern alternative such as `crypto/ed25519`, and drop support for DSA keys in the `crypto/x509` and `golang.org/x/crypto/ssh` packages.

## The problem with DSA

First, DSA suffers of what we now know is a design mistake: it requires each key to bring along its own parameters, instead of setting globally accepted ones. Parameters are slow to generate, large to encode, and most importantly very hard to validate. This caused a remote DoS in Go 1.13 (CVE-2019-17596, #34960) exploitable through both TLS and SSH.

Second, DSA was initially standardized with a max key size of 1024 bits, which is now universally acknowledged as insecure against real-world attackers. While larger key sizes were standardized years later, by then it made no sense to use DSA in new systems anymore, so the systems that kept using DSA did it for backwards compatibility and didn't adopt larger keys. It's also been almost 20 years.

[I wrote more about this in a newsletter issue.](https://buttondown.email/cryptography-dispatches/archive/cryptography-dispatches-dsa-is-past-its-prime/)

## DSA and X.509

The Mozilla Root Store policy rejects DSA keys in X.509 certificates, so they are completely absent from the WebPKI, which is what `crypto/x509` targets. Anecdotally, they are also not in use in any private PKI I am aware of. (This is obviously a hard assertion to substantiate.)

`crypto/x509` is exposed to the world for most Go applications through `crypto/tls`, and supporting DSA is a liability in terms of attack surface, as proved by CVE-2019-17596.

Also note that `crypto/tls` doesn't itself support DSA certificates, so they already can't be used as website certificates, only as intermediate or root CAs.

## DSA and SSH

OpenSSH's `ssh-keygen` only ever supported insecure 1024-bit keys. [94% of the DSA keys on GitHub are 1024-bit](https://gist.github.com/FiloSottile/70215af9b1be7e00ff1cffbff8aa35eb). The golang.org/x/crypto/ssh package [only supports 1024-bit keys](https://github.com/golang/crypto/blob/75b288015ac94e66e3d6715fb68a9b41bf046ec2/ssh/keys.go#L411-L417). DSA as used in SSH is insecure.

There is reason to think removing DSA support will actually _help_ compatibility, by preferring other key types and avoiding connection failures for key sizes other than 1024-bit (#23751). OpenSSH 7.0 disabled DSA support in 2015. Dropping DSA support will also help align the host keys observed by x/crypto/ssh with the ones in an OpenSSH `known_hosts` file.

## Edited to add: NIST is deprecating DSA

DSA is specified in FIPS 186 by NIST. The draft of the next version of the specification, FIPS 186-5, removes all text about DSA except for a paragraph stating that DSA may only be used to verify existing legacy signatures. We risk being behind _the FIPS standards_!

![image](https://user-images.githubusercontent.com/1225294/88199719-3393f180-cc13-11ea-8345-1aeadf06ef50.png)