Skip to content

Commit fc6e532

Browse files
peppelinuxc00kiemon5ter
authored andcommitted
[Strengthen Encryption] PySAML2 Encrypted Assertions now works with Shibboleth SP 3
- Fixed: "ERROR Shibboleth.SSO.SAML2 [6] [default]: failed to decrypt assertion: Unable to resolve any key decryption keys." - Fixed: "WARN XMLTooling.Decrypter [7] [default]: XMLSecurity exception while decrypting key: XSECAlgorithmMapper::mapURIToHandler - URI http://www.w3.org/2001/04/xmlenc#rsa-1_5 disallowed by whitelist/blacklist policy"
1 parent 3d54fc7 commit fc6e532

File tree

4 files changed

+43
-23
lines changed

4 files changed

+43
-23
lines changed

src/saml2/data/templates/template_enc.xml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22
<EncryptedData
33
xmlns="http://www.w3.org/2001/04/xmlenc#"
44
Type="http://www.w3.org/2001/04/xmlenc#Element">
5-
<EncryptionMethod Algorithm=
6-
"http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
5+
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
76
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
87
<EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
9-
<EncryptionMethod Algorithm=
10-
"http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
8+
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>
119
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
1210
<KeyName/>
1311
</KeyInfo>

src/saml2/entity.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
from saml2.sigver import SigverError
6666
from saml2.sigver import SignatureError
6767
from saml2.sigver import make_temp
68+
from saml2.sigver import get_pem_wrapped_unwrapped
6869
from saml2.sigver import pre_encryption_part
6970
from saml2.sigver import pre_signature_part
7071
from saml2.sigver import pre_encrypt_assertion
@@ -654,18 +655,22 @@ def _encrypt_assertion(self, encrypt_cert, sp_entity_id, response, node_xpath=No
654655
_certs = self.metadata.certs(sp_entity_id, "any", "encryption")
655656
exception = None
656657
for _cert in _certs:
658+
wrapped_cert, unwrapped_cert = get_pem_wrapped_unwrapped(_cert)
657659
try:
658-
begin_cert = "-----BEGIN CERTIFICATE-----\n"
659-
end_cert = "\n-----END CERTIFICATE-----\n"
660-
if begin_cert not in _cert:
661-
_cert = "%s%s" % (begin_cert, _cert)
662-
if end_cert not in _cert:
663-
_cert = "%s%s" % (_cert, end_cert)
664-
tmp = make_temp(_cert.encode('ascii'),
660+
tmp = make_temp(wrapped_cert.encode('ascii'),
665661
decode=False,
666662
delete_tmpfiles=self.config.delete_tmpfiles)
663+
664+
# it would be possibile to handle many other args here ...
665+
pre_enc_part_dict = dict()
666+
if encrypt_cert:
667+
pre_enc_part_dict['encrypt_cert'] = unwrapped_cert
668+
pre_enc_part = pre_encryption_part(**pre_enc_part_dict)
669+
# end pre_enc_part
670+
671+
667672
response = self.sec.encrypt_assertion(response, tmp.name,
668-
pre_encryption_part(),
673+
pre_enc_part,
669674
node_xpath=node_xpath)
670675
return response
671676
except Exception as ex:

src/saml2/sigver.py

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import itertools
88
import logging
99
import os
10+
import re
1011
import six
1112
from uuid import uuid4 as gen_random_key
1213
from time import mktime
@@ -59,9 +60,11 @@
5960

6061
SIG = '{{{ns}#}}{attribute}'.format(ns=ds.NAMESPACE, attribute='Signature')
6162

62-
RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5'
63-
TRIPLE_DES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc'
63+
# DEPRECATED
64+
# RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5'
6465

66+
TRIPLE_DES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc'
67+
RSA_OAEP_MGF1P = "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"
6568

6669
class SigverError(SAMLError):
6770
pass
@@ -100,6 +103,14 @@ class CertificateError(SigverError):
100103
pass
101104

102105

106+
def get_pem_wrapped_unwrapped(cert):
107+
begin_cert = "-----BEGIN CERTIFICATE-----\n"
108+
end_cert = "\n-----END CERTIFICATE-----\n"
109+
unwrapped_cert = re.sub(f'{begin_cert}|{end_cert}', '', cert)
110+
wrapped_cert = f'{begin_cert}{unwrapped_cert}{end_cert}'
111+
return wrapped_cert, unwrapped_cert
112+
113+
103114
def read_file(*args, **kwargs):
104115
with open(*args, **kwargs) as handler:
105116
return handler.read()
@@ -1085,10 +1096,8 @@ def encrypt_cert_from_item(item):
10851096
pass
10861097

10871098
if _encrypt_cert is not None:
1088-
if _encrypt_cert.find('-----BEGIN CERTIFICATE-----\n') == -1:
1089-
_encrypt_cert = '-----BEGIN CERTIFICATE-----\n' + _encrypt_cert
1090-
if _encrypt_cert.find('\n-----END CERTIFICATE-----') == -1:
1091-
_encrypt_cert = _encrypt_cert + '\n-----END CERTIFICATE-----'
1099+
wrapped_cert, unwrapped_cert = get_pem_wrapped_unwrapped(_encrypt_cert)
1100+
_encrypt_cert = wrapped_cert
10921101
return _encrypt_cert
10931102

10941103

@@ -1872,8 +1881,10 @@ def pre_signature_part(
18721881
# </EncryptedData>
18731882

18741883

1875-
def pre_encryption_part(msg_enc=TRIPLE_DES_CBC, key_enc=RSA_1_5, key_name='my-rsa-key',
1876-
encrypted_key_id=None, encrypted_data_id=None):
1884+
def pre_encryption_part(msg_enc=TRIPLE_DES_CBC, key_enc=RSA_OAEP_MGF1P,
1885+
key_name='my-rsa-key',
1886+
encrypted_key_id=None, encrypted_data_id=None,
1887+
encrypt_cert=None):
18771888
"""
18781889
18791890
:param msg_enc:
@@ -1885,10 +1896,16 @@ def pre_encryption_part(msg_enc=TRIPLE_DES_CBC, key_enc=RSA_1_5, key_name='my-rs
18851896
ed_id = encrypted_data_id or "ED_{id}".format(id=gen_random_key())
18861897
msg_encryption_method = EncryptionMethod(algorithm=msg_enc)
18871898
key_encryption_method = EncryptionMethod(algorithm=key_enc)
1899+
1900+
enc_key_dict= dict(key_name=ds.KeyName(text=key_name))
1901+
enc_key_dict['x509_data'] = ds.X509Data(
1902+
x509_certificate=ds.X509Certificate(text=encrypt_cert))
1903+
key_info = ds.KeyInfo(**enc_key_dict)
1904+
18881905
encrypted_key = EncryptedKey(
18891906
id=ek_id,
18901907
encryption_method=key_encryption_method,
1891-
key_info=ds.KeyInfo(key_name=ds.KeyName(text=key_name)),
1908+
key_info=key_info,
18921909
cipher_data=CipherData(cipher_value=CipherValue(text='')),
18931910
)
18941911
key_info = ds.KeyInfo(encrypted_key=encrypted_key)

tests/test_42_enc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
__author__ = 'roland'
1414

15-
TMPL_NO_HEADER = """<ns0:EncryptedData xmlns:ns0="http://www.w3.org/2001/04/xmlenc#" xmlns:ns1="http://www.w3.org/2000/09/xmldsig#" Id="{ed_id}" Type="http://www.w3.org/2001/04/xmlenc#Element"><ns0:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" /><ns1:KeyInfo><ns0:EncryptedKey Id="{ek_id}"><ns0:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /><ns1:KeyInfo><ns1:KeyName>my-rsa-key</ns1:KeyName></ns1:KeyInfo><ns0:CipherData><ns0:CipherValue /></ns0:CipherData></ns0:EncryptedKey></ns1:KeyInfo><ns0:CipherData><ns0:CipherValue /></ns0:CipherData></ns0:EncryptedData>"""
16-
TMPL = "<?xml version='1.0' encoding='UTF-8'?>\n%s" % TMPL_NO_HEADER
15+
TMPL_NO_HEADER = """<ns0:EncryptedData xmlns:ns0="http://www.w3.org/2001/04/xmlenc#" xmlns:ns1="http://www.w3.org/2000/09/xmldsig#" Id="{ed_id}" Type="http://www.w3.org/2001/04/xmlenc#Element"><ns0:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" /><ns1:KeyInfo><ns0:EncryptedKey Id="{ek_id}"><ns0:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" /><ns1:KeyInfo><ns1:KeyName>my-rsa-key</ns1:KeyName><ns1:X509Data><ns1:X509Certificate /></ns1:X509Data></ns1:KeyInfo><ns0:CipherData><ns0:CipherValue /></ns0:CipherData></ns0:EncryptedKey></ns1:KeyInfo><ns0:CipherData><ns0:CipherValue /></ns0:CipherData></ns0:EncryptedData>"""
16+
TMPL = f"<?xml version='1.0' encoding='UTF-8'?>\n{TMPL_NO_HEADER}"
1717

1818
IDENTITY = {"eduPersonAffiliation": ["staff", "member"],
1919
"surName": ["Jeter"], "givenName": ["Derek"],

0 commit comments

Comments
 (0)