Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for ed25519 keys in AWS #13304

Merged
merged 1 commit into from
Mar 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 18 additions & 26 deletions pkg/pki/sshkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,19 @@ func ComputeAWSKeyFingerprint(publicKey string) (string, error) {
return "", err
}

der, err := toDER(sshPublicKey)
if err != nil {
return "", fmt.Errorf("error computing fingerprint for SSH public key: %v", err)
switch fmt.Sprintf("%T", sshPublicKey) {
case "*ssh.rsaPublicKey":
der, err := rsaToDER(sshPublicKey)
if err != nil {
return "", fmt.Errorf("error computing fingerprint for SSH public key: %v", err)
}
h := md5.Sum(der)
return colonSeparatedHex(h[:]), nil
case "ssh.ed25519PublicKey":
return ssh.FingerprintSHA256(sshPublicKey), nil
}
h := md5.Sum(der)

return colonSeparatedHex(h[:]), nil
return "", fmt.Errorf("unexpected type of SSH key (%T); AWS can only import RSA and ed25519 keys", sshPublicKey)
}

// ComputeOpenSSHKeyFingerprint computes the OpenSSH fingerprint of the SSH public key
Expand All @@ -93,30 +99,16 @@ func ComputeOpenSSHKeyFingerprint(publicKey string) (string, error) {
return colonSeparatedHex(h[:]), nil
}

// toDER gets the DER encoding of the SSH public key
// rsaToDER gets the DER encoding of the SSH public key
// Annoyingly, the ssh code wraps the actual crypto keys, so we have to use reflection tricks
func toDER(pubkey ssh.PublicKey) ([]byte, error) {
pubkeyValue := reflect.ValueOf(pubkey)
typeName := fmt.Sprintf("%T", pubkey)

func rsaToDER(pubkey ssh.PublicKey) ([]byte, error) {
var cryptoKey crypto.PublicKey
switch typeName {
case "*ssh.rsaPublicKey":
var rsaPublicKey *rsa.PublicKey
targetType := reflect.ValueOf(rsaPublicKey).Type()
rsaPublicKey = pubkeyValue.Convert(targetType).Interface().(*rsa.PublicKey)
cryptoKey = rsaPublicKey

// case "*dsaPublicKey":
// var dsaPublicKey *dsa.PublicKey
// targetType := reflect.ValueOf(dsaPublicKey).Type()
// dsaPublicKey = pubkeyValue.Convert(targetType).Interface().(*dsa.PublicKey)
// cryptoKey = dsaPublicKey

default:
return nil, fmt.Errorf("unexpected type of SSH key (%q); AWS can only import RSA keys", typeName)
}
var rsaPublicKey *rsa.PublicKey

pubkeyValue := reflect.ValueOf(pubkey)
targetType := reflect.ValueOf(rsaPublicKey).Type()
rsaPublicKey = pubkeyValue.Convert(targetType).Interface().(*rsa.PublicKey)
cryptoKey = rsaPublicKey
der, err := x509.MarshalPKIXPublicKey(cryptoKey)
if err != nil {
return nil, fmt.Errorf("error marshaling SSH public key: %v", err)
Expand Down
12 changes: 6 additions & 6 deletions pkg/pki/sshkey_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ func Test_AWSFingerprint_RsaKeyEncrypted(t *testing.T) {
checkAWSFingerprintEqual(t, key, "c9:c5:05:5e:ea:54:fc:a4:7c:7c:75:5c:d2:71:5e:40")
}

func Test_AWSFingerprint_Ed25519Key(t *testing.T) {
key := "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBoB6Gtu8zPAPO1yF4OwysWUD8ZSEQYzMpOT0YvF9qJV user@example"
checkAWSFingerprintEqual(t, key, "SHA256:HvE7+gmH78VS53+iPuRDh/gKjVo26OzYU/qOnJWAgyk")
}

func Test_AWSFingerprint_TrickyWhitespace(t *testing.T) {
// No name, \r instead of whitespace
key := "ssh-rsa\rAAAAB3NzaC1yc2EAAAADAQABAAABAQCySdqIU+FhCWl3BNrAvPaOe5VfL2aCARUWwy91ZP+T7LBwFa9lhdttfjp/VX1D1/PVwntn2EhN079m8c2kfdmiZ/iCHqrLyIGSd+BOiCz0lT47znvANSfxYjLUuKrWWWeaXqerJkOsAD4PHchRLbZGPdbfoBKwtb/WT4GMRQmb9vmiaZYjsfdPPM9KkWI9ECoWFGjGehA8D+iYIPR711kRacb1xdYmnjHqxAZHFsb5L8wDWIeAyhy49cBD+lbzTiioq2xWLorXuFmXh6Do89PgzvHeyCLY6816f/kCX6wIFts8A2eaEHFL4rAOsuh6qHmSxGCR9peSyuRW8DxV725x\r"
Expand All @@ -62,12 +67,7 @@ func Test_AWSFingerprint_TrickyWhitespace(t *testing.T) {

func Test_AWSFingerprint_DsaKey(t *testing.T) {
key := "ssh-dss AAAAB3NzaC1kc3MAAACBAIcCTu3vi9rNjsnhCrHeII7jSN6/FmnIdy09pQAsMAGGvCS9HBOteCKbIyYQQ0+Gi76Oui7cJ2VQojdxOxeZPoSP+QYnA+CVYhnowVVLeRA9VBQG3ZLInoXaqe3nR4/OXhY75GmYShBBPTQ+/fWGX9ltoXfygSc4KjhBNudvj75VAAAAFQDiw8A4MhY0aHSX/mtpa7XV8+iS6wAAAIAXyQaxM/dk0o1vBV3H0V0lGhog3mF7EJPdw7jagYvXQP1tAhzNofxZVhXHr4wGfiTQv9j5plDqQzCI/15a6DRyo9zI+zdPTR41W3dGrk56O2/Qxsz3/vNip5OwpOJ88yMmBX9m36gg0WrOXcZDgErhvZWRt5cXa9QjVg/KpxYLPAAAAIB8e5M82IiRLi+k1k4LsELKArQGzVkPgynESfnEXX0TKGiR7PJvBNGaKnPJtJ0Rrc38w/hLTeklroJt9Rdey/NI9b6tc+ur2pmJdnYppnNCm03WszU4oFD/7KIqR84Hf0fMbWd1hRvznpZhngZ505KNsL+ck0+Tlq6Hdhe2baXJcA== justin@machine"
checkAWSFingerprintError(t, key, "AWS can only import RSA keys")
}

func Test_AWSFingerprint_Ed25519Key(t *testing.T) {
key := "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFpyraYd4rUFftiEKzUO4wKFAgTkXxuJcRZwVcsuZJ8G justin@machine"
checkAWSFingerprintError(t, key, "AWS can only import RSA keys")
checkAWSFingerprintError(t, key, "AWS can only import RSA and ed25519 keys")
}

func checkOpenSSHFingerprintEqual(t *testing.T, publicKey string, fingerprint string) {
Expand Down