Re: ReportLab fails with ValueError on FIPS enabled systems
Andy Robinson <[email protected]> Mon, 30 Jun 2025 08:38:35 +0200
| Newsgroups | gmane.comp.python.reportlab.user |
|---|---|
| Message-ID | <CABjtApuxQza5RFAri1r3AP6F54Ni72gMgiQp_euqeoKFaWt8YQ@mail.gmail.com> |
--===============4359365736090289006== Content-Type: multipart/alternative; boundary="000000000000a2339e0638c447d5" --000000000000a2339e0638c447d5 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Martin, thanks for this! I had never heard of FIPS but this certainly seems harmless and something we could include in an upcoming release. I'll wait for my colleague Robin to review. -- Andy Robinson Managing Director, ReportLab On Mon, 30 Jun 2025 at 02:14, Martin Renters via reportlab-users < [email protected]> wrote: > First of all, I=E2=80=99d like to thank the ReportLab people for releasin= g such a > fabulous open-source toolkit. It truly makes generating PDFs so much easi= er! > > The problem I=E2=80=99m reporting affects users that have enabled FIPS mo= de on > their systems. In my particular case, it is a RHEL 9.6 system. When in FI= PS > mode, certain cryptographic functions are not permitted because of > weaknesses in the algorithms. In the case of ReportLab, this would be the > MD5 function which is used to calculate a document ID and is also used to > track fonts used, and a few other things, as well as in the PDF encryptio= n > functions themselves. > > When in FIPS mode, running a program will cause an exception similar to: > > Traceback (most recent call last): > > File "/opt/dftoolkit/bin/annotateCRF", line 82, in main > > annotate.build_pdf(plate_filter=3Dargs.plates) > > File > "//opt/dftoolkit/lib/python3.9/site-packages/dftoolkit/annotate.py", line > 549, in build_pdf > > self.doc.build(flowables) > > File > "//opt/dftoolkit/lib/python3.9/site-packages/reportlab/platypus/doctempla= te.py", > line 1062, in build > > self._startBuild(filename,canvasmaker) > > File > "//opt/dftoolkit/lib/python3.9/site-packages/reportlab/platypus/doctempla= te.py", > line 1032, in _startBuild > > self.canv =3D self._makeCanvas(filename=3Dfilename,canvasmaker=3Dcanv= asmaker) > > File > "//opt/dftoolkit/lib/python3.9/site-packages/reportlab/platypus/doctempla= te.py", > line 992, in _makeCanvas > > canv =3D canvasmaker(filename or self.filename, > > File > "//opt/dftoolkit/lib/python3.9/site-packages/reportlab/pdfgen/canvas.py", > line 320, in __init__ > > self._doc =3D pdfdoc.PDFDocument(compression=3DpageCompression, > > File > "//opt/dftoolkit/lib/python3.9/site-packages/reportlab/pdfbase/pdfdoc.py"= , > line 137, in __init__ > > sig =3D self.signature =3D md5() > > ValueError: [digital envelope routines] unsupported > > Most of the uses of MD5, aside from the use in the actual PDF encryption, > appear not to be security related. In Python 3.9, the hashlib functions c= an > be passed a keyword argument called =E2=80=98usedforsecurity=E2=80=99 (de= faulting to True) > that can be set to False if the hash algorithm isn=E2=80=99t used for sec= urity > purposes. This allows the use of MD5 hashes even on FIPS enabled systems > and allows ReportLab to successfully generate PDFs. Passing this keyword > argument on the older Python 3.6.8 doesn=E2=80=99t cause any ill effects. > > A small test program demonstrating the hashlib problem on a FIPS enabled > system, and the fix using usedforsecurity=3DFalse is as follows: > > $ more md5test.py > > from hashlib import md5 > > m =3D md5() > > m.update(b'This is a test') > > print(m.hexdigest()) > > > $ python md5test.py > > Traceback (most recent call last): > > File "/home/martin/md5test.py", line 2, in <module> > > m =3D md5() > > ValueError: [digital envelope routines] unsupported > > > Changing the m=3Dmd5() to m=3Dmd5(usedforsecurity=3DFalse) causes it to r= un > successfully: > > $ more md5test.py > > from hashlib import md5 > > m =3D md5(usedforsecurity=3DFalse) > > m.update(b'This is a test') > > print(m.hexdigest()) > > > $ python md5test.py > > ce114e4501d2f4e2dcea3e17b546f339 > > Attached is a patch that adds the usedforsecurity=3DFalse parameter in th= e > cases I believe are not security related. Alternatively, a different hash > function permitted by FIPS could be used. The actual PDF encryption code > isn=E2=80=99t modified by this patch and it will probably require the use= of > different algorithms to be FIPS compatible. > > Thanks for considering this patch, > > Martin > > diff -ru > ../venv3.9/lib/python3.9/site-packages/reportlab/lib/fontfinder.py > reportlab/lib/fontfinder.py > --- ../venv3.9/lib/python3.9/site-packages/reportlab/lib/fontfinder.py 20= 25-06-27 > 12:37:23.507252855 -0400 > +++ reportlab/lib/fontfinder.py 2025-06-29 15:08:52.470092313 -0400 > @@ -216,7 +216,7 @@ > """Base this on the directories...same set of directories > should give same cache""" > fsEncoding =3D self._fsEncoding > - hash =3D md5(b''.join(asBytes(_,enc=3DfsEncoding) for _ in > sorted(self._dirs))).hexdigest() > + hash =3D md5(b''.join(asBytes(_,enc=3DfsEncoding) for _ in > sorted(self._dirs)),usedforsecurity=3DFalse).hexdigest() > from reportlab.lib.utils import get_rl_tempfile > fn =3D get_rl_tempfile('fonts_%s.dat' % hash) > return fn > diff -ru ../venv3.9/lib/python3.9/site-packages/reportlab/lib/utils.py > reportlab/lib/utils.py > --- ../venv3.9/lib/python3.9/site-packages/reportlab/lib/utils.py 2025-06= -27 > 12:37:23.512252786 -0400 > +++ reportlab/lib/utils.py 2025-06-29 15:08:52.473092276 -0400 > @@ -55,7 +55,7 @@ > _rl_NoneType=3Dtype(None) > strTypes =3D (str,bytes) > def _digester(s): > - return md5(s if isBytes(s) else s.encode('utf8')).hexdigest() > + return md5(s if isBytes(s) else > s.encode('utf8'),usedforsecurity=3DFalse).hexdigest() > > def asBytes(v,enc=3D'utf8'): > if isinstance(v,bytes): return v > diff -ru > ../venv3.9/lib/python3.9/site-packages/reportlab/pdfbase/cidfonts.py > reportlab/pdfbase/cidfonts.py > --- ../venv3.9/lib/python3.9/site-packages/reportlab/pdfbase/cidfonts.py = 2025-06-27 > 12:37:23.519252690 -0400 > +++ reportlab/pdfbase/cidfonts.py 2025-06-29 15:08:52.668089932 -0400 > @@ -85,7 +85,7 @@ > self.parseCMAPFile(name) > > def _hash(self, text): > - hasher =3D md5() > + hasher =3D md5(usedforsecurity=3DFalse) > hasher.update(text) > return hasher.digest() > > diff -ru > ../venv3.9/lib/python3.9/site-packages/reportlab/pdfbase/pdfdoc.py > reportlab/pdfbase/pdfdoc.py > --- ../venv3.9/lib/python3.9/site-packages/reportlab/pdfbase/pdfdoc.py 20= 25-06-27 > 12:37:23.520252676 -0400 > +++ reportlab/pdfbase/pdfdoc.py 2025-06-29 15:08:52.672089884 -0400 > @@ -134,7 +134,7 @@ > self.setCompression(compression) > self._pdfVersion =3D pdfVersion > # signature for creating PDF ID > - sig =3D self.signature =3D md5() > + sig =3D self.signature =3D md5(usedforsecurity=3DFalse) > sig.update(b"a reportlab document") > self._timeStamp =3D TimeStamp(self.invariant) > cat =3D self._timeStamp.t > diff -ru ../venv3.9/lib/python3.9/site-packages/reportlab/pdfgen/canvas.p= y > reportlab/pdfgen/canvas.py > --- ../venv3.9/lib/python3.9/site-packages/reportlab/pdfgen/canvas.py 202= 5-06-27 > 12:37:23.523252635 -0400 > +++ reportlab/pdfgen/canvas.py 2025-06-29 15:08:52.786088514 -0400 > @@ -1131,9 +1131,9 @@ > """ > #check if we've done this one already... > if isUnicode(command): > - rawName =3D 'PS' + > hashlib.md5(command.encode('utf-8')).hexdigest() > + rawName =3D 'PS' + > hashlib.md5(command.encode('utf-8'),usedforsecurity=3DFalse).hexdigest() > else: > - rawName =3D 'PS' + hashlib.md5(command).hexdigest() > + rawName =3D 'PS' + > hashlib.md5(command,usedforsecurity=3DFalse).hexdigest() > regName =3D self._doc.getXObjectName(rawName) > psObj =3D self._doc.idToObject.get(regName, None) > if not psObj: > > _______________________________________________ > reportlab-users mailing list > [email protected] > https://pairlist2.pair.net/mailman/listinfo/reportlab-users > --000000000000a2339e0638c447d5 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div dir=3D"ltr">Martin, thanks for this!=C2=A0 I had neve= r heard of FIPS but this certainly seems harmless and something we could in= clude in an upcoming release.=C2=A0 I'll wait for my colleague Robin to= review.<div><br></div><div><span class=3D"gmail_signature_prefix">--</span= ><br><div dir=3D"ltr" class=3D"gmail_signature"><div dir=3D"ltr">Andy Robin= son<br>Managing Director, ReportLab<br></div><div dir=3D"ltr"><br></div></d= iv></div></div><div class=3D"gmail_quote gmail_quote_container"><div dir=3D= "ltr" class=3D"gmail_attr">On Mon, 30 Jun 2025 at 02:14, Martin Renters via= reportlab-users <<a href=3D"mailto:[email protected]= ">[email protected]</a>> wrote:<br></div><blockquote = class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px sol= id rgb(204,204,204);padding-left:1ex"><div>First of all, I=E2=80=99d like t= o thank the ReportLab people for releasing such a fabulous open-source tool= kit. It truly makes generating PDFs so much easier!<div><br></div><div>The = problem I=E2=80=99m reporting affects users that have enabled FIPS mode on = their systems. In my particular case, it is a RHEL 9.6 system. When in FIPS= mode, certain cryptographic functions are not permitted because of weaknes= ses in the algorithms. In the case of ReportLab, this would be the MD5 func= tion which is used to calculate a document ID and is also used to track fon= ts used, and a few other things, as well as in the PDF encryption functions= themselves.</div><div><br></div><div>When in FIPS mode, running a program = will cause an exception similar to:</div><div><br></div><div><p style=3D"ma= rgin:0px;font-style:normal;font-variant-caps:normal;font-stretch:normal;fon= t-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:none;font= -kerning:auto;font-variant-alternates:normal;font-variant-ligatures:normal;= font-variant-numeric:normal;font-variant-east-asian:normal;font-feature-set= tings:normal"><span style=3D"font-variant-ligatures:no-common-ligatures">Tr= aceback (most recent call last):</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">=C2=A0 File "/opt/dftoolkit/bin/annotateCRF", line 82= , in main</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">=C2=A0 =C2=A0 annotate.build_pdf(plate_filter=3Dargs.plates)</s= pan></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">=C2=A0 File "//opt/dftoolkit/lib/python3.9/site-packages/d= ftoolkit/annotate.py", line 549, in build_pdf</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">=C2=A0 =C2=A0 self.doc.build(flowables)</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">=C2=A0 File "//opt/dftoolkit/lib/python3.9/site-packages/r= eportlab/platypus/doctemplate.py", line 1062, in build</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">=C2=A0 =C2=A0 self._startBuild(filename,canvasmaker)</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">=C2=A0 File "//opt/dftoolkit/lib/python3.9/site-packages/r= eportlab/platypus/doctemplate.py", line 1032, in _startBuild</span></p= > <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">=C2=A0 =C2=A0 self.canv =3D self._makeCanvas(filename=3Dfilenam= e,canvasmaker=3Dcanvasmaker)</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">=C2=A0 File "//opt/dftoolkit/lib/python3.9/site-packages/r= eportlab/platypus/doctemplate.py", line 992, in _makeCanvas</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">=C2=A0 =C2=A0 canv =3D canvasmaker(filename or self.filename,</= span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">=C2=A0 File "//opt/dftoolkit/lib/python3.9/site-packages/r= eportlab/pdfgen/canvas.py", line 320, in __init__</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">=C2=A0 =C2=A0 self._doc =3D pdfdoc.PDFDocument(compression=3Dpa= geCompression,</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">=C2=A0 File "//opt/dftoolkit/lib/python3.9/site-packages/r= eportlab/pdfbase/pdfdoc.py", line 137, in __init__</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">=C2=A0 =C2=A0 sig =3D self.signature =3D md5()</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">ValueError: [digital envelope routines] unsupported</span></p><= /div><div><br></div><div>Most of the uses of MD5, aside from the use in the= actual PDF encryption, appear not to be security related. In Python 3.9, t= he hashlib functions can be passed a keyword argument called =E2=80=98usedf= orsecurity=E2=80=99 (defaulting to True) that can be set to False if the ha= sh algorithm isn=E2=80=99t used for security purposes. This allows the use = of MD5 hashes even on FIPS enabled systems and allows ReportLab to successf= ully generate PDFs. Passing this keyword argument on the older Python 3.6.8= doesn=E2=80=99t cause any ill effects.</div><div><br></div><div>A small te= st program demonstrating the hashlib problem on a FIPS enabled system, and = the fix using usedforsecurity=3DFalse is as follows:</div><div><br></div><d= iv><span style=3D"font-family:Menlo;font-size:11px">$ more md5test.py</span= ></div><div><p style=3D"margin:0px;font-style:normal;font-variant-caps:norm= al;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;= font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font= -variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asi= an:normal;font-feature-settings:normal"><span style=3D"font-variant-ligatur= es:no-common-ligatures">from hashlib import md5</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">m =3D md5()</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">m.update(b'This is a test')</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">print(m.hexdigest())</span></p><p style=3D"margin:0px;font-styl= e:normal;font-variant-caps:normal;font-stretch:normal;font-size:11px;line-h= eight:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font= -variant-alternates:normal;font-variant-ligatures:normal;font-variant-numer= ic:normal;font-variant-east-asian:normal;font-feature-settings:normal"><spa= n style=3D"font-variant-ligatures:no-common-ligatures"><br></span></p><p st= yle=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stretch:n= ormal;font-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:= none;font-kerning:auto;font-variant-alternates:normal;font-variant-ligature= s:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-fe= ature-settings:normal"><span style=3D"font-variant-ligatures:no-common-liga= tures">$ python md5test.py</span></p><p style=3D"margin:0px;font-style:norm= al;font-variant-caps:normal;font-stretch:normal;font-size:11px;line-height:= normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-varia= nt-alternates:normal;font-variant-ligatures:normal;font-variant-numeric:nor= mal;font-variant-east-asian:normal;font-feature-settings:normal"><span styl= e=3D"font-variant-ligatures:no-common-ligatures">Traceback (most recent cal= l last):</span></p><p style=3D"margin:0px;font-style:normal;font-variant-ca= ps:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family= :Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alternates:norm= al;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-e= ast-asian:normal;font-feature-settings:normal"><span style=3D"font-variant-= ligatures:no-common-ligatures">=C2=A0 File "/home/martin/md5test.py&qu= ot;, line 2, in <module></span></p><p style=3D"margin:0px;font-style:= normal;font-variant-caps:normal;font-stretch:normal;font-size:11px;line-hei= ght:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-v= ariant-alternates:normal;font-variant-ligatures:normal;font-variant-numeric= :normal;font-variant-east-asian:normal;font-feature-settings:normal"><span = style=3D"font-variant-ligatures:no-common-ligatures">=C2=A0 =C2=A0 m =3D md= 5()</span></p><p style=3D"margin:0px;font-stretch:normal;font-size:11px;lin= e-height:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;f= ont-variant-alternates:normal;font-variant-ligatures:normal;font-variant-nu= meric:normal;font-variant-east-asian:normal;font-feature-settings:normal"><= span style=3D"font-variant-ligatures:no-common-ligatures"> </span></p><p style=3D"margin:0px;font-style:normal;font-variant-caps:norma= l;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;f= ont-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-= variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asia= n:normal;font-feature-settings:normal"><span style=3D"font-variant-ligature= s:no-common-ligatures">ValueError: [digital envelope routines] unsupported<= /span></p><p style=3D"margin:0px;font-style:normal;font-variant-caps:normal= ;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;fo= nt-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-v= ariant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asian= :normal;font-feature-settings:normal"><span style=3D"font-variant-ligatures= :no-common-ligatures"><br></span></p></div><div>Changing the m=3Dmd5() to m= =3Dmd5(usedforsecurity=3DFalse) causes it to run successfully:</div><div><b= r></div><div><p style=3D"margin:0px;font-style:normal;font-variant-caps:nor= mal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo= ;font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;fon= t-variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-as= ian:normal;font-feature-settings:normal"><span style=3D"font-variant-ligatu= res:no-common-ligatures">$ more md5test.py</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">from hashlib import md5</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">m =3D md5(usedforsecurity=3DFalse)</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">m.update(b'This is a test')</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">print(m.hexdigest())</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures"><br></span></p><p style=3D"margin:0px;font-style:normal;font-va= riant-caps:normal;font-stretch:normal;font-size:11px;line-height:normal;fon= t-family:Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alterna= tes:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-v= ariant-east-asian:normal;font-feature-settings:normal"><span style=3D"font-= variant-ligatures:no-common-ligatures">$ python md5test.py</span></p> <p style=3D"margin:0px;font-style:normal;font-variant-caps:normal;font-stre= tch:normal;font-size:11px;line-height:normal;font-family:Menlo;font-size-ad= just:none;font-kerning:auto;font-variant-alternates:normal;font-variant-lig= atures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fo= nt-feature-settings:normal"><span style=3D"font-variant-ligatures:no-common= -ligatures">ce114e4501d2f4e2dcea3e17b546f339</span></p></div><div><span sty= le=3D"font-variant-ligatures:no-common-ligatures"><br></span></div><div>Att= ached is a patch that adds the usedforsecurity=3DFalse parameter in the cas= es I believe are not security related. Alternatively, a different hash func= tion permitted by FIPS could be used. The actual PDF encryption code isn=E2= =80=99t modified by this patch and it will probably require the use of diff= erent algorithms to be FIPS compatible.</div><div><br></div><div>Thanks for= considering this patch,</div><div><br></div><div>Martin</div><div><br></di= v><div><div><div>diff -ru ../venv3.9/lib/python3.9/site-packages/reportlab/= lib/fontfinder.py reportlab/lib/fontfinder.py</div><div>--- ../venv3.9/lib/= python3.9/site-packages/reportlab/lib/fontfinder.py<span style=3D"white-spa= ce:pre-wrap"> </span>2025-06-27 12:37:23.507252855 -0400</div><div>+++ repo= rtlab/lib/fontfinder.py<span style=3D"white-space:pre-wrap"> </span>2025-06= -29 15:08:52.470092313 -0400</div><div>@@ -216,7 +216,7 @@</div><div>=C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0"""Base this on the directories.= ..same set of directories</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0shoul= d give same cache"""</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0fsEncoding =3D self._fsEncoding</div><div>- =C2=A0 =C2=A0 =C2=A0 =C2= =A0hash =3D md5(b''.join(asBytes(_,enc=3DfsEncoding) for _ in sorte= d(self._dirs))).hexdigest()</div><div>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0hash =3D= md5(b''.join(asBytes(_,enc=3DfsEncoding) for _ in sorted(self._dir= s)),usedforsecurity=3DFalse).hexdigest()</div><div>=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0from reportlab.lib.utils import get_rl_tempfile</div><div>=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0fn =3D get_rl_tempfile('fonts_%s.dat' % = hash)</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return fn</div><div>diff = -ru ../venv3.9/lib/python3.9/site-packages/reportlab/lib/utils.py reportlab= /lib/utils.py</div><div>--- ../venv3.9/lib/python3.9/site-packages/reportla= b/lib/utils.py<span style=3D"white-space:pre-wrap"> </span>2025-06-27 12:37= :23.512252786 -0400</div><div>+++ reportlab/lib/utils.py<span style=3D"whit= e-space:pre-wrap"> </span>2025-06-29 15:08:52.473092276 -0400</div><div>@@ = -55,7 +55,7 @@</div><div>=C2=A0_rl_NoneType=3Dtype(None)</div><div>=C2=A0st= rTypes =3D (str,bytes)</div><div>=C2=A0def _digester(s):</div><div>- =C2=A0= =C2=A0return md5(s if isBytes(s) else s.encode('utf8')).hexdigest(= )</div><div>+ =C2=A0 =C2=A0return md5(s if isBytes(s) else s.encode('ut= f8'),usedforsecurity=3DFalse).hexdigest()</div><div>=C2=A0</div><div>= =C2=A0def asBytes(v,enc=3D'utf8'):</div><div>=C2=A0 =C2=A0 =C2=A0if= isinstance(v,bytes): return v</div><div>diff -ru ../venv3.9/lib/python3.9/= site-packages/reportlab/pdfbase/cidfonts.py reportlab/pdfbase/cidfonts.py</= div><div>--- ../venv3.9/lib/python3.9/site-packages/reportlab/pdfbase/cidfo= nts.py<span style=3D"white-space:pre-wrap"> </span>2025-06-27 12:37:23.5192= 52690 -0400</div><div>+++ reportlab/pdfbase/cidfonts.py<span style=3D"white= -space:pre-wrap"> </span>2025-06-29 15:08:52.668089932 -0400</div><div>@@ -= 85,7 +85,7 @@</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0self.parseCMAPFile(name)</div><div>=C2=A0</div><div>=C2=A0 =C2= =A0 =C2=A0def _hash(self, text):</div><div>- =C2=A0 =C2=A0 =C2=A0 =C2=A0has= her =3D md5()</div><div>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0hasher =3D md5(usedfor= security=3DFalse)</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0hasher.update= (text)</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return hasher.digest()</= div><div>=C2=A0</div><div>diff -ru ../venv3.9/lib/python3.9/site-packages/r= eportlab/pdfbase/pdfdoc.py reportlab/pdfbase/pdfdoc.py</div><div>--- ../ven= v3.9/lib/python3.9/site-packages/reportlab/pdfbase/pdfdoc.py<span style=3D"= white-space:pre-wrap"> </span>2025-06-27 12:37:23.520252676 -0400</div><div= >+++ reportlab/pdfbase/pdfdoc.py<span style=3D"white-space:pre-wrap"> </spa= n>2025-06-29 15:08:52.672089884 -0400</div><div>@@ -134,7 +134,7 @@</div><d= iv>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self.setCompression(compression)</div>= <div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0self._pdfVersion =3D pdfVersion</div= ><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0# signature for creating PDF ID</di= v><div>- =C2=A0 =C2=A0 =C2=A0 =C2=A0sig =3D self.signature =3D md5()</div><= div>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0sig =3D self.signature =3D md5(usedforsecu= rity=3DFalse)</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0sig.update(b"= ;a reportlab document")</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0se= lf._timeStamp =3D TimeStamp(self.invariant)</div><div>=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0cat =3D self._timeStamp.t</div><div>diff -ru ../venv3.9/lib/py= thon3.9/site-packages/reportlab/pdfgen/canvas.py reportlab/pdfgen/canvas.py= </div><div>--- ../venv3.9/lib/python3.9/site-packages/reportlab/pdfgen/canv= as.py<span style=3D"white-space:pre-wrap"> </span>2025-06-27 12:37:23.52325= 2635 -0400</div><div>+++ reportlab/pdfgen/canvas.py<span style=3D"white-spa= ce:pre-wrap"> </span>2025-06-29 15:08:52.786088514 -0400</div><div>@@ -1131= ,9 +1131,9 @@</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"""= ;</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0#check if we've done this= one already...</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if isUnicode(co= mmand):</div><div>- =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0rawName =3D &#= 39;PS' + hashlib.md5(command.encode('utf-8')).hexdigest()</div>= <div>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0rawName =3D 'PS' + = hashlib.md5(command.encode('utf-8'),usedforsecurity=3DFalse).hexdig= est()</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else:</div><div>- =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0rawName =3D 'PS' + hashlib.md5(co= mmand).hexdigest()</div><div>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0raw= Name =3D 'PS' + hashlib.md5(command,usedforsecurity=3DFalse).hexdig= est()</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0regName =3D self._doc.get= XObjectName(rawName)</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0psObj =3D = self._doc.idToObject.get(regName, None)</div><div>=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0if not psObj:</div></div></div><div><br></div></div>_____________= __________________________________<br> reportlab-users mailing list<br> <a href=3D"mailto:[email protected]" target=3D"_blank">r= [email protected]</a><br> <a href=3D"https://pairlist2.pair.net/mailman/listinfo/reportlab-users" rel= =3D"noreferrer" target=3D"_blank">https://pairlist2.pair.net/mailman/listin= fo/reportlab-users</a><br> </blockquote></div><div><br clear=3D"all"></div><div><br></div></div> --000000000000a2339e0638c447d5-- --===============4359365736090289006== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline