Skip to content

Add support for sk- (hardware-backed) ed25519 keys #35

@anoadragon453

Description

@anoadragon453

OpenSSH 8.2 or higher supports hardware-backed variants of ed25519 and ecdsa SSH key types, otherwise known as "secure key" (sk) variants.

I have a Yubikey and use its FIDO2 support to store a sk-ed25519 SSH key on the device. It is not (supposedly) possible to get access to the private keys of this variant, but you can access the public key of course.

I use this key to authenticate to my servers, and I'd like to use it with sops-nix as well. However, it appears that ssh-to-age does not support the -sk variant of ed25519 keys, so I get an error:

$ ssh-to-age -i ~/.ssh/id_ed25519_sk_rk.pub
ssh-to-age: failed to convert '[email protected] AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIGVdcgCRUwCd83w5L+k5yhDHrLDF88GgDWdhvMqYAUiAAAAABHNzaDo= ssh:': failed to parse ssh public key: illegal base64 data at input byte 3

which I believe is due to the check for the "ssh-" prefix here:

ssh-to-age/convert.go

Lines 99 to 103 in 3d775f6

if strings.HasPrefix(string(sshKey), "ssh-") {
pk, _, _, _, err = ssh.ParseAuthorizedKey(sshKey)
} else {
_, _, pk, _, _, err = ssh.ParseKnownHosts(sshKey)
}

If we expand it to:

	if strings.HasPrefix(string(sshKey), "ssh-") || strings.HasPrefix(string(sshKey), "sk-ssh-") {
		pk, _, _, _, err = ssh.ParseAuthorizedKey(sshKey)
	} else {
		_, _, pk, _, _, err = ssh.ParseKnownHosts(sshKey)
	}

then we predictably get:

$ ssh-to-age -i ~/.ssh/id_ed25519_sk_rk.pub  
skipped key: got [email protected] key type, but only ed25519 keys are supported

due to:

ssh-to-age/convert.go

Lines 107 to 110 in 3d775f6

// We only care about ed25519
if pk.Type() != ssh.KeyAlgoED25519 {
return nil, fmt.Errorf("got %s key type, but %w", pk.Type(), UnsupportedKeyType)
}

if we then expand that code to:

	// We only care about ed25519 (and the secure key variant)
	if pk.Type() != ssh.KeyAlgoED25519 && pk.Type() != ssh.KeyAlgoSKED25519 {
		return nil, fmt.Errorf("got %s key type, but %w", pk.Type(), UnsupportedKeyType)
	}

we then get:

$ ssh-to-age -i ~/.ssh/id_ed25519_sk_rk.pub
/nix/store/lngv3dl3yal64xripysv284781qrpxj9-ssh-to-age-1.1.1/bin/ssh-to-age: failed to convert '[email protected] AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIGVdcgCRUwCd83w5L+k5yhDHrLDF88GgDWdhvMqYAUiAAAAABHNzaDo= ssh:': BUG! public key does not implement ssh.CryptoPublicKey

which makes sense. ssh.skEd25519PublicKey does not implement ssh.CryptoPublicKey, while ssh.ed25519PublicKey does.

I'm wondering if it's still possible to get the elliptic curve points out of pk and convert it to an age key regardless? Or am I barking up the wrong tree and should go pester to go devs to implement ssh.CryptoPublicKey on ssh.skEd25519PublicKey? :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions