def sign_file(xml_file, root_id, assert_id, key_file, cert_file): """sign *xml_file* with *key_file* and include content of *cert_file*. *xml_file* can be a file, a filename string or an HTTP/FTP url. *key_file* contains the PEM encoded private key. It must be a filename string. *cert_file* contains a PEM encoded certificate (corresponding to *key_file*), included as `X509Data` in the dynamically created `Signature` template. """ # template aware infrastructure from dm.xmlsec.binding.tmpl import parse, Element, SubElement, \ fromstring, XML from dm.xmlsec.binding.tmpl import Signature doc = parse(xml_file) xmlsec.addIDs(doc.getroot(),['ID']) assertion = doc.findall('saml:Assertion', {"saml": "urn:oasis:names:tc:SAML:2.0:assertion"})[0] assertion_xml = sign_xml(tostring(assertion), assert_id, key_file, cert_file) assertion_doc = fromstring(assertion_xml) doc.getroot().remove(doc.findall("saml:Assertion", {"saml": "urn:oasis:names:tc:SAML:2.0:assertion"})[0]) doc.getroot().insert(0, assertion_doc) return sign_xml(tostring(doc), root_id, key_file, cert_file)
def get_response_xml(parameters, signed=False): """ Returns XML for response, with signatures, if signed is True. """ # Reset signatures. params = {} params.update(parameters) params["RESPONSE_SIGNATURE"] = "" _get_in_response_to(params) template = string.Template(RESPONSE) unsigned = template.substitute(params) logging.debug("Unsigned:") logging.debug(unsigned) if not signed: return unsigned # Sign it. # signature_xml = get_signature_xml(unsigned, params['RESPONSE_ID']) # params['RESPONSE_SIGNATURE'] = signature_xml # signed = template.substitute(params) # # logging.debug('Signed:') # logging.debug(signed) config = saml2idp_metadata.SAML2IDP_CONFIG private_key_file = config["private_key_file"] certificate_file = config["certificate_file"] doc = fromstring(unsigned) xmlsec.initialize() signature = Signature(xmlsec.TransformExclC14N, xmlsec.TransformRsaSha1) doc.insert(0, signature) ref = signature.addReference(xmlsec.TransformSha1) ref.addTransform(xmlsec.TransformEnveloped) key_info = signature.ensureKeyInfo() key_info.addKeyName() key_info.addX509Data() dsigCtx = xmlsec.DSigCtx() signKey = xmlsec.Key.load(private_key_file, xmlsec.KeyDataFormatPem, None) signKey.loadCert(certificate_file, xmlsec.KeyDataFormatPem) dsigCtx.signKey = signKey dsigCtx.sign(signature) return tostring(doc)
def sign_xml(xml, root_id, key_file, cert_file): """Sign the given XML.""" # template aware infrastructure from dm.xmlsec.binding.tmpl import parse, Element, SubElement, \ fromstring, XML from dm.xmlsec.binding.tmpl import Signature doc = fromstring(xml) #doc = parse(xml) signature = Signature(xmlsec.TransformExclC14N, xmlsec.TransformRsaSha1) doc.insert(0, signature) ref = signature.addReference(xmlsec.TransformSha1) ref.addTransform(xmlsec.TransformEnveloped) ref.addTransform(xmlsec.TransformExclC14N) key_info = signature.ensureKeyInfo() key_info.addKeyName() key_info.addX509Data() dsigCtx = xmlsec.DSigCtx() signKey = xmlsec.Key.load(key_file, xmlsec.KeyDataFormatPem, None) signKey.loadCert(cert_file, xmlsec.KeyDataFormatPem) dsigCtx.signKey = signKey dsigCtx.sign(signature) return tostring(doc)
def _encrypt_assertion(unencrypted): # load the rsa key # Create and initialize keys manager, we use a simple list based # keys manager, implement your own KeysStore klass if you need # something more sophisticated # mngr = xmlsec.KeysMngr() # config = saml2idp_metadata.SAML2IDP_CONFIG # key = xmlsec.cryptoAppKeyLoad(config['public_key_file'], xmlsec.KeyDataFormatPem, None, None, None) # key.setName(config['public_key_file']) # # add the key to the manager # xmlsec.cryptoAppDefaultKeysMngrAdoptKey(mngr, key) # # # now encrypt the xml # doc = libxml2.parseDoc(unencrypted) # # Create encryption template to encrypt XML file and replace # # its content with encryption result # enc_data_node = xmlsec.TmplEncData(doc, xmlsec.transformAes128CbcId(), None, xmlsec.TypeEncElement, None, None) # # put encrypted data in the <enc:CipherValue/> node # enc_data_node.ensureCipherValue() # # add <dsig:KeyInfo/> # key_info_node = enc_data_node.ensureKeyInfo(None) # # Add <enc:EncryptedKey/> to store the encrypted session key # enc_key_node = key_info_node.addEncryptedKey(xmlsec.transformRsaPkcs1Id(), None, None, None) # # put encrypted key in the <enc:CipherValue/> node # enc_key_node.ensureCipherValue() # # Add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to <enc:EncryptedKey/> # key_info_node2 = enc_key_node.ensureKeyInfo(None) # # Set key name so we can lookup key when needed # key_info_node2.addKeyName(config['public_key_file']) # # Create encryption context # enc_ctx = xmlsec.EncCtx(mngr) # # Generate a Triple DES key # key = xmlsec.keyGenerate(xmlsec.keyDataDesId(), 192, xmlsec.KeyDataTypeSession) # enc_ctx.encKey = key # # Encrypt the data # enc_ctx.xmlEncrypt(enc_data_node, doc.getRootElement()) # # # Destroy all # key.destroy() # mngr.destroy() # enc_ctx.destroy() # enc_data_node.freeNode() # # doc.freeDoc() # return doc xmlsec.initialize() config = saml2idp_metadata.SAML2IDP_CONFIG mngr = xmlsec.KeysMngr() key = xmlsec.Key.load(config["public_key_file"], xmlsec.KeyDataFormatPem) key.name = basename(config["public_key_file"]) mngr.addKey(key) doc = fromstring(unencrypted) encData = EncData(xmlsec.TransformDes3Cbc, type=xmlsec.TypeEncElement) encData.ensureCipherValue() # target for encryption result keyInfo = encData.ensureKeyInfo() encKey = keyInfo.addEncryptedKey(xmlsec.TransformRsaPkcs1) encKey.ensureCipherValue() encKeyInfo = encKey.ensureKeyInfo() encKeyInfo.addKeyName(key.name) encCtx = xmlsec.EncCtx(mngr) encCtx.encKey = xmlsec.Key.generate(xmlsec.KeyDataDes, 192, xmlsec.KeyDataTypeSession) ed = encCtx.encryptXml(encData, doc) return tostring(ed.getroottree())