Repository: python/mypy

Issue:
Bug: Mypy uses MD5 which causes a traceback in FIPS environment
Hello,

Mypy does not work when FIPS (Federal Information Processing Standards) is enabled on RHEL 8.1. The problem is that mypy is calculating MD5 hashes of files and crashes with a traceback:
```
# python3 -m mypy -p pcs --show-traceback --no-incremental
/root/devel/pcs/pcs/__init__.py: error: INTERNAL ERROR -- Please try using mypy master on Github:
https://mypy.rtfd.io/en/latest/common_issues.html#using-a-development-mypy-build
Please report a bug at https://github.com/python/mypy/issues
version: 0.740
Traceback (most recent call last):
  File "/usr/lib64/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib64/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "mypy/build.py", line 1845, in wrap_context
  File "mypy/build.py", line 1945, in parse_file
  File "mypy/fscache.py", line 259, in read
ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS
/root/devel/pcs/pcs/__init__.py: : note: use --pdb to drop into pdb
```
`__init__.py` is an empty file.

Upstream version doesn't work either:
```
# python3 -m mypy -p pcs --show-traceback --no-incremental
/root/devel/pcs/pcs/__init__.py: error: INTERNAL ERROR -- Please try using mypy master on Github:
https://mypy.rtfd.io/en/latest/common_issues.html#using-a-development-mypy-build
Please report a bug at https://github.com/python/mypy/issues
version: 0.750+dev.e99a2b57e160785b09f669e28d68f38d1970c476
Traceback (most recent call last):
  File "/usr/lib64/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib64/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/usr/local/lib/python3.6/site-packages/mypy/__main__.py", line 12, in <module>
    main(None, sys.stdout, sys.stderr)
  File "/usr/local/lib/python3.6/site-packages/mypy/main.py", line 89, in main
    res = build.build(sources, options, None, flush_errors, fscache, stdout, stderr)
  File "/usr/local/lib/python3.6/site-packages/mypy/build.py", line 167, in build
    sources, options, alt_lib_path, flush_errors, fscache, stdout, stderr, extra_plugins
  File "/usr/local/lib/python3.6/site-packages/mypy/build.py", line 235, in _build
    graph = dispatch(sources, manager, stdout)
  File "/usr/local/lib/python3.6/site-packages/mypy/build.py", line 2567, in dispatch
    graph = load_graph(sources, manager)
  File "/usr/local/lib/python3.6/site-packages/mypy/build.py", line 2726, in load_graph
    root_source=True)
  File "/usr/local/lib/python3.6/site-packages/mypy/build.py", line 1825, in __init__
    self.parse_file()
  File "/usr/local/lib/python3.6/site-packages/mypy/build.py", line 2016, in parse_file
    self.ignore_all or self.options.ignore_errors)
  File "/usr/lib64/python3.6/contextlib.py", line 99, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/local/lib/python3.6/site-packages/mypy/build.py", line 1894, in wrap_context
    yield
  File "/usr/local/lib/python3.6/site-packages/mypy/build.py", line 1994, in parse_file
    source = decode_python_encoding(manager.fscache.read(path),
  File "/usr/local/lib/python3.6/site-packages/mypy/fscache.py", line 259, in read
    md5hash = hashlib.md5(data).hexdigest()
ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS
/root/devel/pcs/pcs/__init__.py: : note: use --pdb to drop into pdb
```

Python version:
```
Python 3.6.8 (default, Oct 11 2019, 15:04:54)
[GCC 8.3.1 20190507 (Red Hat 8.3.1-4)] on linux
```

Perhaps SHA1 could be used instead of MD5:
```
>>> import hashlib
>>> hashlib.md5(b"test")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS
>>> hashlib.sha1(b"test")
<sha1 HASH object @ 0x7fdaf70689e0>
```

Thanks for looking into this.


Discussion:
Replacing MD5 with SHA1 sounds reasonable to me. @msullivan What do you think?
Sorry, missed this. Yeah using sha1 would be fine.

I'll do this in two steps: one to refactor where we do everything and one to change the hash over.

Resolving patch:
diff --git a/mypy/util.py b/mypy/util.py
--- a/mypy/util.py
+++ b/mypy/util.py
@@ -476,7 +476,9 @@ def hash_digest(data: bytes) -> str:
     accidental collision, but we don't really care about any of the
     cryptographic properties.
     """
-    return hashlib.md5(data).hexdigest()
+    # Once we drop Python 3.5 support, we should consider using
+    # blake2b, which is faster.
+    return hashlib.sha256(data).hexdigest()
 
 
 class FancyFormatter:


Test patch: