diff options
author | Lars Hupfeldt <lhn@hupfeldtit.dk> | 2020-05-05 00:50:51 +0200 |
---|---|---|
committer | Lars Hupfeldt <lhn@hupfeldtit.dk> | 2020-05-05 00:50:51 +0200 |
commit | 1b8415a1c1c1b82338327eb14ac4872d753c5b73 (patch) | |
tree | d493725beeee8d27ba589c3d5312f16ef6089d27 | |
parent | 153682dd4c8a56d3becff70b0264df4c13b6eb41 (diff) | |
download | sphinx-git-1b8415a1c1c1b82338327eb14ac4872d753c5b73.tar.gz |
Introduce fips_safe_md5, see issue #7611
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | CHANGES | 1 | ||||
-rw-r--r-- | sphinx/builders/html/__init__.py | 5 | ||||
-rw-r--r-- | sphinx/ext/inheritance_diagram.py | 4 | ||||
-rw-r--r-- | sphinx/util/__init__.py | 17 | ||||
-rw-r--r-- | tests/test_build_html.py | 7 |
6 files changed, 25 insertions, 10 deletions
@@ -85,6 +85,7 @@ Other contributors, listed alphabetically, are: * Daniel Pizetta -- inheritance diagram improvements * KINEBUCHI Tomohiko -- typing Sphinx as well as docutils * Adrián Chaves (Gallaecio) -- coverage builder improvements +* Lars Hupfeldt Nielsen - OpenSSL FIPS mode md5 bug fix Many thanks for all contributions! @@ -17,6 +17,7 @@ Bugs fixed ---------- * #7567: autodoc: parametrized types are shown twice for generic types +* #7611: md5 fails when OpenSSL FIPS is enabled Testing -------- diff --git a/sphinx/builders/html/__init__.py b/sphinx/builders/html/__init__.py index 320c7feb6..982889b74 100644 --- a/sphinx/builders/html/__init__.py +++ b/sphinx/builders/html/__init__.py @@ -13,7 +13,6 @@ import posixpath import re import sys import warnings -from hashlib import md5 from os import path from typing import Any, Dict, IO, Iterable, Iterator, List, Set, Tuple @@ -38,7 +37,7 @@ from sphinx.highlighting import PygmentsBridge from sphinx.locale import _, __ from sphinx.search import js_index from sphinx.theming import HTMLThemeFactory -from sphinx.util import logging, progress_message, status_iterator +from sphinx.util import logging, progress_message, status_iterator, fips_safe_md5 from sphinx.util.docutils import is_html5_writer_available, new_document from sphinx.util.fileutil import copy_asset from sphinx.util.i18n import format_date @@ -77,7 +76,7 @@ def get_stable_hash(obj: Any) -> str: return get_stable_hash(list(obj.items())) elif isinstance(obj, (list, tuple)): obj = sorted(get_stable_hash(o) for o in obj) - return md5(str(obj).encode()).hexdigest() + return fips_safe_md5(str(obj).encode()).hexdigest() class Stylesheet(str): diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py index db2a15b14..407fe09f5 100644 --- a/sphinx/ext/inheritance_diagram.py +++ b/sphinx/ext/inheritance_diagram.py @@ -38,7 +38,6 @@ r""" import builtins import inspect import re -from hashlib import md5 from importlib import import_module from typing import Any, Dict, Iterable, List, Tuple from typing import cast @@ -55,6 +54,7 @@ from sphinx.ext.graphviz import ( graphviz, figure_wrapper, render_dot_html, render_dot_latex, render_dot_texinfo ) +from sphinx.util import fips_safe_md5 from sphinx.util.docutils import SphinxDirective from sphinx.writers.html import HTMLTranslator from sphinx.writers.latex import LaTeXTranslator @@ -387,7 +387,7 @@ class InheritanceDiagram(SphinxDirective): def get_graph_hash(node: inheritance_diagram) -> str: encoded = (node['content'] + str(node['parts'])).encode() - return md5(encoded).hexdigest()[-10:] + return fips_safe_md5(encoded).hexdigest()[-10:] def html_visit_inheritance_diagram(self: HTMLTranslator, node: inheritance_diagram) -> None: diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py index 12ae051f1..3c219cc67 100644 --- a/sphinx/util/__init__.py +++ b/sphinx/util/__init__.py @@ -170,6 +170,21 @@ class FilenameUniqDict(dict): self._existing = state +def fips_safe_md5(data=b'', **kwargs): + """Wrapper around hashlib.md5 + + Attempt call with 'usedforsecurity=False' if we get a ValueError, which happens when OpenSSL FIPS mode is enabled: + ValueError: error:060800A3:digital envelope routines:EVP_DigestInit_ex:disabled for fips + + See: https://github.com/sphinx-doc/sphinx/issues/7611 + """ + + try: + return md5(data, **kwargs) + except ValueError: + return md5(data, **kwargs, usedforsecurity=False) + + class DownloadFiles(dict): """A special dictionary for download files. @@ -179,7 +194,7 @@ class DownloadFiles(dict): def add_file(self, docname: str, filename: str) -> str: if filename not in self: - digest = md5(filename.encode()).hexdigest() + digest = fips_safe_md5(filename.encode()).hexdigest() dest = '%s/%s' % (digest, os.path.basename(filename)) self[filename] = (set(), dest) diff --git a/tests/test_build_html.py b/tests/test_build_html.py index ede368315..a93553361 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -10,7 +10,6 @@ import os import re -from hashlib import md5 from itertools import cycle, chain import pytest @@ -19,7 +18,7 @@ from html5lib import HTMLParser from sphinx.builders.html import validate_html_extra_path, validate_html_static_path from sphinx.errors import ConfigError from sphinx.testing.util import strip_escseq -from sphinx.util import docutils +from sphinx.util import docutils, fips_safe_md5 from sphinx.util.inventory import InventoryFile @@ -450,9 +449,9 @@ def test_html_download(app): @pytest.mark.sphinx('html', testroot='roles-download') def test_html_download_role(app, status, warning): app.build() - digest = md5(b'dummy.dat').hexdigest() + digest = fips_safe_md5(b'dummy.dat').hexdigest() assert (app.outdir / '_downloads' / digest / 'dummy.dat').exists() - digest_another = md5(b'another/dummy.dat').hexdigest() + digest_another = fips_safe_md5(b'another/dummy.dat').hexdigest() assert (app.outdir / '_downloads' / digest_another / 'dummy.dat').exists() content = (app.outdir / 'index.html').read_text() |