A pure-Haskell SSH server library

#5Support more secure, non-deprecated key-exchange system

diffie-hellman-group1-sha1 has been deprecated since OpenSSH 7.0 so currently this needs to be added to .ssh/config to use darcsden:

Host hub.darcs.net
    KexAlgorithms diffie-hellman-group1-sha1

diffie-hellman-group-exchange-sha256 is not deprecated and seems to be the closest to diffie-hellman-group1-sha1 so it would likely be the easiest key exchange system to implement and replace diffie-hellman-group1-sha1 on darcsden.

http://irclog.perlgeek.de/darcs/2015-09-16#i_11224700

https://www.ietf.org/rfc/rfc4419.txt

    • summary changed to "Support more secure, non-deprecated key-exchange system"
  • It's come to my attention that curve25519-sha256 is more secure than diffie-hellman-group-exchange-sha256 and already has Haskell implementations:

    https://github.com/thoughtpolice/hs-nacl/blob/master/tests/Curve25519.hs

    • added tag kex
  • Another wrapper for curve25519 : https://hackage.haskell.org/package/curve25519

  • "The key exchange procedure is similar to the ECDH method described in chapter 4 of [RFC5656], though with a different wire encoding used for public values and the final shared secret. Public ephemeral keys are encoded for transmission as standard SSH strings.

    The protocol flow, the SSH_MSG_KEX_ECDH_INIT and SSH_MSG_KEX_ECDH_REPLY messages, and the structure of the exchange hash are identical to chapter 4 of [RFC5656]."

    https://tools.ietf.org/html/draft-josefsson-ssh-curves-04#section-2

    https://tools.ietf.org/html/rfc5656#section-4

    For curve25519-sha256@libssh.org the conversation should look like:

    The client sends:

      byte     SSH_MSG_KEX_ECDH_INIT
      string   Q_C, client's ephemeral public key octet string

    The server responds with:

      byte     SSH_MSG_KEX_ECDH_REPLY
      string   K_S, server's public host key
      string   Q_S, server's ephemeral public key octet string
      string   the signature on the exchange hash

    The exchange hash H is computed as the hash of the concatenation of the following.

      string   V_C, client's identification string (CR and LF excluded)
      string   V_S, server's identification string (CR and LF excluded)
      string   I_C, payload of the client's SSH_MSG_KEXINIT
      string   I_S, payload of the server's SSH_MSG_KEXINIT
      string   K_S, server's public host key
      string   Q_C, client's ephemeral public key octet string
      string   Q_S, server's ephemeral public key octet string
      mpint    K,   shared secret

    For diffie-hellman-group1-sha1 it looks like this:

    First, the client sends the following:

      byte      SSH_MSG_KEXDH_INIT
      mpint     e

    The server then responds with the following:

      byte      SSH_MSG_KEXDH_REPLY
      string    server public host key and certificates (K_S)
      mpint     f
      string    signature of H

    The (exchange) hash H is computed as the HASH hash of the concatenation of the following:

      string    V_C, the client's identification string (CR and LF excluded)
      string    V_S, the server's identification string (CR and LF excluded)
      string    I_C, the payload of the client's SSH_MSG_KEXINIT
      string    I_S, the payload of the server's SSH_MSG_KEXINIT
      string    K_S, the host key
      mpint     e, exchange value sent by the client
      mpint     f, exchange value sent by the server
      mpint     K, the shared secret

    https://tools.ietf.org/html/rfc4253#section-8

  • For those who missed it on irc yesterday, ssh with the curve25519-sha256@libssh.org kex now works (most of the time). When it is not working, it may have to do with a key or signature not being padded with zeros to 32 bytes or something. It could also have to do with when the ssh client decides to rekey, but I think this is less likely. I will dig into this more, checking the size of each component of the exchange hash and all the keys.

    http://hub.darcs.net/pointfree/ssh-curve25519-sha256

    Next steps:

    @simon and myself both seem to think diffie-hellman-group1-sha1 support should just be dropped because it is not very secure anymore, adds sloc, and OpenSSH 7.0 has disabled it by default. Does anyone need it?

    By the way, cabal test will still not work because it depends on libssh2-hs which depends on libssh2 which apparently does not offer the curve25519-sha256 kex. libssh does support curve25519-sha256@libssh.org but I can't find libssh (client) haskell bindings.

    https://www.libssh2.org/libssh2-vs-libssh.html

    Although, there are bindings to the server part of libssh here. They could be adapted.

  • What's the status of this ? Could it be merged and released as 0.4 (or it might be a good time to go to 1.0, since there seems to be quite a few changes ?)

  • For future reference as to why these changes haven't been merged yet.

    • fr33domlover's refactorings diverged quite a lot from the pointfree/ssh-curve25519-sha256 fork.
    • libssh2 doesn't support curve25519-sha256 so the tests won't work (libssh supports that kex, libssh2 doesn't).
    • The darcsden ssh server would have to be updated to support fr33domlover's changes.
    • fr33domlover's changes got merged into ganesh/ssh first.
    • There was some talk of using ssh-hans instead of this, or at least using pieces from ssh-hans. https://github.com/glguy/ssh-hans ssh-hans has a both a client and server ssh implementation and support for many kex's etc.
    • The darcsden ssh server would have to be updated to use ssh-hans.
    • ssh-hans only supports the OpenSSH key format, generated with the -o option to ssh-keygen. I don't think existing darcsden/darcshub keys are in that format.

    One short term option would be to deploy pointfree/ssh-curve25519-sha256 just to hub.darcs.net until the above issues get resolved, for the sake of user experience and security.

  • @pointfree: do you have tests passing in your branch ? After building it with lts-8.4, I get:

    ~/src/ssh_curve25519$ stack test
    ssh-0.3.2: test (suite: ssh-test)
    
    Tests
      With server
        Single key auth tests
          Check auth with id_dsa
            Works:                                     FAIL
              Exception: KEX_FALIURE
            Fails with broken private key:             FAIL
              Exception: KEX_FALIURE
          Check auth with id_rsa_1024
            Works:                                     FAIL
              Exception: KEX_FALIURE
            Fails with broken private key:             FAIL
              Exception: KEX_FALIURE
          Check auth with id_rsa_2048
            Works:                                     FAIL
              Exception: KEX_FALIURE
            Fails with broken private key:             FAIL
              Exception: KEX_FALIURE
          Check auth with id_rsa_4096
            Works:                                     FAIL
              Exception: KEX_FALIURE
            Fails with broken private key:             FAIL
              Exception: KEX_FALIURE
          Check auth with id_rsa_test
            Works:                                     FAIL
              Exception: KEX_FALIURE
            Fails with broken private key:             FAIL
              Exception: KEX_FALIURE
          Check auth with id_rsa_test2
            Works:                                     FAIL
              Exception: KEX_FALIURE
            Fails with broken private key:             FAIL
              Exception: KEX_FALIURE
        Check auth failure with wrong key:             FAIL
          Exception: KEX_FALIURE
      Signatures
        signatures from sign work with verify:         OK (1.35s)
          +++ OK, passed 100 tests.
        mutated signatures from sign fail with verify: OK (1.42s)
          +++ OK, passed 100 tests.
        random signatures fail with verify:            OK (0.04s)
          +++ OK, passed 100 tests.
    
    13 out of 16 tests failed (2.88s)
    
    Test suite failure for package ssh-0.3.2
        ssh-test:  exited with: ExitFailure 1
    Logs printed to console
  • Doh, you mentioned that, disregard.

  • darcs hub is now running the pointfree/ssh-curve25519-sha256 branch, to make life easier for darcs hub users. I hope it will be merged upstream soon, and tests made to not fail. Thanks!

  • We should also note that SHA1 has been publicly broken this year, https://en.wikipedia.org/wiki/SHA-1