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.
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:
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?
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:
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?
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.
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:
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 to everyone who responded; i ended up having three issues resolved with this thread.
error “Key too small: 0”
This was due to the modulus (n) being empty.
Solving the first revealed the next error:
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!
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.