Enabling the new ML-DSA44 Ed25519 hybrid Post-Quantum Cryptography host and client keys

New and shiny algorithms
In OpenSSH 10.4, the project added a new type of host and client key. It is a hybrid of the existing Ed25519 key with added ML-DSA44. For successful connections, both the Ed25519 and the ML-DSA44 keys must be verified. This provides protection against, not yet capable enough, quantum-computers and against possible failure of the, still relatively new, ML-DSA algorithms.
Default builds of OpenSSH include the algorithms, but does not enable them by default as this is still considered experimental.
NOTE: I configure my OpenSSH build --without-openssl, it is not needed for this new algorithm.
I've created a patch and a PR for the FreeBSD port.
Building your own OpenSSH
On FreeBSD, I rely on the security/openssh-portable port, on other systems, I build OpenSSH myself.
mkdir -p ~/src
cd ~/src
wcurl https://ftp.openbsd.org/pub/openbsd/openssh/openssh-10.5p1.tar.gz
tar -xf openssh-10.5p1.tar.gz
cd openssh-10.5p1
./configure --without-openssl --sysconfdir=/usr/local/etc/ssh
make
sudo make install
You'll find ssh in /usr/local/bin, sshd in /usr/local/sbin, and the configuration files and host keys in /usr/local/etc/ssh.
Configuring your install
For both ssh_config and sshd_config you can use the Include keyword.
Create the include dirs and add the include lines to the ssh and sshd config files.
sudo install -d -o0 -g0 -m755 /usr/local/etc/ssh/ssh_config.d
sudo install -d -o0 -g0 -m750 /usr/local/etc/ssh/sshd_config.d
echo "Include /usr/local/etc/ssh/ssh_config.d/*.conf" | sudo tee -a /usr/local/etc/ssh/ssh_config
echo "Include /usr/local/etc/ssh/sshd_config.d/*.conf" | sudo tee -a /usr/local/etc/ssh/sshd_config
If you want to re-use your default ssh configuration, include them in ssh_config and sshd_config like so
echo "Include /etc/ssh/ssh_config" | sudo tee -a /usr/local/etc/ssh/ssh_config
echo "Include /etc/ssh/sshd_config" | sudo tee -a /usr/local/etc/ssh/sshd_config
Note that this includes the base configuration last and that OpenSSH configuration is "first obtained value will be used".
Anything you have configured in /usr/local/etc/ssh will override configuration from /etc/ssh.
You'll need to generate the new ML-DSA44/Ed25519 keys for server and client.
Add the mldsa44_ed25519.conf files that enable the ML-DSA44/Ed25519 algorithms to your configuration.
sudo ssh-keygen -t mldsa44-ed25519 -f /usr/local/etc/ssh/ssh_host_mldsa44_ed25519_key -N ''
As a user, you can generate your client key
ssh-keygen -t mldsa44-ed25519
Now we can enable ML-DSA44/Ed25519. These files go into the included directories, so you can quickly enable/disable them by renaming the file.
We're using the + modifier so they're added to the existing or default configuration.
# sshd_config
cat <<EOF | sudo tee -a /usr/local/etc/ssh/sshd_config.d/mldsa44_ed25519.conf
HostKey /usr/local/etc/ssh/ssh_host_mldsa44_ed25519_key
HostKeyAlgorithms +ssh-mldsa44-ed25519-cert-v01@openssh.com,ssh-mldsa44-ed25519@openssh.com
PubkeyAcceptedAlgorithms +ssh-mldsa44-ed25519-cert-v01@openssh.com,ssh-mldsa44-ed25519@openssh.com
CASignatureAlgorithms +ssh-mldsa44-ed25519@openssh.com
HostbasedAcceptedAlgorithms +ssh-mldsa44-ed25519-cert-v01@openssh.com,ssh-mldsa44-ed25519@openssh.com
EOF
# ssh_config
cat <<EOT | sudo tee -a /usr/local/etc/ssh/ssh_config.d/mldsa44_ed25519.conf
HostKeyAlgorithms +ssh-mldsa44-ed25519-cert-v01@openssh.com,ssh-mldsa44-ed25519@openssh.com
PubkeyAcceptedAlgorithms +ssh-mldsa44-ed25519-cert-v01@openssh.com,ssh-mldsa44-ed25519@openssh.com
CASignatureAlgorithms +ssh-mldsa44-ed25519@openssh.com
HostbasedAcceptedAlgorithms +ssh-mldsa44-ed25519-cert-v01@openssh.com,ssh-mldsa44-ed25519@openssh.com
Verify
Verify your changes using the ssh -G and sshd -T commands. They show the resulting configuration, and possibly errors stemming from the base OpenSSH configuration.
Examples below are from an Ubuntu 24.04 host.
# Verify client configuration
$ /usr/local/bin/ssh -G localhost | grep algorithm
/etc/ssh/ssh_config line 52: Unsupported option "gssapiauthentication"
hostkeyalgorithms **ssh-mldsa44-ed25519**@openssh.com,ssh-ed25519
hostbasedacceptedalgorithms ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519,sk-ssh-ed25519@openssh.com
kexalgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org
casignaturealgorithms ssh-ed25519,sk-ssh-ed25519@openssh.com
pubkeyacceptedalgorithms **ssh-mldsa44-ed25519**@openssh.com
# Verify server configuration
$ sudo /usr/local/sbin/sshd -T | grep -E '(Algorithm|HostKey.*mldsa)'
/etc/ssh/sshd_config line 108: Unsupported option UsePAM
KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org
CASignatureAlgorithms ssh-ed25519,sk-ssh-ed25519@openssh.com,ssh-mldsa44-ed25519@openssh.com
HostbasedAcceptedAlgorithms ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519,sk-ssh-ed25519@openssh.com,ssh-mldsa44-ed25519-cert-v01@openssh.com,ssh-mldsa44-ed25519@openssh.com
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519,sk-ssh-ed25519@openssh.com,ssh-mldsa44-ed25519-cert-v01@openssh.com,ssh-mldsa44-ed25519@openssh.com
PubkeyAcceptedAlgorithms ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519,sk-ssh-ed25519@openssh.com,ssh-mldsa44-ed25519-cert-v01@openssh.com,ssh-mldsa44-ed25519@openssh.com
HostKey /usr/local/etc/ssh/ssh_host_mldsa44_ed25519_key
Both show "Unsupported option" for things that have not been enabled in the build, these are not fatal.
Compare the output with the regular ssh -G localhost and sshd -T commands.
You may need to add/modify your GIT_SSH or GIT_SSH_COMMAND environment variable to make git use it.
Activate
Client / ssh
Set an alias for ssh in the system profile, your personal profile or shell rc-file.
Server / sshd
Take precautions if you're doing this via an ssh connection: keep an ssh session to the server open, existing ssh sessions don't drop when restarting sshd.
On FreeBSD, disable sshd, enable openssh, enable mldsa44-ed15519.
sysrc sshd_enable="NO"
sysrc openssh_enable="YES"
sysrc openssh_mldsa44_ed25519_enable="YES"
service sshd onestop
service openssh start
On Systemd/Linux systems, I'm a clueless BSD guy. Overrides didn't work, copying the ssh.service unit file didn't either. If you have a working solution, let me know!
