Summary
hiba-ca.sh generates user certificates with extensions that are not in lexical order, violating the OpenSSH PROTOCOL.certkeys specification. This causes Go's x/crypto/ssh library to reject the certificate during parsing.
OpenSSH Spec Requirement
The OpenSSH PROTOCOL.certkeys spec mandates that certificate extensions must be lexically ordered:
Critical options section:
Options must be lexically ordered by "name" if they appear in the sequence. Each named option may only appear once in a certificate.
Extensions section:
The encoding and ordering of extensions in this field is identical to that of the critical options, as is the requirement that each name appear only once.
Problem
When hiba-ca.sh signs a user certificate, ssh-keygen embeds the following default extensions:
permit-agent-forwarding
permit-port-forwarding
permit-pty
permit-user-rc
permit-X11-forwarding
The HIBA extension (extension:grant@hibassh.dev=...) is then appended via the -O flag. The resulting certificate contains extensions in this order:
permit-agent-forwarding <-- default
permit-port-forwarding <-- default
permit-pty <-- default
permit-user-rc <-- default
permit-X11-forwarding <-- default
grant@hibassh.dev[...] <-- added by hiba-ca.sh
While extension:grant@hibassh.dev lexically precedes all permit-* extensions, ssh-keygen does not guarantee the final ordering when mixing built-in defaults with custom extensions added via -O. The resulting certificate may have extensions out of lexical order.
Impact
Go's x/crypto/ssh library (v0.50.0, used in featureprofiles go.mod) strictly enforces the lexical ordering in parseTuples():
// according to [PROTOCOL.certkeys], the names must be in
// lexical order.
if haveLastKey && keyStr <= lastKey {
return nil, fmt.Errorf("ssh: certificate options are not in lexical order")
}
When parsing the certificate, the Go SSH client fails with:
ssh: certificate options are not in lexical order
This error propagates up through ssh.ParseAuthorizedKey() as:
illegal base64 data at input byte 8
Note: OpenSSH's own ssh client is more lenient and does not enforce lexical ordering during parsing, so the same certificate works fine with the ssh CLI but fails with Go-based SSH clients.
Summary
hiba-ca.shgenerates user certificates with extensions that are not in lexical order, violating the OpenSSHPROTOCOL.certkeysspecification. This causes Go'sx/crypto/sshlibrary to reject the certificate during parsing.OpenSSH Spec Requirement
The OpenSSH PROTOCOL.certkeys spec mandates that certificate extensions must be lexically ordered:
Problem
When
hiba-ca.shsigns a user certificate,ssh-keygenembeds the following default extensions:permit-agent-forwardingpermit-port-forwardingpermit-ptypermit-user-rcpermit-X11-forwardingThe HIBA extension (
extension:grant@hibassh.dev=...) is then appended via the-Oflag. The resulting certificate contains extensions in this order:permit-agent-forwarding <-- default
permit-port-forwarding <-- default
permit-pty <-- default
permit-user-rc <-- default
permit-X11-forwarding <-- default
grant@hibassh.dev[...] <-- added by hiba-ca.sh
While
extension:grant@hibassh.devlexically precedes allpermit-*extensions,ssh-keygendoes not guarantee the final ordering when mixing built-in defaults with custom extensions added via-O. The resulting certificate may have extensions out of lexical order.Impact
Go's
x/crypto/sshlibrary (v0.50.0, used in featureprofiles go.mod) strictly enforces the lexical ordering inparseTuples():When parsing the certificate, the Go SSH client fails with:
This error propagates up through ssh.ParseAuthorizedKey() as:
Note: OpenSSH's own ssh client is more lenient and does not enforce lexical ordering during parsing, so the same certificate works fine with the ssh CLI but fails with Go-based SSH clients.