def sending(self, context): msgtype = "RacunZahtjev" if "PoslovniProstorZahtjev" in context.envelope: msgtype = "PoslovniProstorZahtjev" doc2 = libxml2.parseDoc(context.envelope) zahtjev = doc2.xpathEval('//*[local-name()="%s"]' % msgtype)[0] doc2.setRootElement(zahtjev) x = doc2.getRootElement().newNs('http://www.apis-it.hr/fin/2012/types/f73', 'tns') for i in doc2.xpathEval('//*'): i.setNs(x) libxml2.initParser() libxml2.substituteEntitiesDefault(1) xmlsec.init() xmlsec.cryptoAppInit(None) xmlsec.cryptoInit() doc2.getRootElement().setProp('Id', msgtype) xmlsec.addIDs(doc2, doc2.getRootElement(), ['Id']) signNode = xmlsec.TmplSignature(doc2, xmlsec.transformExclC14NId(), xmlsec.transformRsaSha1Id(), None) doc2.getRootElement().addChild(signNode) refNode = signNode.addReference(xmlsec.transformSha1Id(), None, None, None) refNode.setProp('URI', '#%s' % msgtype) refNode.addTransform(xmlsec.transformEnvelopedId()) refNode.addTransform(xmlsec.transformExclC14NId()) dsig_ctx = xmlsec.DSigCtx() key = xmlsec.cryptoAppKeyLoad(keyFile, xmlsec.KeyDataFormatPem, None, None, None) dsig_ctx.signKey = key xmlsec.cryptoAppKeyCertLoad(key, certFile, xmlsec.KeyDataFormatPem) key.setName(keyFile) keyInfoNode = signNode.ensureKeyInfo(None) x509DataNode = keyInfoNode.addX509Data() xmlsec.addChild(x509DataNode, "X509IssuerSerial") xmlsec.addChild(x509DataNode, "X509Certificate") dsig_ctx.sign(signNode) if dsig_ctx is not None: dsig_ctx.destroy() context.envelope = """<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Body>""" + doc2.serialize().replace('<?xml version="1.0" encoding="UTF-8"?>','') + """</soapenv:Body></soapenv:Envelope>""" # Ugly hack # Shutdown xmlsec-crypto library, ako ne radi HTTPS onda ovo treba zakomentirati da ga ne ugasi prije reda xmlsec.cryptoShutdown() xmlsec.shutdown() libxml2.cleanupParser() return context
def sign_file(self, xml_file, signed_xml_file, pkcs_file, password): assert(xml_file) assert(pkcs_file) assert(password) # Load template if not self.check_filename(xml_file): return -1 doc = libxml2.parseFile(xml_file) if doc is None or doc.getRootElement() is None: log.error(" unable to parse file \"%s\"" % xml_file) return self.cleanup(doc) log.debug("Signing file %s using %s " % (xml_file, pkcs_file)) if self._use_template: # If the template is already in the text ready to be filled signNode = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs); if signNode is None: log.error(" failed to find signature template") return self.cleanup(doc) else: # If the signature structure has to be constructed and added. # Create signature template for RSA-SHA256 enveloped signature signNode = xmlsec.TmplSignature(doc, xmlsec.transformInclC14NId(), xmlsec.transformRsaSha1Id(), None) # Add <dsig:Signature/> node to the doc doc.getRootElement().addChild(signNode) # Add reference refNode = signNode.addReference(xmlsec.transformSha1Id(), None, "", None) if refNode is None: log.error("Failed to add reference to signature template") return self.cleanup(doc) # Add enveloped transform if refNode.addTransform(xmlsec.transformEnvelopedId()) is None: log.error("Failed to add enveloped transform to reference") return self.cleanup(doc) # Add <dsig:KeyInfo/> and <dsig:X509Data/> keyInfoNode = signNode.ensureKeyInfo(None) if keyInfoNode is None: log.error("Failed to add key info") return self.cleanup(doc) x509DataNode = keyInfoNode.addX509Data() if x509DataNode is None: log.error("Failed to add X509Data node") return self.cleanup(doc) if xmlsec.addChild(x509DataNode, xmlsec.NodeX509SubjectName) is None: log.error("Failed to X509SubjectName to x509DataNode") return self.cleanup(doc) # Sample code from here. # http://ndg-security.ceda.ac.uk/browser/TI12-security/trunk/python/NDG/XMLSecDoc.py?rev=920 if xmlsec.addChild(x509DataNode, xmlsec.NodeX509Certificate) is None: log.error("Failed to X509certificate to x509DataNode") return self.cleanup(doc) # endif (if use_template..) # Create signature context, we don't need keys manager in this # example dsig_ctx = xmlsec.DSigCtx() if dsig_ctx is None: log.error("Failed to create signature context") return self.cleanup(doc) # Store the context.. self.dsig_ctx = dsig_ctx # Load private key, assuming that there is not password if not self.check_filename(pkcs_file): return self.cleanup(doc, dsig_ctx) #key = xmlsec.cryptoAppKeyLoad(key_file, xmlsec.KeyDataFormatPem, # None, None, None) key = xmlsec.cryptoAppPkcs12Load(pkcs_file, password, None, None) if key is None: log.error("Failed to load private pem key from \"%s\"" % pkcs_file) return self.cleanup(doc, dsig_ctx) dsig_ctx.signKey = key # Load certificate and add to the key # if not check_filename(cert_file): # return self.cleanup(doc, dsig_ctx) # if xmlsec.cryptoAppKeyCertLoad(key, cert_file, xmlsec.KeyDataFormatPem) < 0: # log.error(" failed to load pem certificate \"%s\"" % cert_file # return self.cleanup(doc, dsig_ctx) # Set key name to the file name, this is just an example! if key.setName(pkcs_file) < 0: log.error("Failed to set key name for key from \"%s\"" % pkcs_file) return self.cleanup(doc, dsig_ctx) # Sign the template if dsig_ctx.sign(signNode) < 0: log.error("Signature failed") return self.cleanup(doc, dsig_ctx) # Print signed document to stdout #doc.dump("-") #doc.formatDump("-", 0) import libxml2mod fp = file(signed_xml_file, "w") libxml2mod.xmlDocFormatDump(fp, doc._o, 0) fp.close() # Success return self.cleanup(doc, dsig_ctx, 1)