A common application of security keys is as a hardware-backed SSH key. I have lately been curious as to whether it would be possible to use one as an SSH host key. It seems like it should be straightforward enough, it’s just another SSH key after all, if it works as a client identity key, why wouldn’t it work as a host key?

So I had a mess around with this, but haven’t been able to get it to work. Using sudo ssh-keygen -t ed25519-sk -O no-touch-required (or with -O resident as well) just ends up with the connection being refused and the auth log showing sshd: no hostkeys available -- exiting.

I had a look at the source for OpenSSH, but after 10 minutes of digging can find no indication of why it would cosider this to not be an ED25519_SK key, which the code explicitly accepts as a host key.

If anyone has any ideas for what is going wrong or has better luck, I would love to hear the details.

(Posted in selfhosted because this is the most prominent community that talks about ssh I can find, somewhat unsurprisingly)

EDIT to emphasize that this is talk about host keys like /etc/ssh/ssh_host_ed25519, not client keys. My attempts to make a working “ssh_host_ed25519_sk” are what I am reporting on here.

UPDATE: It works! So it ended up being a combination of a couple of confusing things, I believe.

One is that there is an old bug that means that ssh-keygen -K will accidentally make keys require user interaction again, which sshd then ignores as though they don’t exist. I believe this is what I was seeing previously, as I had been messing around with the keys elsewhere to verify them and then used ssh-keygen -K as a convenient way to drop them into /etc/ssh. But that alone would not have been enough to stop me, as I did try generating them in-place…

But I generated them with the name ssh_host_ed25519_sk_key, following the naming convention of id_ed25519_sk, and the fact that ED25519_SK is listed as a different enum value in the OpenSSH source. However, even upon stripping out every other key and enabling debug logging, it simply never even tried to touch that file as far as I could tell. So as an experiment I renamed it to ssh_host_ed25519_key as though it is a normal key, and that immediately worked exactly as expected!

So my final steps to get this working were:

sudo ssh-keygen -t ed25519_sk -O resident -O no-touch-required
Generating public/private ed25519-sk key pair.
You may need to touch your authenticator to authorize key generation.
Enter PIN for authenticator: 
Enter file in which to save the key (/root/.ssh/id_ed25519_sk): /etc/ssh/ssh_host_ed25519_key
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /etc/ssh/ssh_host_ed25519_key
Your public key has been saved in /etc/ssh/ssh_host_ed25519_key.pub

Testing sshing into the host then works flawlessly as long as the security key is plugged in, and the connection is rejected the moment it is unplugged.

So this has been an interesting little experiment. Notably, because of the requirement for interaction with the security key, this will mess up anything else (like age) that uses the key directly as a cryptographic identity and isn’t smart enough to reach out to the security key.

Given how long it took me to find any information about this, hopefully this will serve someone well in future.

    • gozz@lemmy.worldOP
      link
      fedilink
      English
      arrow-up
      8
      ·
      4 days ago

      I possibly should put greater emphasis on the fact that I am talking about the host key, not the client key. This guide is for a client identity key. I am talking about host keys as you find in /etc/ssh/ssh_host_ed25519, etc.

      • jet@hackertalks.com
        link
        fedilink
        English
        arrow-up
        3
        ·
        edit-2
        4 days ago

        Can you explain to me the workflow you have envisioned for the host identity key in /etc/ssh being keyed of a FIDO2 secure element? You plug a secure element into a server?

        Sounds like you want something like a HSM that integrates into your sshd to pull the certificates. Even then you have the chicken and egg problem, how do you identify the hardware to the HSM? You need some trusted boot environment, and now your down into vender specific implementations to “trust” the booted hardware.

        • gozz@lemmy.worldOP
          link
          fedilink
          English
          arrow-up
          2
          ·
          4 days ago

          Yeah, the rough idea is to use any old FIDO2 key as a USB HSM. Not necessarily looking for a very practical solution (the easy fix would be to just encrypt the drive), but curious. What inspired this, though not necessarily the final application, is Nix secret distribution tools that use the host key as the secret recipient. This means that theoretically if you have the host identity tied to an external HSM or similar you could have the same image deploy as different machines based on what security key you have plugged in.

          • jet@hackertalks.com
            link
            fedilink
            English
            arrow-up
            2
            ·
            4 days ago

            Fair enough;

            Do a dry run for a CLIENT key, make sure you have the libfido2 middleware installed and working; Ensure you have set your sshd_config file properly with no-touch-required

            From the documentation " Note: not all tokens support disabling the touch requirement." so do a test client side before banging your head on it.

            • gozz@lemmy.worldOP
              link
              fedilink
              English
              arrow-up
              2
              ·
              4 days ago

              Got the client working (mostly) without issues again, though trying to imitate my process for host keys as closely as possible I did encounter some weirdness that led me to this open bug: https://bugzilla.mindrot.org/show_bug.cgi?id=3355 So that may be the source of my issues… If they keys I was using suddenly were secretly requiring touch, it would explain a lot. I can’t right now but I will do another experiment with host keys when I can. Still would love to see if anyone else is able to reproduce this behaviour or get it working.

            • gozz@lemmy.worldOP
              link
              fedilink
              English
              arrow-up
              2
              ·
              4 days ago

              I previously have had no issues using this as a client key, but honestly I wouldn’t put it past myself to have picked the wrong key and not noticed. Maybe I will give it another try, but I don’t think that’s it.

      • Natanael@slrpnk.net
        link
        fedilink
        English
        arrow-up
        1
        arrow-down
        1
        ·
        edit-2
        4 days ago

        You don’t want FIDO2 security tokens for that, use an OpenPGP applet (works with some Yubikeys and with many programmable smartcards). Much more practical for authenticating a server.

        BTW we have a lot of cryptography experts in www.reddit.com/r/crypto (yes I know, I’m trying to get the community moved, I’ve been moderating it for a decade and it’s a slow process)

        • gozz@lemmy.worldOP
          link
          fedilink
          English
          arrow-up
          2
          ·
          4 days ago

          I am familiar with these alternatives. My experiment was specific in wanting FIDO2 and I ended up figuring out the issue. It was the intersection of a couple of weird behaviours that made debugging very confusing, but it works exactly as I expected it would once those are resolved. I guess we can consider this a proof of concept that you can indeed use FIDO2 tokens as an external SSH host key (though as I said below whether this is practically useful is another matter entirely).

          • Natanael@slrpnk.net
            link
            fedilink
            English
            arrow-up
            1
            arrow-down
            1
            ·
            edit-2
            4 days ago

            Your workaround is precisely why I said “more practical”. Any updates to your tooling might break it because it’s not an expected usecase

  • xylogx@lemmy.world
    link
    fedilink
    English
    arrow-up
    4
    arrow-down
    2
    ·
    4 days ago

    What type of key do you have. Yubikey 5 supports multiple protocols including some you can use with SSH:

    • Multi-protocol: YubiKey 5 Series is the most versatile security key supporting multiple authentication protocols including FIDO2/WebAuthn (hardware bound passkey), FIDO U2F, Yubico OTP, OATH-TOTP, OATH-HOTP, Smart card (PIV) and OpenPGP.

    SSH would need to implement webauthn to support FIDO.

    • xylogx@lemmy.world
      link
      fedilink
      English
      arrow-up
      2
      ·
      4 days ago

      Looks like this happened:

      OpenSSH server has had built-in support for WebAuthn keys since 8.2.

  • ricecake
    link
    fedilink
    English
    arrow-up
    3
    arrow-down
    2
    ·
    4 days ago

    Unfortunately, I think you’re going to run into trouble because fido authenticators are geared towards working as user authenticators rather than as device authenticators.
    It certainly should be possible from a technical perspective, but implementation-wise, it’s very likely that the code focuses on making fido devices work with client keys, and using tpms for host keys, since that’s much more focused on headless server functionality.

    Oval peg in a round hole.

    • Oisteink@feddit.nl
      link
      fedilink
      English
      arrow-up
      2
      ·
      4 days ago

      Nah - storing cryptographic key pairs is a supported and valid use-case for fido2

      • ricecake
        link
        fedilink
        English
        arrow-up
        1
        ·
        4 days ago

        It wasn’t the crypto key pair part I was referring to, it was the part where fido is geared towards interactive user auth, not non-interactive storage.
        It wouldn’t have surprised me if the ssh devs hadn’t put implementing fido support for host keys high in the development list, or that it was tricky to find documentation for. Using something like a tpm is the more typical method.

        There’s no technical reason it can’t work, and the op got it to work so clearly the implementation supports it, but that doesn’t mean it’s the most expected setup, which means it might have unexpected gaps in functionality or terrible documentation.

        • Oisteink@feddit.nl
          link
          fedilink
          English
          arrow-up
          1
          ·
          4 days ago

          Yeah - i mistook it for user keys, not host. Im guessing they used piv/smart-card and not fido, as fido is indeed made with interactive use in mind

  • Oisteink@feddit.nl
    link
    fedilink
    English
    arrow-up
    1
    arrow-down
    1
    ·
    edit-2
    4 days ago

    Been using this for a while - yubico has a nice guide. Dunno why you struggled to find good info as i can just google «fifo2 ssh» and use the top link

    Nevermind - i see OP is trying to reinvent a broken wheel. Ignore my comments on this post