Updating to a new IDP with Django 2.2 & Djangosaml2 on Python 3.6
ERROR ::2023-11-10 16:47:47,443::sigver sigver.py:850 ::returncode=1
error=func=xmlSecTransformNodeRead:file=transforms.c:line=1549:obj=unknown:subj=xmlSecTransformIdListFindByHref:error=1:xmlsec library function failed:href=http://www.w3.org/2009/xmlenc11#aes128-gcm
func=xmlSecTransformCtxNodeRead:file=transforms.c:line=694:obj=unknown:subj=xmlSecTransformNodeRead:error=1:xmlsec library function failed:name=EncryptionMethod
func=xmlSecEncCtxEncDataNodeRead:file=xmlenc.c:line=905:obj=unknown:subj=xmlSecTransformCtxNodeRead:error=1:xmlsec library function failed:node=EncryptionMethod
func=xmlSecEncCtxDecryptToBuffer:file=xmlenc.c:line=715:obj=unknown:subj=xmlSecEncCtxEncDataNodeRead:error=1:xmlsec library function failed:
func=xmlSecEncCtxDecrypt:file=xmlenc.c:line=623:obj=unknown:subj=xmlSecEncCtxDecryptToBuffer:error=1:xmlsec library function failed:
Error: failed to decrypt file
Error: failed to decrypt file "/tmp/tmptkxst803"
output=
ERROR ::2023-11-10 16:47:47,458::sigver sigver.py:850 ::returncode=1
error=func=xmlSecTransformNodeRead:file=transforms.c:line=1549:obj=unknown:subj=xmlSecTransformIdListFindByHref:error=1:xmlsec library function failed:href=http://www.w3.org/2009/xmlenc11#aes128-gcm
func=xmlSecTransformCtxNodeRead:file=transforms.c:line=694:obj=unknown:subj=xmlSecTransformNodeRead:error=1:xmlsec library function failed:name=EncryptionMethod
func=xmlSecEncCtxEncDataNodeRead:file=xmlenc.c:line=905:obj=unknown:subj=xmlSecTransformCtxNodeRead:error=1:xmlsec library function failed:node=EncryptionMethod
func=xmlSecEncCtxDecryptToBuffer:file=xmlenc.c:line=715:obj=unknown:subj=xmlSecEncCtxEncDataNodeRead:error=1:xmlsec library function failed:
func=xmlSecEncCtxDecrypt:file=xmlenc.c:line=623:obj=unknown:subj=xmlSecEncCtxDecryptToBuffer:error=1:xmlsec library function failed:
Error: failed to decrypt file
Error: failed to decrypt file "/tmp/tmpmpjdtmyj"
After going down several rabbit-holes, testing different signing algorithms, I finally read the error message carefully.
The error comes from the xmlsec1 binary which is used to perform the actual cryptographic functions needed by PySAML2, namely signing, verification and encrypt/decryption, and actually clearly states the issue in the first line:
error=func=xmlSecTransformNodeRead:file=transforms.c:line=1549:obj=unknown:subj=xmlSecTransformIdListFindByHref:error=1:xmlsec library function failed:href=http://www.w3.org/2009/xmlenc11#aes128-gcm
Breaking it down into pieces and translating:
error=func=xmlSecTransformNodeRead:file=transforms.c:line=1549:obj=unknown:
- Error reading a node in the target XML file due to an unknown object (executable code)
file=transforms.c:line=1549:obj=unknown:
- Error reading a node in the XML file
subj=xmlSecTransformIdListFindByHref:error=1:xmlsec library function failed:href=http://www.w3.org/2009/xmlenc11#aes128-gcm:
- The missing executable code referred to in the target XML file is identified by the URL 'http://www.w3.org/2009/xmlenc11#aes128-gcm'
Specifically the last part "aes128-gcm" refers to an encryption/decryption algorithm based on the AES algorithm. Now encryption is a very complex and difficult subject, as security is almost impossible to generalize, and even minor changes in how it applies can completely change its effectiveness. However it seems that the specific implementations in the 2001 W3C XML Encryption Standard require AES CBC and were completely vulnerable to attack, detailed by Matthew Green here.
However, if we look at the xmlsec1 changelog here https://www.aleksey.com/xmlsec/news.html, AES CBC support was added to the xmlsec1 (openssl) edition in version 1.2.27 on October 23 2018, and the version shipped with RHEL 7 is xmlsec1 (openssl) 1.2.20. Creating a local copy is not easy as xmlsec1 relies on libXML, OpenSSL, and other system packages, and compiling/linking against secure versions of them is not a trivial exercise.
Luckily they were able to downgrade the requirements back to AES128-CBC for my specific SP and mitigate the risks as all IDP/SP request/responses are only available over SSL, however time to finish up the OS2 replacement built on RHEL 8, Python 3.11 with a more modern xmlsec1!