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 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.
@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.
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?
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?
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.
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.
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.
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!
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!
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).
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.
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.
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.
I'm sure you can figure out which CSR was used to get the certificate on the client side, right?
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.
You should point out that the article is from 2017.
Yes, 5 years ago!
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.