Golang complained today:

RSA modulus is not a positive number

I wondered whether this was a fault with our cert(s) or whether golang was loading it properly. As there was no canonical resource on the net for how to diagnose it, her’s what I did (some anonymity applied to the cert):

First:

openssl asn1parse -i -dump -in /path/to/certificate | egrep -A6 -B1 :rsaEncryption

which gives these lines:

289:d=3 hl=2 l= 11 cons: SEQUENCE
291:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption
302:d=3 hl=4 l= 270 prim: BIT STRING
0000 - 00 30 82 01 09 02 82 01-00 cb 4a 13 93 bf 3e 91 .0........J...>.
0010 - 89 08 4e 85 fb e0 2a b8-9e 1c 7f d3 1a eb 34 77 ..N...*.......4w
0020 - 6d 8a 0c 1d d9 13 70 40-ba be 5f 77 2f a1 88 66 m.....p@.._w/..f
0030 - fd 2e ef 14 3f 1d 36 ff-df 23 1c 6a a5 f1 ae fb ....?.6..#.j....
0040 - e6 9a 0a 8b dc 53 5d f4-7a be 0c 27 38 76 2f 27 .....S].z..'8v/'

That tells me that the rsaEncryption bit string starts at byte offset 302. So now I can look at it like this:

$ openssl asn1parse -i -dump -in /path/to/certificate -strparse 302
0:d=0 hl=4 l= 265 cons: SEQUENCE
4:d=1 hl=4 l= 256 prim: INTEGER :-4189AC6C40C16E76F7B17A041FD54761E3802CE514CB889275F3E226EC8FBF4541A088D05E779902D110EBC0E2C90020DCE3955A0E51041965F57423ACA20B8541F3D8C789D0D812AD2ED8006D99EE533A7000AB4FAFA61F46CE80E0CE46D1B4DB88383511FFCE3727D09EEDBE9D479C5FD9AD858580E44A0C9606483B1C7A248B30A7AE1E8CA7F679949AAAB961611EE677CA7DFF59EA8FAF7A6849FC28695B0CE6547CDB48633BC81EC419BB30DC53928C84946BBE5E8E8506971A184C4956E4FC8B4DCA53936B2F1E19937856673E9FF8D29746F41CA6F3A56E15A34F8C46785A06EC77773CD8A8E43EF5EC9EA6887530E4790DEDBED534033B0D1379E9DA
264:d=1 hl=2 l= 3 prim: INTEGER :010001

The two INTEGER values displayed are the RSA modulus and the exponent (65537 in this case).

But the modulus shown is negative (see initial - sign on the first line representing an INTEGER), which is contrary to RFC3447, which means golang complains, even if openssl s_client does not.

Note that if you attempt to display this with openssl x509 -modulus, it won’t display the fault (i.e. it will display the two’s complement hex value rather than the negative number, so you have no idea of the problem).

Conclusion: the certificate is broken, and golang is (technically) right to complain. Apparently the issue was caused by it being generated by a buggy version of gnutls. Solution: Regenerate the certificate.