I am trying to use certbot on a machine that is in FIPS mode. I run FIPS mode because one don't want to write code that wouldn't be executable on a FIPS machine. My setup is Red Hat 7.5 with all the current updates, EPEL installed, with the following packages: httpd, mod_ssl, certbot [0.23]. I ran accross the following thread that indicated that FIPS mode wasn't available: OpenSSL in FIPS Mode does not have MD5 Hash Functionality Required by Certbot. Unfortunately, I can't reopen that thread so hopefully others might be able to find this one.
I had the same error experienced in that thread, including the stack trace:
File “/usr/lib/python2.7/site-packages/certbot/main.py”, line 861, in main return config.func(config, plugins)
File “/usr/lib/python2.7/site-packages/certbot/main.py”, line 770, in certonly le_client = _init_le_client(config, auth, installer)
File “/usr/lib/python2.7/site-packages/certbot/main.py”, line 479, in _init_le_client acc, acme = _determine_account(config)
File “/usr/lib/python2.7/site-packages/certbot/main.py”, line 378, in _determine_account config, account_storage, tos_cb=_tos_cb)
File “/usr/lib/python2.7/site-packages/certbot/client.py”, line 174, in register acc = account.Account(regr, key)
File “/usr/lib/python2.7/site-packages/certbot/account.py”, line 62, in init
The command I was writing was (with substitutions for my domain and my email):
certbot certonly --test-cert -d *.MYDOMAIN --keep-until-expiring --agree-tos -m MY@EMAIL.COM
So, I decided to look at account.py, around line 62 to see what was going on. It is an invocation to hashlib.md5(). Well, the failure makes sense as FIPS regards MD5 as unsafe and prohibits the use of MD5. I then went to the python documentation and checked on hashlib. It presents a convenient function called algorithms and algorithms_guaranteed. I started up a small python environment through 'python' and gave it a try:
guaranteed_algorithms = hashlib.algorithms_guaranteed
set(['sha1', 'sha224', 'sha384', 'sha256', 'sha512', 'md5'])
So, it looks like it isn't a cross-platform problem and it appears that stronger digests such as sha256 and sha512 are available. OK
Next, on to the totality of certbot's python. Let's see where else MD5 is used:
grep -i 'md5' /usr/lib/python2.7/site-packages/certbot/*.py
/usr/lib/python2.7/site-packages/certbot/account.py: self.id = hashlib.md5(
Well, it seems this is the ONLY invocation of it. Well, I can't quite tell exactly what it is doing. It appears it is hashing the email to make some form of ID, but I really can't figure out if this is just local or if it is sent to LE servers.
So, I just tweaked the line to:
self.id = hashlib.sha256(
... and everything looks like it worked. Of course, I now need to maintain this patch forever, but can anyone comment on what the implications are of using sha256 instead of md5 are? Are there any other implications of using sha256 instead of MD5 that will come to bite me later?