{"record":{"id":"e0b442cd2ecd5aef","repo":"FiloSottile/age","slug":"unknown-ssh-recipient-type-q","errorCode":null,"errorMessage":"unknown SSH recipient type: %q","messagePattern":"unknown SSH recipient type: %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agessh/agessh.go","lineNumber":186,"sourceCode":"\t\tsshKey:         pk,\n\t\ttheirPublicKey: mpk,\n\t}, nil\n}\n\nfunc ParseRecipient(s string) (age.Recipient, error) {\n\tpubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(s))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"malformed SSH recipient: %q: %v\", s, err)\n\t}\n\n\tvar r age.Recipient\n\tswitch t := pubKey.Type(); t {\n\tcase \"ssh-rsa\":\n\t\tr, err = NewRSARecipient(pubKey)\n\tcase \"ssh-ed25519\":\n\t\tr, err = NewEd25519Recipient(pubKey)\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unknown SSH recipient type: %q\", t)\n\t}\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"malformed SSH recipient: %q: %v\", s, err)\n\t}\n\n\treturn r, nil\n}\n\nfunc ed25519PublicKeyToCurve25519(pk ed25519.PublicKey) ([]byte, error) {\n\t// See https://blog.filippo.io/using-ed25519-keys-for-encryption and\n\t// https://pkg.go.dev/filippo.io/edwards25519#Point.BytesMontgomery.\n\tp, err := new(edwards25519.Point).SetBytes(pk)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn p.BytesMontgomery(), nil\n}\n","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/FiloSottile/age/blob/b74dce4cdbe35b5e5f66c06d9612b72f89028758/agessh/agessh.go#L168-L204","documentation":"After successfully parsing the SSH key, ParseRecipient only supports the types ssh-rsa and ssh-ed25519. Any other key type (e.g. ecdsa-sha2-nistp256, sk-ssh-ed25519@openssh.com) hits the default case and is rejected as an unknown SSH recipient type.","triggerScenarios":"Calling agessh.ParseRecipient with a parsed key whose Type() is neither \"ssh-rsa\" nor \"ssh-ed25519\" — e.g. ECDSA, DSA, or security-key (FIDO) variants.","commonSituations":"Users offering ECDSA or hardware security keys (YubiKey sk-* keys) as age recipients; default ssh-keygen output of older distros that generated ecdsa keys; team configs mixing key types.","solutions":["Convert to a supported key type: generate ssh-rsa (>= 3072 bits) or ssh-ed25519 keys for use with age.","Add the supported type to recipients explicitly and regenerate unsupported keys.","Alternatively encrypt to the plugin/native age recipient types that the version supports."],"exampleFix":"// before\nage -r 'ecdsa-sha2-nistp256 AAAA...' // unsupported type\n// after\nssh-keygen -t ed25519 -f id_ed25519\nage -r \"$(cat id_ed25519.pub)\"","handlingStrategy":"type-guard","validationCode":"k, _, _, _, err := ssh.ParseAuthorizedKey([]byte(s))\nif err == nil {\n    switch k.Type() {\n    case \"ssh-rsa\", \"ssh-ed25519\":\n        // supported\n    default:\n        return fmt.Errorf(\"unsupported SSH key type %q; use ssh-rsa or ssh-ed25519\", k.Type())\n    }\n}","typeGuard":"func isSupportedSSHType(s string) bool {\n    k, _, _, _, err := ssh.ParseAuthorizedKey([]byte(s))\n    if err != nil {\n        return false\n    }\n    return k.Type() == \"ssh-rsa\" || k.Type() == \"ssh-ed25519\"\n}","tryCatchPattern":"r, err := agessh.ParseRecipient(s)\nif err != nil {\n    if strings.Contains(err.Error(), \"unknown SSH recipient type\") {\n        return errors.New(\"generate an ssh-rsa or ssh-ed25519 key instead\")\n    }\n    return err\n}","preventionTips":["Standardize team SSH keys on ssh-ed25519 or ssh-rsa (>=3072 bits).","Check `ssh-keygen -lf key.pub` key type before using it with age.","Do not use ECDSA, DSA, or sk-* FIDO keys as age SSH recipients."],"tags":["ssh","recipient","unsupported-key-type"],"backgroundTag":"unknown-ssh-recipient-type","analyzedSha":"b74dce4cdbe35b5e5f66c06d9612b72f89028758","analyzedAt":"2026-08-31T23:59:31.627Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}