Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/crypto/ssh: handshake failed: ssh: unsupported DSA key size 2048 #23751

Open
CameronGo opened this issue Feb 8, 2018 · 24 comments
Open

x/crypto/ssh: handshake failed: ssh: unsupported DSA key size 2048 #23751

CameronGo opened this issue Feb 8, 2018 · 24 comments
Milestone

Comments

@CameronGo
Copy link

@CameronGo CameronGo commented Feb 8, 2018

We are seeing some odd behavior connecting to a customer SFTP site with a username and password. This code is working for all other tested endpoints.

I see a section of code in the crypto/keys.go file in the function checkDSAParams that fails if the key length is not 1024, but since I am able to connect to that SFTP with ssh and other SFTP clients, I'm not sure why that restriction is being enforced in Go.

What version of Go are you using (go version)?

go1.9.2 linux/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"

What did you do?

Attempting to establish a connection to a remote SFTP server.
ssh.Dial("tcp", config.SftpServer+":"+string(config.SftpPort), sshConfig)

If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.

What did you expect to see?

A successful SSH handshake and authentication.

What did you see instead?

An error: ssh: handshake failed: ssh: unsupported DSA key size 2048

@bradfitz bradfitz changed the title ssh: handshake failed: ssh: unsupported DSA key size 2048 x/crypto/ssh: handshake failed: ssh: unsupported DSA key size 2048 Feb 8, 2018
@gopherbot gopherbot added this to the Unreleased milestone Feb 8, 2018
@bradfitz
Copy link
Contributor

@bradfitz bradfitz commented Feb 8, 2018

/cc @hanwen

@hanwen
Copy link
Contributor

@hanwen hanwen commented Feb 9, 2018

See RFC 4253 , sec 6.6, which refers to https://csrc.nist.gov/csrc/media/publications/fips/186/2/archive/2000-01-27/documents/fips186-2.pdf
page 8 requires the prime to be less than 1024 bits.
(since DSA specifies SHA1 as hash, there is no point in using larger DSA numbers.)

try using a different type of key. Adding DSA was a mistake, and OpenSSH has deprecated them starting 7.0

@CameronGo
Copy link
Author

@CameronGo CameronGo commented Feb 9, 2018

So I'm all for using a different type of key, but in this case the challenge is we don't control the host to which we are sending files. The remote host is an IBM Sterling File Gateway and the customer in this case has simply implemented a DSS host key.

This is far afield of my area of expertise, but does the reference to larger key sizes in FIPS 186-3 nullify the key size limitation previously referenced in 186-2?

@hanwen
Copy link
Contributor

@hanwen hanwen commented Feb 9, 2018

https://csrc.nist.gov/csrc/media/publications/fips/186/3/archive/2009-06-25/documents/fips_186-3.pdf lists the suggested hash sizes (N), which would be 224 for 2048 bits; if you can use a smaller size for the hash, but then SHA1 (160 bits) would be the weakest link in the signature scheme.

That said, it's possible that there exists some variant of this that does so anyway. My suggestion is to find an open source client/server that supports your device and see what they are doing. It should be fairly easy to test the code against your device.

for reference, this what made me put the check in, #19424 , which suggests an open source (probably openssh) version of this.

@hanwen
Copy link
Contributor

@hanwen hanwen commented Feb 9, 2018

probably not openssh.

$ ssh-keygen -f /tmp/ds -t dsa -b 2048
Invalid DSA key length: must be 1024 bits

@hanwen
Copy link
Contributor

@hanwen hanwen commented Feb 9, 2018

see here https://github.com/fuchsia-mirror/third_party-openssh-portable/blob/620515639a6e3649bb2a4585522a5aae69e8653b/ssh-dss.c#L196

you'd get 160 bits of hash, which then goes into

https://android.googlesource.com/platform/external/boringssl/+/ed3d82f35eb0aa9d81f2398c2142ba07dfc1acee/src/crypto/dsa/dsa.c#636

I think this here just puts the 160 bits of sha1 into 256 bits, leaving the rest 0. https://android.googlesource.com/platform/external/boringssl/+/ed3d82f35eb0aa9d81f2398c2142ba07dfc1acee/src/crypto/dsa/dsa.c#696

I suspect it might work if you set the blob buffer to 32byte after all.

Can you generate a key like above, configure it in ~/.authorized_keys, and experiment a bit?

@CameronGo
Copy link
Author

@CameronGo CameronGo commented Feb 9, 2018

I'll take a look at trying to generate a DSA key that is 2048 today. In the meantime I thought I'd mention that what makes this sticky is the fact that my SSH client on Ubuntu is able to connect to their SFTP site (if I explicitly enable the DSS host keys) and that clients like WinSCP are able to connect without an issue. This gives the customer the impression that their side of the connection is fine, which technically maybe it is, even if it is non-standard.

In the meantime I thought perhaps posting a redacted WinSCP log for a successful connection may help.
winscplog-redacted.log

In particular this section highlighting the key being used:

. 2018-02-08 17:05:52.370 The first key-exchange algorithm supported by the server is diffie-hellman-group-exchange-sha256, which is below the configured warning threshold.
. 2018-02-08 17:05:52.370 
. 2018-02-08 17:05:52.370 Do you want to continue with this connection? ()
. 2018-02-08 17:05:56.673 Doing Diffie-Hellman group exchange
. 2018-02-08 17:05:56.673 Waiting for the server to continue with the initialization
. 2018-02-08 17:05:56.701 Detected network event
. 2018-02-08 17:05:56.701 Doing Diffie-Hellman key exchange with hash SHA-256
. 2018-02-08 17:05:56.914 Waiting for the server to continue with the initialization
. 2018-02-08 17:05:56.944 Detected network event
. 2018-02-08 17:05:57.380 Verifying host key dss 0xba3fc42b3e97ae42 2e2f3cdde32bcfc1 7135f79f9de3c243 9197a9cb000de632 f288df42f8305c3b ceabb4298d3821a3 1ca7008f4454799a b99f94aa9edbb39f 83df48c7d24c1c25 8ed9d790ad01705f 7c135d5216f2ce24 a9d19e5c59648e97 3555330709b9cb32 15bb2ed8ddd0ef83 d089c5d08231adf6 4e7a93e33f5836cb 46b962bbb89bf32d 861820cc5059e648 209cbbcd1f47fa81 3285e5f106ce0268 081aee85b4bd6350 7268b12e01947f35 ffb874a6460199c3 850b510633ee90d8 8502acf3993cadb6 65e48d10fa196bab 706852b913bac202 e0a8692e031d092e bb192e35085a94c1 2bb260a72396cc24 40986ed575aa5a3b 2b1d9c4f302287d3 ,0xbd06bb5514e8bf17 b74a5311cd622802 ca3aa5ef,0x6e528b5c440b815c 7091335273f8d8b8 96549579885558b7 5f1cbe3b5068ae2c 56c9dd9ebb51f9bc 3414bba311d96b0e 9cc2cd0ce94a5d2b 2cefde3c7252b6a0 4dcd843fba21f666 6915a58a5d32020b fb2ed29d47b97c73 5de663149cfa8acb 163c47643c29ded7 06696a085b742644 7a2fd8a5e9b08d41 e11b8334864d43f4 70f4c0b84cc98e0e 96ad59ed7bef7fed b7f3471b48fc6770 68566d169b58313a 8050725df6cfc4c8 cb84ad486e7f4361 f2881062b645f9fd 495ec200dcdf5acc 75318633b607baa1 eb8abc09725dc273 b913199b118bef2a 19707db7c0ef6c45 a0f9c18f81284626 f6b8c3681d5e0cfd ffaf6df9bf1b459b 901d845bc6ec6dc3 ,0x27773427e739c3ba 4749386c029e141e 7fef515ee72f100d dcfe8582fdef88e7 1493734080fc7ba3 386766a8923cc3ea 6257f599d8c12897 ec0a311991a9e926 d9e3ec884495fd2b ef35a3f49cfd6d6b ffadf6478b2e76f3 c13e926e82bfff2b 6be79ab022853f05 f6a55e7b1adda019 e75536396ab61eca b44fa9f4d6f80414 9338c4d51b1b9b5a ee0769dcec3dbbc4 6e18e0d0c907dd78 4e826f743da9b926 5ca2a40073418946 d5828feb0c35a8b6 2781ef854d77d490 f57fc18a022a6fcc 9a87527a8815e285 a2febf552759dac6 5739cd1f200e3ebd 26fbd38f98086cfc 5b5b5db80f3f2d65 d9587152eafa914e bf45dee2b8da5b14 d4fd49b2bfed763f  with fingerprint ssh-dss 2048 f1:24:2b:a2:df:b9:f6:5c:4b:ba:cd:90:e9:e0:9e:80
. 2018-02-08 17:05:57.392 Host key matches cached key
. 2018-02-08 17:05:57.392 Host key fingerprint is:
. 2018-02-08 17:05:57.392 ssh-dss 2048 f1:24:2b:a2:df:b9:f6:5c:4b:ba:cd:90:e9:e0:9e:80
. 2018-02-08 17:05:57.393 Initialised AES-256 SDCTR client->server encryption
. 2018-02-08 17:05:57.393 Initialised HMAC-SHA-256 client->server MAC algorithm
. 2018-02-08 17:05:57.393 Waiting for the server to continue with the initialization
@ipcjk
Copy link

@ipcjk ipcjk commented Feb 17, 2018

Just for fun and record:

I also run into this issue today and took a look into my key archive. The original ssh.com client created DSA-2048 keys by default back then. Could be people still use an old ssh version :)

joerg@j:~/ssh2/ssh-3.2.9.1/apps/ssh$ ./ssh-keygen2 Generating 2048-bit dsa key pair 19 o.oOo.oOOo.o

The latest version goes for rsa by default:
ssh-keygen-g3 -v Generating 2048-bit rsa key pair 3 o.oOo.oOo.oO Key generated.

@42wim
Copy link

@42wim 42wim commented Nov 18, 2018

Got the same issue on trying to connect to HPE BladeSystem c-Class Onboard Administrator it's running OpenSSH_OA. So it's definitely out there in the wild :-)

@ncw
Copy link
Contributor

@ncw ncw commented May 15, 2020

We've just come across this with rclone and some but not all rsync.net servers.

Here is the forum thread for more info

This reproduces it

$ rclone lsf --sftp-host ch-s010.rsync.net --sftp-user test --sftp-ask-password :sftp:
Enter SFTP password: 
2020/05/15 09:37:54 Failed to create file system for ":sftp:": NewFs: couldn't connect SSH: ssh: handshake failed: ssh: unsupported DSA key size 2048

The server identifies itself as

SSH-2.0-OpenSSH_7.5-hpn14v5 FreeBSD-openssh-portable-7.5.p1_1,1
@ncw
Copy link
Contributor

@ncw ncw commented May 16, 2020

I made a small patch to x/crypto/ssh and one of my users confirmed that it fixes the problem for them.

diff --git a/golang.org/x/crypto/ssh/keys.go b/golang.org/x/crypto/ssh/keys.go
index 06f537c13..77d7b66fa 100644
--- a/vendor/golang.org/x/crypto/ssh/keys.go
+++ b/vendor/golang.org/x/crypto/ssh/keys.go
@@ -412,7 +412,7 @@ func checkDSAParams(param *dsa.Parameters) error {
        // SSH specifies FIPS 186-2, which only provided a single size
        // (1024 bits) DSA key. FIPS 186-3 allows for larger key
        // sizes, which would confuse SSH.
-       if l := param.P.BitLen(); l != 1024 {
+       if l := param.P.BitLen(); l != 1024 && l != 2048 {
                return fmt.Errorf("ssh: unsupported DSA key size %d", l)
        }

Is there any interest in merging a proper version of the above? I'd need to do a bit of reasearch into exactly what FIPS 186-3 says.

@gromita
Copy link

@gromita gromita commented Jul 3, 2020

I made a small patch to x/crypto/ssh and one of my users confirmed that it fixes the problem for them.

diff --git a/golang.org/x/crypto/ssh/keys.go b/golang.org/x/crypto/ssh/keys.go
index 06f537c13..77d7b66fa 100644
--- a/vendor/golang.org/x/crypto/ssh/keys.go
+++ b/vendor/golang.org/x/crypto/ssh/keys.go
@@ -412,7 +412,7 @@ func checkDSAParams(param *dsa.Parameters) error {
        // SSH specifies FIPS 186-2, which only provided a single size
        // (1024 bits) DSA key. FIPS 186-3 allows for larger key
        // sizes, which would confuse SSH.
-       if l := param.P.BitLen(); l != 1024 {
+       if l := param.P.BitLen(); l != 1024 && l != 2048 {
                return fmt.Errorf("ssh: unsupported DSA key size %d", l)
        }

Is there any interest in merging a proper version of the above? I'd need to do a bit of reasearch into exactly what FIPS 186-3 says.

Hello @ncw, I run into the same problem. What's the workaround that you adopted? Working with your own fork + patch?

Many Thanks

@ncw
Copy link
Contributor

@ncw ncw commented Jul 4, 2020

I run into the same problem. What's the workaround that you adopted? Working with your own fork + patch?

The user has been happy running on the patched version I sent them - I haven't forked the library.

It would be nice to get this very small patch into the library - what do you think @hanwen ?

@cyanide1323
Copy link

@cyanide1323 cyanide1323 commented Jul 21, 2020

@ncw

I run into the same problem. What's the workaround that you adopted? Working with your own fork + patch?

The user has been happy running on the patched version I sent them - I haven't forked the library.

It would be nice to get this very small patch into the library - what do you think @hanwen ?

Hey @hanwen Is it possible to include the changes mentioned by @ncw. Can you please look at these changes urgently?

@hanwen
Copy link
Contributor

@hanwen hanwen commented Jul 21, 2020

Hey, I've stepped down as maintainer of the Go SSH package. Please talk to @FiloSottile

@ncw
Copy link
Contributor

@ncw ncw commented Jul 21, 2020

I made a small patch here #23751 (comment) which my users say fixes this problem @FiloSottile

I've no idea whether it is sensible though so some guidance here would be much appreciated!

@gromita
Copy link

@gromita gromita commented Jul 21, 2020

I made a small patch here #23751 (comment) which my users say fixes this problem @FiloSottile

I've no idea whether it is sensible though so some guidance here would be much appreciated!

Hi, I've been using @ncw code as workaround for the time being to connect to the ssh server running in target device (we've no control on it to eventually change configuration).

@FiloSottile
Copy link
Member

@FiloSottile FiloSottile commented Jul 21, 2020

I was honestly hoping to remove DSA support altogether, in part because we only support insecure key sizes, so to reduce the attack surface (which has led to client and server DoS in the past). I guess not allowing larger key sizes is a bit contradictory though.

First though I would like to figure out two things:

  1. how did these servers end up with a 2048-bit key when ssh-keygen only supports 1024?
  2. do these servers only have a DSA key, or are we selecting DSA even if other alternatives are available?

Hopefully what's happening is that the server has other keys and if we drop DSA support it will just pick the better ones.

@FiloSottile
Copy link
Member

@FiloSottile FiloSottile commented Jul 21, 2020

$ rclone lsf --sftp-host ch-s010.rsync.net --sftp-user test --sftp-ask-password :sftp:

Yep, there we go, this server gives priority to DSA but also has an Ed25519 key.

debug2: host key algorithms: ssh-dss,ssh-ed25519

If we were to just deprioritize or remove DSA, this would just work.

The problem is that we don't have a host key upgrade mechanism: if some application only accepts the DSA key in HostKeyCallback, we'll break connections by switching. If we only deprioritize we can get away with calling the callback on every key until one works, but I really wanted to remove DSA.

On the other hand, anyone currently using DSA is using an insecure key size, so there's an argument for the security exception to the backwards compatibility policy.

Finally, since OpenSSH removed DSA support, connecting to these servers using an existing known_hosts is currently broken, because the key in known_hosts will not be the DSA one.

I think the conclusion is to remove DSA, which will actually fix most of these servers, and will only break connections that would have otherwise been insecure. I will file a proposal.

@ncw
Copy link
Contributor

@ncw ncw commented Jul 21, 2020

I think the conclusion is to remove DSA, which will actually fix most of these servers, and will only break connections that would have otherwise been insecure. I will file a proposal.

What would the patch to x/crypto/ssh look like to do that? If there was a simple one then I could get the affected users to try it and we could get some feedback as to whether that will fix their problems.

I'm sympathetic to removing DSA, but I don't know how many existing users that will break - has anyone done an internet wide scan of supported SSH auth mechanisms I wonder? I found this https://github.com/ofalk/scanssh/wiki plus a paper from 2000...

@FiloSottile
Copy link
Member

@FiloSottile FiloSottile commented Jul 21, 2020

What would the patch to x/crypto/ssh look like to do that? If there was a simple one then I could get the affected users to try it and we could get some feedback as to whether that will fix their problems.

Haven't tested it, but it should be just a matter of deleting this switch case.

https://github.com/golang/crypto/blob/948cd5f35899cbf089c620b3caeac9b60fa08704/ssh/keys.go#L62-L63

I'm sympathetic to removing DSA, but I don't know how many existing users that will break - has anyone done an internet wide scan of supported SSH auth mechanisms I wonder?

OpenSSH dropped support five years ago. I am not particularly worried.

@gromita
Copy link

@gromita gromita commented Jul 22, 2020

What would the patch to x/crypto/ssh look like to do that? If there was a simple one then I could get the affected users to try it and we could get some feedback as to whether that will fix their problems.

Haven't tested it, but it should be just a matter of deleting this switch case.

https://github.com/golang/crypto/blob/948cd5f35899cbf089c620b3caeac9b60fa08704/ssh/keys.go#L62-L63

I'm sympathetic to removing DSA, but I don't know how many existing users that will break - has anyone done an internet wide scan of supported SSH auth mechanisms I wonder?

OpenSSH dropped support five years ago. I am not particularly worried.

Hello @FiloSottile, I tried the proposed change and I can say that is working for some devices that required @ncw patch but not working for all. Getting some errors: ssh: handshake failed: ssh: unknown key algorithm: ssh-dss

Code used:

crypto/ssh/keys.go
@@ -59,8 +59,6 @@ func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err
        switch algo {
        case KeyAlgoRSA:
                return parseRSA(in)
-       case KeyAlgoDSA:
-               return parseDSA(in)
        case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
                return parseECDSA(in)
        case KeyAlgoSKECDSA256:
@@ -412,7 +410,7 @@ func checkDSAParams(param *dsa.Parameters) error {
        // SSH specifies FIPS 186-2, which only provided a single size
        // (1024 bits) DSA key. FIPS 186-3 allows for larger key
        // sizes, which would confuse SSH.
-       if l := param.P.BitLen(); l != 1024 && l != 2048 {
+       if l := param.P.BitLen(); l != 1024 {
                return fmt.Errorf("ssh: unsupported DSA key size %d", l)
        }

Thanks,
Regards

GL

@ncw
Copy link
Contributor

@ncw ncw commented Jul 22, 2020

I just read through the original thread on the rclone forum and the user said

Support at rsync.net suggested forcing the use of ssh-ed25519 by using the HostKeyAlgorithms option.

So @FiloSottile your suggestion of removing DSA seems like a good one and fixes the two known cases we've come across!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
10 participants
You can’t perform that action at this time.