The recent release of OpenSSH 6.5 had many convincing new features to make me update to it early, quoting from the release notes:
- support for key exchange using elliptic-curve Diffie–Hellman in Daniel Bernstein’s Curve25519
- support for Ed25519 as a public key type
- a new private key format that uses a bcrypt KDF to better protect keys at rest
- a new transport cipher
chacha20-poly1305@openssh.com
that combines Daniel Bernstein’s ChaCha20 stream cipher and Poly1305 MAC to build an authenticated encryption mode
Since OpenSSH 5.7, there is support for ECDSA keys according to RFC5656. The problem with this schema is that it uses NIST curves generally. Due to recent events, everyone is (rightfully) more paranoid now, and there are reasons to consider these curves to be problematic. Thus, I decided to disable support for ECDSA host keys and use the superior ED25519 scheme for new keys.
However, I also need to access many machines which don’t run the latest version of OpenSSH, but for these we can at least make use of the new, safer public key format.
First, I will show how to update your OpenSSH installation to make use of the new features, and then I’ll explain what else I had to do to make everything work correctly.
Upgrading OpenSSH
Arch is, at the time of writing, providing binaries in “testing”, but plucking a single package is easy:
# pacman -U http://mirror.de.leaseweb.net/archlinux/testing/os/x86_64/openssh-6.5p1-1-x86_64.pkg.tar.xz
After merging configuration files (if required), we edit
/etc/ssh/sshd_config
and spell out the HostKey
s to disable the
built-in defaults, which include ECDSA.
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
Upon restarting SSH, a new ED25519 hostkey will be generated. Using ignite:
# sv restart sshd
Essentially, that’s it. Let’s check that the ECDSA hostkey is disabled:
% ssh-keyscan -t ecdsa,ed25519 localhost
# localhost SSH-2.0-OpenSSH_6.5
no hostkey alg
# localhost SSH-2.0-OpenSSH_6.5
localhost ssh-ed25519 AAAA...
(AFAIU, ECDSA user keys in authorized_keys
will still work. It’s
your task to replace them with ED22519 ones, I have found no way to
blacklist them.)
We continue by creating a new ED25519 key for the user:
% ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/chris/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
...
For testing, we can add it to the locally accepted keys:
% cat .ssh/id_ed25519.pub >>.ssh/authorized_keys
Finally, we can test it:
% ssh chris@localhost
Enter passphrase for key '/home/chris/.ssh/id_ed25519':
It seems to work! (Perhaps you’ll see an update of the fingerprint if
you had the ECDSA one saved in .ssh/known_hosts
.)
I was happy about that until I realized that ssh
asked for the
passphrase, and not my gnome-keyring-daemon
… which brings us to
part two of this post.
Migrating to ssh-agent and the IdentityPersist patch
Since new ED25519 keys are always stored in the new bcrypt format,
they won’t work (as of right now) with SSH agents that don’t support
it (I know of gnome-keyring
and mate-keyring
; gpg-agent
stores
the key itself, anyway). Essentially, only plain ssh-agent
supports
it, but I used to hate ssh-agent
since it doesn’t support adding
keys upon use: gnome-keyring
will ask for the password and keep the
key unlocked. Since I try to keep my keys
locked
when I’m not using them, I don’t want to keep them unlocked in every
session, and neither unlock them manually, because that is
inconvenient.
Luckily, I found this
patch which adds
the key automatically. I hope it gets accepted, because it is very
useful. I couldn’t wait and patched OpenSSH
myself.
With this tiny patch, I could finally drop my use of gnome-keyring
,
which is one more step towards a GTK3-free desktop.
I run ssh-agent
from my .xinitrc
:
eval $(ssh-agent -s)
xscreensaver-ssh-helper &
Now, we can convert our old keys to the new storage format:
% ssh-keygen -p -o -f ~/.ssh/id_dsa
Enter old passphrase:
Key has comment 'id_dsa'
Enter new passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved with the new passphrase.
The key file should now start with -----BEGIN OPENSSH PRIVATE KEY-----
.
The public key format is unchanged.
For the IdentityPersist patch, we need to add a line to .ssh/config
,
stating the lifetime of the key (or true
for infinity):
IdentityPersist 300
Now, we can try everything together:
% ssh myhost
Enter passphrase for key '/home/chris/.ssh/id_dsa':
Identity added: /home/chris/.ssh/id_dsa (id_dsa)
...
Another SSH connect within the next 5 minutes will connect without asking for a password.
I noticed one more difference between gnome-keyring
and ssh-agent
:
gnome-keyring
would unlock any key that has a *.pub
in ~/.ssh
, while
ssh-agent
requires an explicit list in .ssh/config
:
IdentityFile ~/.ssh/id_ed25519
IdentityFile ~/.ssh/id_dsa
IdentityFile ~/.ssh/id_work
Fixing Gnus
I had one final issue, which is rather niche: My newsreader gnus
connects to my NNTP feed via a SSH hop. The configuration looked like this:
(setq gnus-select-method
'(nntp "localhost"
(nntp-address "myshellhost")
(nntp-rlogin-program "ssh")
(nntp-open-connection-function nntp-open-rlogin)
(nntp-end-of-line "\n")
(nntp-rlogin-parameters ("nc" "mynntpserver" "nntp"))))
A configuration like this will fail, because Emacs runs this ssh
process with a pty
, and there ssh
will stupidly ask for the
password to unlock (if required). But I learned this
configuration is outdated anyway, and the recommended version using
nntp-open-via-rlogin-and-netcat
works correctly, and asks for the
password (if required) using x11-ask-sshpass
. This is mentioned in
a comment in nntp.el
, so I’m not the first on to stumble on this.
A fixed version of above would be:
(setq gnus-select-method
'(nntp "localhost"
(nntp-address "mynntpserver")
(nntp-via-address "myshellserver")
(nntp-via-rlogin-command "ssh")
(nntp-via-rlogin-command-switches ("-C"))
(nntp-open-connection-function nntp-open-via-rlogin-and-netcat)))
Enjoy your safer OpenSSH setup!
NP: Slime—A.C.A.B.