Rejecting SHA-1 CSRs - New hash algorithm

I wrote my own ACME client.

Today I noticed that the SHA-1 CSRs are no longer working in the staging environment.

I tried switching to SHA-256 and SHA-512, but I got a "signature algorithm not supported" error.

Which hash algorithm should I use now?

I'm pretty sure you should be using SHA-256. Are you getting that error from the ACME server, or something in your code that's creating the CSR?

This change was announced here; you should subscribe to the API Announcements category if you maintain an ACME client so that you don't get surprised by this sort of thing in the future.

5 Likes

@petercooperjr is correct. You probably want SHA-256. The Boulder code that enforces that is here: boulder/csr.go at 238c309088f5aa2d752160a7349d0d65e89da9a0 · letsencrypt/boulder · GitHub

If you can post your code, or an example CSR your code generated, we might be able to help you debug.

3 Likes

Thanks, @jsha and @petercooperjr!

I use an encryption component called Chilkat RSA:

https://www.chilkatsoft.com/refdoc/phpRsaRef.html#method33

Switching from SHA-1 to SHA-256 should be as simple as changing the following line in my ACME client:

FROM:

sASNCertReqInfoSig=oRSA.SignBytesENC(sCertReqInfoDer,"SHA-1")

TO:

sASNCertReqInfoSig=oRSA.SignBytesENC(sCertReqInfoDer,"SHA-256")

But it didn't work.

Any clues?

3 Likes

It's still not clear to me exactly what error you're getting where. Is your library returning that it doesn't support that hash method? Or are you actually managing to put an SHA-256 hash in the CSR but getting an error from the ACME server that it doesn't like it?

3 Likes

The text signature algorithm not supported is part of Boulder's error message, so I'm guessing the error is coming from the server.

@grudnitzki1 can you get your software to log the CSR before submission, and share that? CSRs contain public keys, not private keys, so they are safe to share.

3 Likes

Oh, is it the same error as if it's using SHA-1?

I'm wondering if you're hashing with SHA-256, but didn't update the part of the CSR that specifies which hash method was used.

3 Likes

Just poking around that documentation site a bit, it looks like what you're looking for might be the CSR's HashAlgorithm method. Though it says that SHA-256 is the default, so I'm sure I don't really know how that library works if you're making SHA-1 hashed CSRs with it if you didn't mean to.

https://www.chilkatsoft.com/refdoc/phpCsrRef.html

3 Likes

Yes @jsha , the error was coming from the server.

You are right, @petercooperjr !
I forgot to update the part of the CSR that specifies which hash method was used!

To resolve the case, besides changing sha1 to sha256, I also changed the following line of my code:

FROM:

iRet=oASNAlgId.AppendOid("1.2.840.113549.1.1.5")

TO:

iRet=oASNAlgId.AppendOid("1.2.840.113549.1.1.11")

The first line above is the SHA1 algorithm identifier.
The second is the SHA256 algorithm identifier.

Reference: https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-crypt_algorithm_identifier

Thank you both for the answers! You saved my day!

6 Likes

BTW, here is an URL that is already using a certificate I created with a SHA256 self-signed CSR:

https://www.boutiquedecanetas.com.br/

The cert seems OK, but I couldn't find that info on its details on Firefox.

Please let me know if everything is fine with it.

Thank you!

2 Likes

The CSR isn't used directly in the certificate on the web site; the Certificate Authority just uses the public key from it (and a couple other things), and the signature in the CSR (which includes that SHA-256 hash) just validates that the submitter in fact has the corresponding private key. But that signature isn't needed (and wouldn't be useful) in the final certificate. The final certificate has a signature from the CA, and those signatures have been using SHA-256 for a very long time (and you have no control over that part).

6 Likes

Also to make it explicitely clear, although @petercooperjr already explained it as such, any "fancy" detail incorporated into your CSR wouldn't be included into the certificate, unless Let's Encrypt actively does so. E.g., the only "fancy" thing currently added to the certificate if present in the CSR is the "must staple" TLS extension. Anything else is completely ignored.

4 Likes

Is it possible for you to confirm on the LE server side if the the following URL's cert was created with a SHA256 self-signed CSR?

https://www.boutiquedecanetas.com.br/

I'm not sure why I used the production servers, which still accept both SHA1 and SHA256 self-signed CSRs.

Well, I have no access to LE's servers (I'm just a random person on the Internet), and while the staff here has been known to dig through logs to solve particularly thorny problems I don't think there's a need for them to do so here. Can't you just point your code at the staging server and see if it still works? You don't need to install the staging certificate on your server, just see if your code can get one.

4 Likes

In the staging server it worked fine.

Well, if the staging server accepts your CSR, then I think you should be all set for the upcoming prod change.

4 Likes

I'm sure you can figure out which CSR was used to get the certificate on the client side, right?

2 Likes

Old information, as it is from 2017, The SHA1 hash function is now completely unsafe

Just for anyone not in the know that is new to the forum.

1 Like

You should point out that the article is from 2017.
Yes, 5 years ago!

1 Like

Yes, though in this particular case (signing the signature of your CSR) I think the practical implications of an attack are really limited.

But there's really no reason not to switch to SHA-256 (or better) at this point for pretty much everything either, now that it's so widely supported.

2 Likes