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? I could not find anything in the spec that would prescribe such double-prefixing, or any description of why of all the strings it is done only for the values of critical options (not the labels etc.) The "Critical Options" section of the PROTOCOL.certkeys (referenced above) says only the following about the format for those options: string name string data so I would expect the "normal" string serialization for both name (label) and the data (actual value). There is also no list or multiple string values involved - both the source-address and force-command are singe "flat" strings (source-address can have multiple IPs but they are comma-separated inside of the same string). Could it be a bug in ssh-keygen? When I generate certificates that include such options - for example, with "ssh-keygen -s ... -O source-address=10.78.72.0/29 -O force-command=/tmp/foobar" and then decode the generated certificate (awk '{print $2}' filename-cert.pub | base64 -D | hexdump -C ) I get the following relevant snippet of the dump: 00000190 00 00 00 27 00 00 00 0e 73 6f 75 72 63 65 2d 61 |...'....source-a| 000001a0 64 64 72 65 73 73 *00 00 00 11 00 00 00 0d *31 30 |ddress........10| 000001b0 2e 37 38 2e 37 32 2e 30 2f 32 39 00 00 00 82 00 |.78.72.0/29.....| highlighted is the double-prefix in question: 00 00 00 11 00 00 00 0d The same happens with the force-command value. 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: 00000180 00 00 00 00 00 00 32 00 00 00 00 00 00 00 64 00 |......2.......d.| 00000190 00 00 43 00 00 00 0d 66 6f 72 63 65 2d 63 6f 6d |..C....force-com| 000001a0 6d 61 6e 64 *00 00 00 0b* 2f 74 6d 70 2f 66 6f 6f |mand..../tmp/foo| 000001b0 62 61 72 00 00 00 0e 73 6f 75 72 63 65 2d 61 64 |bar....source-ad| 000001c0 64 72 65 73 73 00 00 00 0d 31 30 2e 37 38 2e 37 |dress....10.78.7| 000001d0 32 2e 30 2f 32 39 00 00 00 16 00 00 00 0e 70 65 |2.0/29........pe| - so before the value of force-command, there is a single length offset 00 00 00 0b, and before the IP address - a single length offset: 00 00 00 0d ssh-keygen -L on such a Go-generated certificate gives the following error: Critical Options: buffer_get_string_ret: bad string length 796159344 buffer_get_string: buffer error The "bad string length" is easily explained - the decimal 796159344 is 0x2f746d70 which comes from the bytes 2f 74 6d 70 - "*/tmp*" in the "/tmp/foobar" string value of the force-command critical option. If I hack the Go ssh library to add an extra prefix with length+4 value, then ssh-keygen -L is happy again. Let me know if you agree that it is a bug in ssh-keygen, I'll be happy to open a Bugzilla ticket. Thanks, Dmitry _______________________________________________ openssh-unix-dev mailing list openssh-unix-dev@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev