Issue with ssl.com's ACME implementation

I recently started testing Posh-ACME against ssl.com's new ACME endpoints. The object URIs make it seem like they're running some version of EJBCA under the hood. So this may not be something they can directly fix if it is indeed a bug.

In any case, the problem I'm currently running into is that their ACME server is throwing an error when I do a standard POST-as-GET request to my account's URL (to verify it's still valid among other things). Here's an example of the debug output showing the request and response details. I should mention that this code works just fine against LE, BuyPass, and ZeroSSL.

DEBUG: Refreshing account a1
DEBUG: ACME Header:
{
  "alg": "ES256",
  "kid": "https://acme.ssl.com/ejbca/acme/sslcom-dv-ecc/acct/EIjIP6HFmmByGJRwtHYKog",
  "url": "https://acme.ssl.com/ejbca/acme/sslcom-dv-ecc/acct/EIjIP6HFmmByGJRwtHYKog",
  "nonce": "AAABe2BWZ8MAAAAAAAGId9C2Iygyaf43suVZZr-pT7ld2NKyGv6JGoumWiwZa0UiPjBz6RP2fZ5Zg4ikuKeamA"
}
DEBUG: ACME Payload: (empty)
DEBUG: Signing message using EC with SHA256
DEBUG: POST https://acme.ssl.com/ejbca/acme/sslcom-dv-ecc/acct/EIjIP6HFmmByGJRwtHYKog
{"payload":"","protected":"eyJhbGciOiJFUzI1NiIsImtpZCI6Imh0dHBzOi8vYWNtZS5zc2wuY29tL2VqYmNhL2FjbWUvc3NsY29tLWR2LWVjYy9hY2N0L0VJaklQNkhGbW1CeUdKUnd0SFlLb2ciLCJ1cmwiOiJodHRwczovL2FjbWUuc3NsLmNvbS9lamJjYS9hY21lL3NzbGNvbS1kdi1lY2MvYWNjdC9FSWpJUDZIRm1tQnlHSlJ3dEhZS29nIiwibm9uY2UiOiJBQUFCZTJCV1o4TUFBQUFBQUFHSWQ5QzJJeWd5YWY0M3N1Vlpaci1wVDdsZDJOS3lHdjZKR291bVdpd1phMFVpUGpCejZSUDJmWjVaZzRpa3VLZWFtQSJ9","signature":"KBXitpY7SdfCX856lFq5y20wJ4Fe8IiodI9kcBdGVLnzO6tVdYPUQsruYI0CkmGV_BC6ck6HeCVS0xPfHVOPGg"}
DEBUG: Response Code 403, Body:
{"message":"Missing Authentication Token"}

Can anyone else confirm the problem with another client? You'll need to register a website account first in order to get the required EAB credentials. It happens with both their RSA and ECC directory endpoints:
https://acme.ssl.com/sslcom-dv-rsa
https://acme.ssl.com/sslcom-dv-ecc

Does their version of EJBCA just not support POST-as-GET requests? You get the same error if you try an unauthenticated GET against the account URI.

It also bugs me that the error body JSON doesn't have any of the RFC 7807 "Problem Details" members (like type in particular).

More testing results. I get the same error even with a valid non-empty payload trying to update the contact field on my account:

DEBUG: ACME Header:
{
  "alg": "ES256",
  "kid": "https://acme.ssl.com/ejbca/acme/sslcom-dv-rsa/acct/jTFCxbACQgGTN_H8icjJ0Q",
  "url": "https://acme.ssl.com/ejbca/acme/sslcom-dv-rsa/acct/jTFCxbACQgGTN_H8icjJ0Q",
  "nonce": "AAABe2DuJFAAAAAAAAGKz9C2Iygyaf43suVZZr-pT7n2WDOp5SBEmP9rj2I05oUqblZPgA9xVIYGoD_CfelGVA"
}
DEBUG: ACME Payload:
{"contact":["mailto:me@example.com"]}
DEBUG: Signing message using EC with SHA256
DEBUG: POST https://acme.ssl.com/ejbca/acme/sslcom-dv-rsa/acct/jTFCxbACQgGTN_H8icjJ0Q
{"payload":"eyJjb250YWN0IjpbIm1haWx0bzptZUBleGFtcGxlLmNvbSJdfQ","protected":"eyJhbGciOiJFUzI1NiIsImtpZCI6Imh0dHBzOi8vYWNtZS5zc2wuY29tL2VqYmNhL2FjbWUvc3NsY29tLWR2LXJzYS9hY2N0L2pURkN4YkFDUWdHVE5fSDhpY2pKMFEiLCJ1cmwiOiJodHRwczovL2FjbWUuc3NsLmNvbS9lamJjYS9hY21lL3NzbGNvbS1kdi1yc2EvYWNjdC9qVEZDeGJBQ1FnR1ROX0g4aWNqSjBRIiwibm9uY2UiOiJBQUFCZTJEdUpGQUFBQUFBQUFHS3o5QzJJeWd5YWY0M3N1Vlpaci1wVDduMldET3A1U0JFbVA5cmoySTA1b1VxYmxaUGdBOXhWSVlHb0RfQ2ZlbEdWQSJ9","signature":"4Rmxhfwum54jKCFzarK1ntzmU31R0jPlrbxB6jGpiqr8-PWH_JA3w-ksh_f_3568PsxxvnWy2FQCFIIFxU4RNw"}
DEBUG: Response Code 403, Body:
{"message":"Missing Authentication Token"}
3 Likes

I'd have to look at it again but I could only get their RSA workflow to work, so that's the only one I included in Certify The Web.

It's possible there is a backend issue bubbling up, as 'Missing Authentication Token' is also something AWS API Gateway would say.

2 Likes

I can confirm from the headers implementation is running on AWS, hosted on WildFly (JBoss) and that the RSA account path seems to be working (https://acme.ssl.com/ejbca/acme/sslcom-dv-rsa/acct/<acc id>)

Another thing I noticed is that they let your re-use EAB credentials, whereas some others don't.

2 Likes

Here's the source code for EJBCA: GitHub - primekeydevs/ejbca-ce: EJBCA Community - Open Source Enterprise PKI impressively one of the files is 15 years old, so this has been around a while :slight_smile:

2 Likes

The AWS link is a great find and the response headers do make it seem like it's CloudFront throwing the error before the request even makes it to EJBCA.

HTTP/1.1 403 Forbidden
Content-Type: application/json
Content-Length: 42
Connection: keep-alive
Date: Fri, 20 Aug 2021 03:54:03 GMT
x-amzn-RequestId: f8a408e0-ae22-4b9b-959e-a2b708d561ca
x-amzn-ErrorType: MissingAuthenticationTokenException
x-amz-apigw-id: EWMWWHluoAMFjqg=
X-Cache: Error from cloudfront
Via: 1.1 a3bb8de6e66bc0b405844dff5a066f37.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: LAX3-C2
X-Amz-Cf-Id: UJm1TAdtTgvIrk3V40tFoJgsa8diiwzfhsiw2ZS6G5yneofE96kpSw==

The brief searching I've done on the error in relation to AWS makes it sound like it's a common mistake when you're either using the wrong HTTP verb or the wrong endpoint. But neither should be the case here because POST is definitely the right verb and the endpoint was provided by the server.

If I ignore the errors doing account related stuff, I can actually move forward and create a new order using the account and even successfully authorize the DNS challenges. But when I try to finalize the order, they throw an error because apparently they're expecting an email address to be included in the CSR. :man_facepalming:

{
  "detail": "Email address cannot be empty or null.. If you need assistance, please contact support@ssl.com",
  "type": "urn:ietf:params:acme:error:badCSR"
}

What sort of crazy pants requirement is that on a DV cert?

3 Likes

Interesting, again maybe you are still using an EC key and that forces it down a non-working path. Certify doesn't put an email address in the CSR either, but the RSA path passes.

2 Likes

Apparently this is just a bad error message. The ACME account I was using was created with an empty contact field. I created a new one (since I still can't update an existing one) with an email address and now the finalization works.

Seems like if they want to enforce an email address on the ACME account, they should do that at creation time! Especially since their account endpoints are so broken they can't be updated.

4 Likes

Hey @webprofusion, do you recall the error message you got when attempting to get a cert from the EC path? I can get as far as the finalization step where I'm sending the CSR (with a P-256 key) and I get the following error:

{
    "type":  "urn:ietf:params:acme:error:badCSR"
    "detail":  "Requested key usage will not be granted.. If you need assistance, please contact\r\nsupport@ssl.com",
}

Curious if it's the same error you got. Also wondering if there's actually something they don't like about the CSR or if this is another "bad" error message and it's the server's way of saying they don't actually offer ECC certs yet.

2 Likes

Just a random thought, but that could be related to the OIDs related to (extended) key usage that are included in the CSR. I mean for signing and whatnot.

2 Likes

Appreciate the thought, but it's unlikely. It's the same code generating the CSR regardless of the ACME server. It only includes Digital Signature and Key Encipherment in the standard key usage and the normal Client + Server authentication OIDs in the extended key usage. The same values work for their RSA endpoint.

2 Likes

try removing clinetauth extkeyuseage? I think some CA don't include that to leaf

3 Likes

Yes, I had two issues, one was that the certes library I use was constructing a csr that also asked for NonRepudiation for some reason. After contacting the ssldotcom support they told me what the issues was. I then got the RSA chain working, but couldn't find a key spec (ES256 etc) that would worked for the EC chain so gave up on that.

If RSA is also working for you and EC isn't you could try contacting support to see if they can tell you anything, or try it with certbot.

2 Likes

Key Encipherment is not valid for ECDSA certificates. This is for "when the subject public key is used for enciphering private or secret keys, i.e., for key transport." (RFC 5280).

For example, you usually set this in RSA certs to allow for the old static RSA key exchange in TLS. As you can't encipher with ECDSA, this key usage is not valid for that type.

I believe Let's Encrypt (and probably other CA's) strip off the attribute automatically for you, if it's not valid. Maybe they don't?

4 Likes

Brilliant, @Nummer378. I had no idea and this was totally the problem. Removed Key Encipherment from the CSR and it went through first try.

5 Likes

Yay! I got one right! In abstract, at least. :smiley:

3 Likes

Just to follow up. The Key Encipherment was definitely the solution to the finalization problem. But I still don't have a solution to the Account endpoint issues. I'll likely be emailing support about this to see what they say.

6 Likes

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