Thanks Damien for your response and explanations - I opened https://bugzilla.mindrot.org/show_bug.cgi?id=2389 to improve the wording the PROTOCOL.certkeys spec. Currently reading that the format the critical options field is a sequence of tuples: > > string name > string data I would expect both fields to have the same encoding since they have the same type "string" (and also by analogy with multiple other string fields in the specification). Do you think it would be worth to give the second field of the tuple some other type like "object" or "composite" or string[] - especially since you say the intent is to support "data types other than string, e.g. integers or arrays of string"? http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL?rev=HEAD&content-type=text/x-cvsweb-markup uses the type string[] for the list of strings (as in: " string[] hostkeys") which makes it clear that the field has different semantics and encoding than a "plain" string one. I opened an issue for Go's crypto/ssh library: https://github.com/golang/go/issues/10569 Thanks, Dmitry On Fri, Apr 24, 2015 at 8:11 AM, Damien Miller <djm@xxxxxxxxxxx> wrote: > On Thu, 23 Apr 2015, Dmitry Savintsev wrote: > > > Hi, > > > > I have a question regarding the binary format of the certificates > generated > > with ssh-keygen, in particular when the critical options of > source-address > > or force-command are present and the correspondence to the certificate > > format specifications such as > > > http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD > > . > > > > It appears that the string values of the source-address and force-command > > are prepended with *two* length offsets - 4-byte offset with the integer > > value of len(string)+4 followed by the 4-byte offset with the proper > > length, and then the string. Is it a correct behavior? > > Yes, as per PROTOCOL.certkeys: > > > The critical options section of the certificate specifies zero or more > > options on the certificates validity. The format of this field > > is a sequence of zero or more tuples: > > > > string name > > string data > > So that's the first header for the data. You then have to look at the > table to determine the format of data's contents. E.g. > > > force-command string Specifies a command that is > executed > ... > > So, for name=force-command, the contents of the data buffer are a string. > That's the second header. > > The intent is to support options/extensions with data types other > than string, e.g. integers or arrays of string. > > > This apparent deviation (unless I misread the spec, of course!) creates > > problems in terms of interoperability with other tools. Go ssh library ( > > https://godoc.org/golang.org/x/crypto/ssh), for example, does not do the > > "double-wrapping", and as a result, you cannot read the certificates > > generated with Go using ssh-keygen -L -f <filename>. ssh-keygen tries to > > read the first 4 bytes of the string value as the second length offset > and > > of course things quickly go south. Here's a hexdump of the certificate > > generated with Go around the critical options section. > > Go's implementation is incorrect here. > > Maybe the wording of PROTOCOL.certkeys could be improved to avoid > the confusion, but I'm surprised the Go SSH developers didn't check > against what OpenSSH actually generates (or ask if in doubt). > > -d > _______________________________________________ openssh-unix-dev mailing list openssh-unix-dev@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev