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 assina_xml(self, xml): self._checar_certificado() self._inicializar_cripto() try: doc_xml = libxml2.parseMemory(xml.encode('utf-8'), len(xml.encode('utf-8'))) signNode = xmlsec.TmplSignature(doc_xml, xmlsec.transformInclC14NId(), xmlsec.transformRsaSha1Id(), None) doc_xml.getRootElement().addChild(signNode) refNode = signNode.addReference( xmlsec.transformSha1Id(), None, '#NFe43150602261542000143550010000000761792265342', None) refNode.addTransform(xmlsec.transformEnvelopedId()) refNode.addTransform(xmlsec.transformInclC14NId()) keyInfoNode = signNode.ensureKeyInfo() keyInfoNode.addX509Data() dsig_ctx = xmlsec.DSigCtx() chave = xmlsec.cryptoAppKeyLoad(filename=str(self.arquivo), format=xmlsec.KeyDataFormatPkcs12, pwd=str(self.senha), pwdCallback=None, pwdCallbackCtx=None) dsig_ctx.signKey = chave dsig_ctx.sign(signNode) status = dsig_ctx.status dsig_ctx.destroy() if status != xmlsec.DSigStatusSucceeded: raise RuntimeError( 'Erro ao realizar a assinatura do arquivo; status: "' + str(status) + '"') xpath = doc_xml.xpathNewContext() xpath.xpathRegisterNs('sig', NAMESPACE_SIG) certificados = xpath.xpathEval( '//sig:X509Data/sig:X509Certificate') for i in range(len(certificados) - 1): certificados[i].unlinkNode() certificados[i].freeNode() xml = doc_xml.serialize() return xml finally: doc_xml.freeDoc() self._finalizar_cripto()
def sign_file(xml_file, key_file): assert (xml_file) assert (key_file) # Load template doc = libxml2.parseFile(xml_file) if doc is None or doc.getRootElement() is None: print "Error: unable to parse file \"%s\"" % xml_file return cleanup(doc) # Create signature template for RSA-SHA1 enveloped signature signNode = xmlsec.TmplSignature(doc, xmlsec.transformExclC14NId(), xmlsec.transformRsaSha1Id(), None) if signNode is None: print "Error: failed to create signature template" return cleanup(doc) # Add <dsig:Signature/> node to the doc doc.getRootElement().addChild(signNode) # Add reference refNode = signNode.addReference(xmlsec.transformSha1Id(), None, None, None) if refNode is None: print "Error: failed to add reference to signature template" return cleanup(doc) # Add enveloped transform if refNode.addTransform(xmlsec.transformEnvelopedId()) is None: print "Error: failed to add enveloped transform to reference" return cleanup(doc) # Add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to put key name # in the signed document keyInfoNode = signNode.ensureKeyInfo(None) if keyInfoNode is None: print "Error: failed to add key info" return cleanup(doc) keyNameInfo = keyInfoNode.addKeyName(None) if keyNameInfo is None: print "Error: failed to add key name" return cleanup(doc) # Create signature context, we don't need keys manager in this example dsig_ctx = xmlsec.DSigCtx() if dsig_ctx is None: print "Error: failed to create signature context" return cleanup(doc) # Load private key, assuming that there is not password key = xmlsec.cryptoAppKeyLoad(key_file, xmlsec.KeyDataFormatPem, None, None, None) if key is None: print "Error: failed to load private pem key from \"%s\"" % key_file return cleanup(doc, dsig_ctx) dsig_ctx.signKey = key # Set key name to the file name, this is just an example! if key.setName(key_file) < 0: print "Error: failed to set key name for key from \"%s\"" % key_file return cleanup(doc, dsig_ctx) # Sign the template if dsig_ctx.sign(signNode) < 0: print "Error: signature failed" return cleanup(doc, dsig_ctx) # Print signed document to stdout doc.dump("-") # Success return cleanup(doc, dsig_ctx, 1)
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)
def template_sign(self, body, canonicalization, signing, references, key_name=None, key_x509=False): """Signs a XML file and creates a template based on the information provided. This information generally can be found in the documentation. body -- The XML body string. canonicalization -- The c14n method, e.g. enc-c14n signing -- The signing method, e.g. rsa-sha256 references -- A dict containing mappings of reference methods to an iterable of transforms, e.g. {'sha256': ('enveloped-signature', )} key_name -- The key name, or None if not required key_x509 -- Boolean indicating whether X509 data is required. """ # Translate c14n and signing arguments canonicalization = XMLDSIG._determine_transform_format( canonicalization) signing = XMLDSIG._determine_transform_format(signing) doc = dsig_ctx = None try: # Reparse using libxml2 doc = libxml2.parseDoc(body) if doc is None or doc.getRootElement() is None: raise XMLDSIGError("Failed feeding xml to libxml2") # Create signature template sign_node = xmlsec.TmplSignature(doc, canonicalization, signing, None) if sign_node is None: raise XMLDSIGError('Failed creating a signature template.') doc.getRootElement().addChild(sign_node) # Create references for (reference, transforms) in references.items(): ref = XMLDSIG._determine_transform_format(reference) ref_node = sign_node.addReference(ref, None, None, None) if ref_node is None: raise XMLDSIGError( 'Failed adding reference %s to template.' % reference) # add transforms for transform in transforms: trans = XMLDSIG._determine_transform_format(transform) if ref_node.addTransform(trans) is None: raise XMLDSIGError( 'Failed adding transform %s to template.' % transform) # Add keyinfo if key_name or key_x509: keyinfo_node = sign_node.ensureKeyInfo(None) if keyinfo_node is None: raise XMLDSIGError('Failed adding key info to template.') if key_name: if keyinfo_node.addKeyName(key_name) is None: raise XMLDSIGError( 'Failed adding key name to template.') if key_x509: if keyinfo_node.addX509Data() is None: raise XMLDSIGError( 'Failed adding X509 data to template.') # create a signing context dsig_ctx = self._create_dsig_ctx() # Sign if dsig_ctx.sign(sign_node) < 0: raise XMLDSIGError('Failed signing the xml.') return doc.serialize('UTF-8', 0) # 0 = not pretty except XMLDSIGError: raise except Exception as e: raise XMLDSIGError('Something went wrong signing the xml: %s' % e) finally: # Clear some space, it is a C API after all if dsig_ctx is not None: dsig_ctx.destroy() if doc is not None: doc.freeDoc()