Error during Account Registration - Key too small: 0

I am currently testing the Account Creation phase for a new ACME client i am building.

I am sending request to /acme/new-reg on the staging server and i get a response code of 400 with the following data returned:

{
"type": "urn:acme:error:malformed",
"detail": "Key too small: 0",
"status": 400
}

Naturally, i thought the account key pair that i was using was too small (it was 2048 bit). So i changed the code to create and use a 4096 bit key pair but i am still getting the same error.

I also tried the building the request using the test-ca.key from the boulder/test

Here is the request i built using the test-ca.key:

{
"header": {
	"alg": "RS256",
	"jwk": {
		"kty": "RSA",
		"n": "",
		"e": "AQE"
	}
},
"protected": "eyJhbGciOiJSUzI1NiIsImp3ayI6eyJrdHkiOiJSU0EiLCJuIjoiIiwiZSI6IkFRRSJ9LCJub25jZSI6ImJMTmlZZGYxZzRmMlU2c3pMUEctMEN5UDlOajgtWFhlR00zUEdqVHBsRDAifQ",
"payload": "eyJyZXNvdXJjZSI6Im5ldy1yZWciLCJhZ3JlZW1lbnQiOiJodHRwczovL2xldHNlbmNyeXB0Lm9yZy9kb2N1bWVudHMvTEUtU0EtdjEuMS4xLUF1Z3VzdC0xLTIwMTYucGRmIiwiY29udGFjdCI6WyJtYWlsdG86dHBlbm5lckA0ZC5jb20iLCJ0ZWw6KzE0MDg1NTc0NjAwIl19",
"signature": "rJgaGo5raS5ufvJZ0cT604LI4Sz8L7PtAhRVQOKzznNxW7JEXXm0m3-vUtAj47U7an37JggZVHbEmF0-vFSoisbIK9dY5EifVDRb0lpfCv6tlLIS3BjR2A9zYLrRUnl_iw5SkA76whPS8gMXM-Y8HvyuUQqBrUAZ-WaS_1vxO9koTbNZKBDWNXBxShrU24UDpvxpusXzIixmNDilWdVC3r-Abypqe6bZ5PgvHWgVwGTTgMJ_mb5nbE4OURZRJH4-e0Vm6NjoYkEOkY49MO09-77EebWmcZ49CEFv5nya0PwNz9xZMXdcdyKObNU97AUMk_a5qqY60huu5Zrd5O4WPg"
}

The above request yields the same error:

{
"type": "urn:acme:error:malformed",
"detail": "Key too small: 0",
"status": 400
}

I have been searching online for references to this "Key too small: 0" error but I have been unable to find anything.

Any idea what's going on here?

Is this really blank ? (it shouldn't be) or have you deleted it to post here for some reason.

2 Likes

As pointed out by @serverco the blank “n” in your RSA JWK is at fault here. I suspect whatever code you are using to generate the JWK has a bug. Take a look at the “n” value in this example key from RFC7517:

    {
          "kty":"RSA",
          "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx
     4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs
     tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2
     QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI
     SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb
     w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
          "e":"AQAB",
          "alg":"RS256",
          "kid":"2011-04-29"
    }

I would expect a well formed RSA JWK to have an encoded “n” value like the above.

2 Likes

Thank you both very much for this clue - indeed my code is returning a null value for n when i get the details of the private key…

I am feeding the test-ca.key into a simple php script that my code is calling:

function getKeyDetails($pem) {
  $res = openssl_pkey_get_private($pem);
  $va = openssl_pkey_get_details($res);
  return json_encode($va);
}

My code is then getting the following JSON returned for the test-ca.key which i use for constructing the JWK:

{
"bits": 2048,
"key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwgpHeZoFxRKydxdjNBPX\ncPk2v5neYvEwyHdNR23qwAKapsnRu1GWBd8y00szY5TUjprcm760hlJ2fa/bUkHC\n/FTOllDjPLZyKYiIxANkJAcnDML0ZmfwdpbT3WLP0fQajcDtYNfBg2ax0s1GLTSj\nXhSOhpWpo+xitla9EpohGppTSEeZLQBbBBK83/3eIwhe7KLDLCaTAptaefEJD+Cx\ny0oVS1w2vATH1aCPoqWHANPIjVBZIFvFVg3JSA8XMrGtKbAw7TI19/uGj5BP3Hn5\nj/tcTn1LgxzhlfFxcp7D+BKU31Tma9P4PYGEO2QK6l1+xk0JBanbsD5v8OasUj02\nqwIDAQAB\n-----END PUBLIC KEY-----\n",
"rsa": {
	"n": null,
	"e": "\u0001\u0001",
	"d": null,
	"p": null,
	"q": null,
	"dmp1": null,
	"dmq1": null,
	"iqmp": null
},
"type": 0
}

I will investigate this aspect of the code, and probably look for an alternative way to get the modulus (n) of a key.

Do you have a suggested way to get this information from a private key, perhaps with a call to the openssl binary (i am researching this now)?

Thank you again for your time!

I am now using openssl command line tools to get the modulus;

openssl rsa -noout -modulus -in key.pem

continuing to test with the test-ca.key file i get the following modulus:

C20A47799A05C512B27717633413D770F936BF99DE62F130C8774D476DEAC0029AA6C9D1BB519605DF32D34B336394D48E9ADC9BBEB48652767DAFDB5241C2FC54CE9650E33CB672298888C403642407270CC2F46667F07696D3DD62CFD1F41A8DC0ED60D7C18366B1D2CD462D34A35E148E8695A9A3EC62B656BD129A211A9A534847992D005B0412BCDFFDDE23085EECA2C32C2693029B5A79F1090FE0B1CB4A154B5C36BC04C7D5A08FA2A58700D3C88D5059205BC5560DC9480F1732B1AD29B030ED3235F7FB868F904FDC79F98FFB5C4E7D4B831CE195F171729EC3F81294DF54E66BD3F83D81843B640AEA5D7EC64D0905A9DBB03E6FF0E6AC523D36AB

And using this i build the following JWK:

{
"header": {
	"alg": "RS256",
	"jwk": {
		"kty": "RSA",
		"n": "QzIwQTQ3Nzk5QTA1QzUxMkIyNzcxNzYzMzQxM0Q3NzBGOTM2QkY5OURFNjJGMTMwQzg3NzRENDc2REVBQzAwMjlBQTZDOUQxQkI1MTk2MDVERjMyRDM0QjMzNjM5NEQ0OEU5QURDOUJCRUI0ODY1Mjc2N0RBRkRCNTI0MUMyRkM1NENFOTY1MEUzM0NCNjcyMjk4ODg4QzQwMzY0MjQwNzI3MENDMkY0NjY2N0YwNzY5NkQzREQ2MkNGRDFGNDFBOERDMEVENjBEN0MxODM2NkIxRDJDRDQ2MkQzNEEzNUUxNDhFODY5NUE5QTNFQzYyQjY1NkJEMTI5QTIxMUE5QTUzNDg0Nzk5MkQwMDVCMDQxMkJDREZGRERFMjMwODVFRUNBMkMzMkMyNjkzMDI5QjVBNzlGMTA5MEZFMEIxQ0I0QTE1NEI1QzM2QkMwNEM3RDVBMDhGQTJBNTg3MDBEM0M4OEQ1MDU5MjA1QkM1NTYwREM5NDgwRjE3MzJCMUFEMjlCMDMwRUQzMjM1RjdGQjg2OEY5MDRGREM3OUY5OEZGQjVDNEU3RDRCODMxQ0UxOTVGMTcxNzI5RUMzRjgxMjk0REY1NEU2NkJEM0Y4M0Q4MTg0M0I2NDBBRUE1RDdFQzY0RDA5MDVBOURCQjAzRTZGRjBFNkFDNTIzRDM2QUI",
		"e": "AQE"
	}
},
"protected": "eyJhbGciOiJSUzI1NiIsImp3ayI6eyJrdHkiOiJSU0EiLCJuIjoiUXpJd1FUUTNOems1UVRBMVF6VXhNa0l5TnpjeE56WXpNelF4TTBRM056QkdPVE0yUWtZNU9VUkZOakpHTVRNd1F6ZzNOelJFTkRjMlJFVkJRekF3TWpsQlFUWkRPVVF4UWtJMU1UazJNRFZFUmpNeVJETTBRak16TmpNNU5FUTBPRVU1UVVSRE9VSkNSVUkwT0RZMU1qYzJOMFJCUmtSQ05USTBNVU15UmtNMU5FTkZPVFkxTUVVek0wTkNOamN5TWprNE9EZzRRelF3TXpZME1qUXdOekkzTUVORE1rWTBOalkyTjBZd056WTVOa1F6UkVRMk1rTkdSREZHTkRGQk9FUkRNRVZFTmpCRU4wTXhPRE0yTmtJeFJESkRSRFEyTWtRek5FRXpOVVV4TkRoRk9EWTVOVUU1UVRORlF6WXlRalkxTmtKRU1USTVRVEl4TVVFNVFUVXpORGcwTnprNU1rUXdNRFZDTURReE1rSkRSRVpHUkVSRk1qTXdPRFZGUlVOQk1rTXpNa015Tmprek1ESTVRalZCTnpsR01UQTVNRVpGTUVJeFEwSTBRVEUxTkVJMVF6TTJRa013TkVNM1JEVkJNRGhHUVRKQk5UZzNNREJFTTBNNE9FUTFNRFU1TWpBMVFrTTFOVFl3UkVNNU5EZ3dSakUzTXpKQ01VRkVNamxDTURNd1JVUXpNak0xUmpkR1FqZzJPRVk1TURSR1JFTTNPVVk1T0VaR1FqVkRORVUzUkRSQ09ETXhRMFV4T1RWR01UY3hOekk1UlVNelJqZ3hNamswUkVZMU5FVTJOa0pFTTBZNE0wUTRNVGcwTTBJMk5EQkJSVUUxUkRkRlF6WTBSREE1TURWQk9VUkNRakF6UlRaR1JqQkZOa0ZETlRJelJETTJRVUkiLCJlIjoiQVFFIn0sIm5vbmNlIjoiVmFoVUlsaDVlZjFPeUY5bWgwWTZEcFFNYWxfN0Vad09UdkRZcS10RWtlbyJ9",
"payload": "eyJyZXNvdXJjZSI6Im5ldy1yZWciLCJhZ3JlZW1lbnQiOiJodHRwczovL2xldHNlbmNyeXB0Lm9yZy9kb2N1bWVudHMvTEUtU0EtdjEuMS4xLUF1Z3VzdC0xLTIwMTYucGRmIiwiY29udGFjdCI6WyJtYWlsdG86dHBlbm5lckA0ZC5jb20iLCJ0ZWw6KzE0MDg1NTc0NjAwIl19",
"signature": "v151HMiAOx5KkOR4ySiZ7yTBstpnZ0Sa-6TA41i-NY6hoWHogXBObVMQ_LhuD2lvlmMWBFwfuFZw0m13SyDDpzir9HL089ol26NzLRn3uuMH2--33kBiJoHYfVriOOkYBTUhaSS1yapFcrQumQv9VbE3Rtz4jVF5coTjycbxxGO0_6S0NLtsagYHub0uhd7FqJjkORtiYZujsIm52BRW8936ch505iiLq1kNx1idoSoiu4Uyd-eNL71WCxT4BK07wBiaexSnV83XhnmWummIJ4rOZDYvZkMTWYiCqkUv-tufB3uw_GRN5hNYo7RMgjH3sp-HzyrHjT-U-eOr0c_2KA"
}

However now i get the following error:

{
   "type": "urn:acme:error:malformed",
   "detail": "Key length wasn't a multiple of 8: 4095",
   "status": 400
}

So i am making progress, but still struggling with key lengths...

It needs to be base64 url encoded. ( from draft-ietf-acme-acme-03 )

Binary fields in the JSON objects used by ACME are encoded using
base64url encoding described in [RFC4648] Section 5, according to the
profile specified in JSON Web Signature [RFC7515] Section 2. This
encoding uses a URL safe character set. Trailing '=' characters MUST
be stripped.

I find it very suspicious that your e value is “AQE” instead of “AQAB”. Almost all RSA implementations now use the public exponent 65537 (0x10001), which is represented as “AQAB” in base64. Could there be a problem with your base64 encoding? JWK uses a specific kind of base64 encoding; are you sure that you’re using the base64 flavor that it expects?

2 Likes

I think the details i am getting back from openssl_pkey_get_details are inaccurate... for e i am getting "e": "\u0001\u0001" which is being Base64URLEncoded to AQE - so it seems that not only is the modulus (n) wrong, but so is the public exponent (e); probably the entire result.

I just tested the test-ca.key with the OpenSSL command line tools and the public exponent (e) is listed as publicExponent: 65537 (0x10001) so i incorporated the AQAB value into my routine and i still get the same error about Key length wasn't a multiple of 8: 4095.

Here is the data i am sending to /acme/new-reg via POST:

{
"header": {
	"alg": "RS256",
	"jwk": {
		"kty": "RSA",
		"n": "QzIwQTQ3Nzk5QTA1QzUxMkIyNzcxNzYzMzQxM0Q3NzBGOTM2QkY5OURFNjJGMTMwQzg3NzRENDc2REVBQzAwMjlBQTZDOUQxQkI1MTk2MDVERjMyRDM0QjMzNjM5NEQ0OEU5QURDOUJCRUI0ODY1Mjc2N0RBRkRCNTI0MUMyRkM1NENFOTY1MEUzM0NCNjcyMjk4ODg4QzQwMzY0MjQwNzI3MENDMkY0NjY2N0YwNzY5NkQzREQ2MkNGRDFGNDFBOERDMEVENjBEN0MxODM2NkIxRDJDRDQ2MkQzNEEzNUUxNDhFODY5NUE5QTNFQzYyQjY1NkJEMTI5QTIxMUE5QTUzNDg0Nzk5MkQwMDVCMDQxMkJDREZGRERFMjMwODVFRUNBMkMzMkMyNjkzMDI5QjVBNzlGMTA5MEZFMEIxQ0I0QTE1NEI1QzM2QkMwNEM3RDVBMDhGQTJBNTg3MDBEM0M4OEQ1MDU5MjA1QkM1NTYwREM5NDgwRjE3MzJCMUFEMjlCMDMwRUQzMjM1RjdGQjg2OEY5MDRGREM3OUY5OEZGQjVDNEU3RDRCODMxQ0UxOTVGMTcxNzI5RUMzRjgxMjk0REY1NEU2NkJEM0Y4M0Q4MTg0M0I2NDBBRUE1RDdFQzY0RDA5MDVBOURCQjAzRTZGRjBFNkFDNTIzRDM2QUI",
		"e": "AQAB"
	}
},
"protected": "eyJhbGciOiJSUzI1NiIsImp3ayI6eyJrdHkiOiJSU0EiLCJuIjoiUXpJd1FUUTNOems1UVRBMVF6VXhNa0l5TnpjeE56WXpNelF4TTBRM056QkdPVE0yUWtZNU9VUkZOakpHTVRNd1F6ZzNOelJFTkRjMlJFVkJRekF3TWpsQlFUWkRPVVF4UWtJMU1UazJNRFZFUmpNeVJETTBRak16TmpNNU5FUTBPRVU1UVVSRE9VSkNSVUkwT0RZMU1qYzJOMFJCUmtSQ05USTBNVU15UmtNMU5FTkZPVFkxTUVVek0wTkNOamN5TWprNE9EZzRRelF3TXpZME1qUXdOekkzTUVORE1rWTBOalkyTjBZd056WTVOa1F6UkVRMk1rTkdSREZHTkRGQk9FUkRNRVZFTmpCRU4wTXhPRE0yTmtJeFJESkRSRFEyTWtRek5FRXpOVVV4TkRoRk9EWTVOVUU1UVRORlF6WXlRalkxTmtKRU1USTVRVEl4TVVFNVFUVXpORGcwTnprNU1rUXdNRFZDTURReE1rSkRSRVpHUkVSRk1qTXdPRFZGUlVOQk1rTXpNa015Tmprek1ESTVRalZCTnpsR01UQTVNRVpGTUVJeFEwSTBRVEUxTkVJMVF6TTJRa013TkVNM1JEVkJNRGhHUVRKQk5UZzNNREJFTTBNNE9FUTFNRFU1TWpBMVFrTTFOVFl3UkVNNU5EZ3dSakUzTXpKQ01VRkVNamxDTURNd1JVUXpNak0xUmpkR1FqZzJPRVk1TURSR1JFTTNPVVk1T0VaR1FqVkRORVUzUkRSQ09ETXhRMFV4T1RWR01UY3hOekk1UlVNelJqZ3hNamswUkVZMU5FVTJOa0pFTTBZNE0wUTRNVGcwTTBJMk5EQkJSVUUxUkRkRlF6WTBSREE1TURWQk9VUkNRakF6UlRaR1JqQkZOa0ZETlRJelJETTJRVUkiLCJlIjoiQVFBQiJ9LCJub25jZSI6ImtiTEpDZ0M2OFpQOWFGcWlMd2FHbWJQMXFRSnAtUmF2a1EtTjF4XzFzd1EifQ",
"payload": "eyJyZXNvdXJjZSI6Im5ldy1yZWciLCJhZ3JlZW1lbnQiOiJodHRwczovL2xldHNlbmNyeXB0Lm9yZy9kb2N1bWVudHMvTEUtU0EtdjEuMS4xLUF1Z3VzdC0xLTIwMTYucGRmIiwiY29udGFjdCI6WyJtYWlsdG86dHBlbm5lckA0ZC5jb20iLCJ0ZWw6KzE0MDg1NTc0NjAwIl19",
"signature": "QhCxpEtw8nTN6bBwVvolsNZig9kMSQAz0BuGuCDjgTqPdOGpEBNtuHN7mBVXuLU_BzWgg0k2_MGYcId2w-qCSKiQMoDuQcDFVigGoYGSFzFi7nwO0MI2UVBEvog1Czxhv0qYUSiVKF0msW84kzaLPpi9iESh73MPLRhEMRYtP8QTz2EYPRo-3_VPt10Nyz5UMzd-hklMLMMnWIcuL6sXZxuj6nU-gOYQC_N5AQvygKdauccdZSziagSLhI5r7PT0l5cQjk_WTqmRExtc95evdiMAvFpPyzIzFRHVdm6_wk5bUZEb55gnX1a80T1e2aNdjiJmrFBHADXcnR_QRx5C_Q"
}

The strange part is that the error lists 4095:

Key length wasn't a multiple of 8: 4095

Although the test-ca.key i am using is a 2048 bit key; if I was using a 4096 bit key i would think maybe i was somehow munging one of the bits... but that isn't the case here as it is a 2048 bit key.

Any idea which key this error refers to and why it references 4095 at the end of the error?

I just realized the modulus returned by OpenSSL is sometimes prepended with 00 depending on how it is called:

Example 1 - includes 00:

openssl.exe rsa -noout -inform pem -text -in key.pem

Returns:

modulus:
00:c2:0a:47:79:9a:05:c5:12:b2:77:17:63:34:13:
d7:70:f9:36:bf:99:de:62:f1:30:c8:77:4d:47:6d:
ea:c0:02:9a:a6:c9:d1:bb:51:96:05:df:32:d3:4b:
33:63:94:d4:8e:9a:dc:9b:be:b4:86:52:76:7d:af:
db:52:41:c2:fc:54:ce:96:50:e3:3c:b6:72:29:88:
88:c4:03:64:24:07:27:0c:c2:f4:66:67:f0:76:96:
d3:dd:62:cf:d1:f4:1a:8d:c0:ed:60:d7:c1:83:66:
b1:d2:cd:46:2d:34:a3:5e:14:8e:86:95:a9:a3:ec:
62:b6:56:bd:12:9a:21:1a:9a:53:48:47:99:2d:00:
5b:04:12:bc:df:fd:de:23:08:5e:ec:a2:c3:2c:26:
93:02:9b:5a:79:f1:09:0f:e0:b1:cb:4a:15:4b:5c:
36:bc:04:c7:d5:a0:8f:a2:a5:87:00:d3:c8:8d:50:
59:20:5b:c5:56:0d:c9:48:0f:17:32:b1:ad:29:b0:
30:ed:32:35:f7:fb:86:8f:90:4f:dc:79:f9:8f:fb:
5c:4e:7d:4b:83:1c:e1:95:f1:71:72:9e:c3:f8:12:
94:df:54:e6:6b:d3:f8:3d:81:84:3b:64:0a:ea:5d:
7e:c6:4d:09:05:a9:db:b0:3e:6f:f0:e6:ac:52:3d:
36:ab

Example 2 - does not include 00:

openssl.exe rsa -noout -modulus -in key.pem

Returns:

Modulus=C20A47799A05C512B27717633413D770F936BF99DE62F130C8774D476DEAC0029AA6C9D1BB519605DF32D34B336394D48E9ADC9BBEB48652767DAFDB5241C2FC54CE9650E33CB672298888C403642407270CC2F46667F07696D3DD62CFD1F41A8DC0ED60D7C18366B1D2CD462D34A35E148E8695A9A3EC62B656BD129A211A9A534847992D005B0412BCDFFDDE23085EECA2C32C2693029B5A79F1090FE0B1CB4A154B5C36BC04C7D5A08FA2A58700D3C88D5059205BC5560DC9480F1732B1AD29B030ED3235F7FB868F904FDC79F98FFB5C4E7D4B831CE195F171729EC3F81294DF54E66BD3F83D81843B640AEA5D7EC64D0905A9DBB03E6FF0E6AC523D36AB

My code is using the output from the second example and Base64URLencoding the value above (as a string), which I am starting to think is the wrong approach.

I should probably build a blob using the hex/character codes and then Base64URLencode that blob - but should i include the 00 as the first byte of the blob?

@tpenner, the problem appears to be that you are base64-encoding hexadecimal-encoded strings rather than raw bytes. The base64 data that you sent decoded to the hexadecimal-encoded modulus (starting with “C20A47”) rather than a byte representation of the modulus. That could also explain why your data is almost exactly twice as large as expected.

2 Likes

Also, just to be clear: The test-ca.key from the Boulder repository is not intended for use outside of Boulder’s test environment. I would very strongly recommend generating your own key, even if it’s just for testing. If you were to accidentally use test-ca.key as the private key to generate a certificate, that certificate would be compromised because the private key is made public. Here’s how you would generate your own key:

openssl.exe genrsa

1 Like

Thank you @schoen and @jsha

I only used the Boulder test key because of the “key too small” error i was initially getting.

I thought the test key was used for unit testing your product and would therefore be of the expected key size; i hoped it would get me passed the “key too small” error. Plus since the boulder test key was already public i wouldn’t mind posting the key details in this help request.

In the end, the “key too small” error was regarding my Modulus (n) being an empty string ("").

I planned to use my own key generated from openssl genrsa for this once i get it working; but i will switch back to using my own key right now to avoid forgetting to switch later.

I think once i rewrite the code to use the binary data instead of the string data it will resolve this “Key length wasn’t a multiple of 8: 4095” error.

Thanks for all the pointers!

2 Likes

Thanks to everyone who responded; i ended up having three issues resolved with this thread.

  1. error “Key too small: 0”

This was due to the modulus (n) being empty.

Solving the first revealed the next error:

  1. error “Key length wasn’t a multiple of 8: 4095”

This was because i was Base64URLencoding the String Value of the modulus.
I needed to Base64URLencode the Binary representation of the modulus.
Once i changed the code to use the Binary representation of the modulus it worked!

  1. The public exponent (e) did not match the certificate.

I didn’t get any error specifically for this; but it was pointed out in this thread that (e) was wrong, and indeed (e) was wrong.

This is now solved; my registration routine appears to be working now.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.