6060from saml2 .samlp import SessionIndex
6161from saml2 .samlp import artifact_resolve_from_string
6262from saml2 .samlp import response_from_string
63- from saml2 .sigver import SignatureError
63+ from saml2 .sigver import SignatureError , XMLSEC_SESSION_KEY_URI_TO_ALG
6464from saml2 .sigver import SigverError
6565from saml2 .sigver import get_pem_wrapped_unwrapped
6666from saml2 .sigver import make_temp
7878from saml2 .xmldsig import SIG_ALLOWED_ALG
7979from saml2 .xmldsig import DefaultSignature
8080
81-
8281logger = logging .getLogger (__name__ )
8382
8483__author__ = "rolandh"
@@ -181,6 +180,9 @@ def __init__(self, entity_type, config=None, config_file="", virtual_organizatio
181180
182181 self .sec = security_context (self .config )
183182
183+ self .encrypt_assertion_session_key_algs = self .config .encrypt_assertion_session_key_algs
184+ self .encrypt_assertion_cert_key_algs = self .config .encrypt_assertion_cert_key_algs
185+
184186 if virtual_organization :
185187 if isinstance (virtual_organization , str ):
186188 self .vorg = self .config .vorg [virtual_organization ]
@@ -644,34 +646,97 @@ def has_encrypt_cert_in_metadata(self, sp_entity_id):
644646 return True
645647 return False
646648
647- def _encrypt_assertion (self , encrypt_cert , sp_entity_id , response , node_xpath = None ):
649+ def _encrypt_assertion (
650+ self ,
651+ encrypt_cert ,
652+ sp_entity_id ,
653+ response ,
654+ node_xpath = None ,
655+ encrypt_cert_session_key_alg = None ,
656+ encrypt_cert_cert_key_alg = None ,
657+ ):
648658 """Encryption of assertions.
649659
650660 :param encrypt_cert: Certificate to be used for encryption.
651661 :param sp_entity_id: Entity ID for the calling service provider.
652662 :param response: A samlp.Response
663+ :param encrypt_cert_cert_key_alg: algorithm used for encrypting session key
664+ :param encrypt_cert_session_key_alg: algorithm used for encrypting assertion
665+ :param encrypt_cert_cert_key_alg:
653666 :param node_xpath: Unquie path to the element to be encrypted.
654667 :return: A new samlp.Resonse with the designated assertion encrypted.
655668 """
656669 _certs = []
657670
658671 if encrypt_cert :
659- _certs .append ((None , encrypt_cert ))
672+ _certs .append ((None , encrypt_cert , None , None ))
660673 elif sp_entity_id is not None :
661- _certs = self .metadata .certs (sp_entity_id , "any" , "encryption" )
674+ _certs = self .metadata .certs (sp_entity_id , "any" , "encryption" , get_with_usage_and_encryption_methods = True )
662675 exception = None
663- for _cert_name , _cert in _certs :
676+
677+ # take certs with encryption and encryption_methods first (priority 1)
678+ sorted_certs = []
679+ for _unpacked_cert in _certs :
680+ _cert_name , _cert , _cert_use , _cert_encryption_methods = _unpacked_cert
681+ if _cert_use == "encryption" and _cert_encryption_methods :
682+ sorted_certs .append (_unpacked_cert )
683+
684+ # take certs with encryption or encryption_methods (priority 2)
685+ for _unpacked_cert in _certs :
686+ _cert_name , _cert , _cert_use , _cert_encryption_methods = _unpacked_cert
687+ if _cert_use == "encryption" and _unpacked_cert not in sorted_certs :
688+ sorted_certs .append (_unpacked_cert )
689+
690+ for _unpacked_cert in _certs :
691+ if _unpacked_cert not in sorted_certs :
692+ sorted_certs .append (_unpacked_cert )
693+
694+ for _cert_name , _cert , _cert_use , _cert_encryption_methods in sorted_certs :
664695 wrapped_cert , unwrapped_cert = get_pem_wrapped_unwrapped (_cert )
665696 try :
666697 tmp = make_temp (
667698 wrapped_cert .encode ("ascii" ),
668699 decode = False ,
669700 delete_tmpfiles = self .config .delete_tmpfiles ,
670701 )
702+
703+ msg_enc = (
704+ encrypt_cert_session_key_alg
705+ if encrypt_cert_session_key_alg
706+ else self .encrypt_assertion_session_key_algs [0 ]
707+ )
708+ key_enc = (
709+ encrypt_cert_cert_key_alg if encrypt_cert_cert_key_alg else self .encrypt_assertion_cert_key_algs [0 ]
710+ )
711+
712+ if encrypt_cert != _cert and _cert_encryption_methods :
713+ viable_session_key_algs = []
714+ for alg in self .encrypt_assertion_session_key_algs :
715+ for cert_method in _cert_encryption_methods :
716+ if cert_method .get ("algorithm" ) == alg :
717+ viable_session_key_algs .append (alg )
718+
719+ viable_cert_algs = []
720+ for alg in self .encrypt_assertion_cert_key_algs :
721+ for cert_method in _cert_encryption_methods :
722+ if cert_method .get ("algorithm" ) == alg :
723+ viable_cert_algs .append (alg )
724+
725+ if viable_session_key_algs :
726+ msg_enc = viable_session_key_algs [0 ]
727+
728+ if viable_cert_algs :
729+ key_enc = viable_cert_algs [0 ]
730+
731+ key_type = XMLSEC_SESSION_KEY_URI_TO_ALG .get (msg_enc )
732+
671733 response = self .sec .encrypt_assertion (
672734 response ,
673735 tmp .name ,
674- pre_encryption_part (key_name = _cert_name , encrypt_cert = unwrapped_cert ),
736+ pre_encryption_part (
737+ key_name = _cert_name , encrypt_cert = unwrapped_cert , msg_enc = msg_enc , key_enc = key_enc
738+ ),
739+ key_type = key_type ,
675740 node_xpath = node_xpath ,
676741 )
677742 return response
@@ -697,7 +762,11 @@ def _response(
697762 encrypt_assertion_self_contained = False ,
698763 encrypted_advice_attributes = False ,
699764 encrypt_cert_advice = None ,
765+ encrypt_cert_advice_cert_key_alg = None ,
766+ encrypt_cert_advice_session_key_alg = None ,
700767 encrypt_cert_assertion = None ,
768+ encrypt_cert_assertion_cert_key_alg = None ,
769+ encrypt_cert_assertion_session_key_alg = None ,
701770 sign_assertion = None ,
702771 pefim = False ,
703772 sign_alg = None ,
@@ -731,8 +800,16 @@ def _response(
731800 element should be encrypted.
732801 :param encrypt_cert_advice: Certificate to be used for encryption of
733802 assertions in the advice element.
803+ :param encrypt_cert_advice_cert_key_alg: algorithm used for encrypting session key
804+ by encrypt_cert_advice
805+ :param encrypt_cert_advice_session_key_alg: algorithm used for encrypting assertion
806+ when using encrypt_cert_advice
734807 :param encrypt_cert_assertion: Certificate to be used for encryption
735808 of assertions.
809+ :param encrypt_cert_assertion_cert_key_alg: algorithm used for encrypting session key
810+ by encrypt_cert_assertion
811+ :param encrypt_cert_assertion_session_key_alg: algorithm used for encrypting assertion when
812+ using encrypt_cert_assertion
736813 :param sign_assertion: True if assertions should be signed.
737814 :param pefim: True if a response according to the PEFIM profile
738815 should be created.
@@ -856,6 +933,8 @@ def _response(
856933 sp_entity_id ,
857934 response ,
858935 node_xpath = node_xpath ,
936+ encrypt_cert_session_key_alg = encrypt_cert_advice_session_key_alg ,
937+ encrypt_cert_cert_key_alg = encrypt_cert_advice_cert_key_alg ,
859938 )
860939 response = response_from_string (response )
861940
@@ -900,7 +979,13 @@ def _response(
900979 response = signed_instance_factory (response , self .sec , to_sign_assertion )
901980
902981 # XXX encrypt assertion
903- response = self ._encrypt_assertion (encrypt_cert_assertion , sp_entity_id , response )
982+ response = self ._encrypt_assertion (
983+ encrypt_cert_assertion ,
984+ sp_entity_id ,
985+ response ,
986+ encrypt_cert_session_key_alg = encrypt_cert_assertion_session_key_alg ,
987+ encrypt_cert_cert_key_alg = encrypt_cert_assertion_cert_key_alg ,
988+ )
904989 else :
905990 # XXX sign other parts! (defiend by to_sign)
906991 if to_sign :
@@ -1357,7 +1442,6 @@ def create_manage_name_id_response(
13571442 digest_alg = None ,
13581443 ** kwargs ,
13591444 ):
1360-
13611445 rinfo = self .response_args (request , bindings )
13621446
13631447 response = self ._status_response (
0 commit comments