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 assina_xml(self, xml, reference): self._checar_certificado() self._inicializar_cripto() try: doc_xml = libxml2.parseMemory( xml, len(xml)) signNode = xmlsec.TmplSignature(doc_xml, xmlsec.transformInclC14NId(), xmlsec.transformRsaSha1Id(), None) doc_xml.getRootElement().addChild(signNode) refNode = signNode.addReference(xmlsec.transformSha1Id(), None, reference, 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()
def verify_file(mngr, xml_file): assert(mngr) assert(xml_file) # Load XML file if not check_filename(xml_file): return -1 doc = libxml2.parseFile(xml_file) if doc is None or doc.getRootElement() is None: print "Error: unable to parse file \"%s\"" % tmpl_file return cleanup(doc) # Find start node node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) if node is None: print "Error: start node not found in \"%s\"", xml_file # Create signature context dsig_ctx = xmlsec.DSigCtx(mngr) if dsig_ctx is None: print "Error: failed to create signature context" return cleanup(doc) # Limit the Reference URI attributes to empty or None dsig_ctx.enabledReferenceUris = xmlsec.TransformUriTypeEmpty # Limit allowed transforms for signature and reference processing if (dsig_ctx.enableSignatureTransform(xmlsec.transformInclC14NId()) < 0 or dsig_ctx.enableSignatureTransform(xmlsec.transformExclC14NId()) < 0 or dsig_ctx.enableSignatureTransform(xmlsec.transformSha1Id()) < 0 or dsig_ctx.enableSignatureTransform(xmlsec.transformRsaSha1Id()) < 0): print "Error: failed to limit allowed signature transforms" return cleanup(doc, dsig_ctx) if (dsig_ctx.enableReferenceTransform(xmlsec.transformInclC14NId()) < 0 or dsig_ctx.enableReferenceTransform(xmlsec.transformExclC14NId()) < 0 or dsig_ctx.enableReferenceTransform(xmlsec.transformSha1Id()) < 0 or dsig_ctx.enableReferenceTransform(xmlsec.transformEnvelopedId())< 0): print "Error: failed to limit allowed reference transforms" return cleanup(doc, dsig_ctx) # In addition, limit possible key data to valid X509 certificates only if dsig_ctx.keyInfoReadCtx.enabledKeyData.add(xmlsec.keyDataX509Id()) < 0: print "Error: failed to limit allowed key data" return cleanup(doc, dsig_ctx) # Verify signature if dsig_ctx.verify(node) < 0: print "Error: signature verify" return cleanup(doc, dsig_ctx) # Check that we have only one Reference if (dsig_ctx.status == xmlsec.DSigStatusSucceeded and dsig_ctx.signedInfoReferences.getSize() != 1): print "Error: only one reference is allowed" return cleanup(doc, dsig_ctx) # Print verification result to stdout if dsig_ctx.status == xmlsec.DSigStatusSucceeded: print "Signature is OK" else: print "Signature is INVALID" # 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 verify_file(mngr, xml_file): assert (mngr) assert (xml_file) # Load XML file if not check_filename(xml_file): return -1 doc = libxml2.parseFile(xml_file) if doc is None or doc.getRootElement() is None: print "Error: unable to parse file \"%s\"" % tmpl_file return cleanup(doc) # Find start node node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) if node is None: print "Error: start node not found in \"%s\"", xml_file # Create signature context dsig_ctx = xmlsec.DSigCtx(mngr) if dsig_ctx is None: print "Error: failed to create signature context" return cleanup(doc) # Limit the Reference URI attributes to empty or None dsig_ctx.enabledReferenceUris = xmlsec.TransformUriTypeEmpty # Limit allowed transforms for signature and reference processing if (dsig_ctx.enableSignatureTransform(xmlsec.transformInclC14NId()) < 0 or dsig_ctx.enableSignatureTransform(xmlsec.transformExclC14NId()) < 0 or dsig_ctx.enableSignatureTransform(xmlsec.transformSha1Id()) < 0 or dsig_ctx.enableSignatureTransform( xmlsec.transformRsaSha1Id()) < 0): print "Error: failed to limit allowed signature transforms" return cleanup(doc, dsig_ctx) if (dsig_ctx.enableReferenceTransform(xmlsec.transformInclC14NId()) < 0 or dsig_ctx.enableReferenceTransform(xmlsec.transformExclC14NId()) < 0 or dsig_ctx.enableReferenceTransform(xmlsec.transformSha1Id()) < 0 or dsig_ctx.enableReferenceTransform( xmlsec.transformEnvelopedId()) < 0): print "Error: failed to limit allowed reference transforms" return cleanup(doc, dsig_ctx) # In addition, limit possible key data to valid X509 certificates only if dsig_ctx.keyInfoReadCtx.enabledKeyData.add(xmlsec.keyDataX509Id()) < 0: print "Error: failed to limit allowed key data" return cleanup(doc, dsig_ctx) # Verify signature if dsig_ctx.verify(node) < 0: print "Error: signature verify" return cleanup(doc, dsig_ctx) # Check that we have only one Reference if (dsig_ctx.status == xmlsec.DSigStatusSucceeded and dsig_ctx.signedInfoReferences.getSize() != 1): print "Error: only one reference is allowed" return cleanup(doc, dsig_ctx) # Print verification result to stdout if dsig_ctx.status == xmlsec.DSigStatusSucceeded: print "Signature is OK" else: print "Signature is INVALID" # Success return cleanup(doc, dsig_ctx, 1)
def _determine_transform_format(formatstring): """Translates strings to all transform methods of the pyXMLsec library. This should actually sort out which value could be used where, but for now, it works :-). """ if formatstring == 'aes128-cbc': result = xmlsec.transformAes128CbcId() elif formatstring == 'aes192-cbc': result = xmlsec.transformAes192CbcId() elif formatstring == 'aes256-cbc': result = xmlsec.transformAes256CbcId() elif formatstring == 'kw-aes128': result = xmlsec.transformKWAes128Id() elif formatstring == 'kw-aes192': result = xmlsec.transformKWAes192Id() elif formatstring == 'kw-aes256': result = xmlsec.transformKWAes256Id() elif formatstring == 'des3-cbc': result = xmlsec.transformDes3CbcId() elif formatstring == 'kw-des3': result = xmlsec.transformKWDes3Id() elif formatstring == 'dsa-sha1': result = xmlsec.transformDsaSha1Id() elif formatstring == 'hmac-md5': result = xmlsec.transformHmacMd5Id() elif formatstring == 'hmac-ripemd160': result = xmlsec.transformHmacRipemd160Id() elif formatstring == 'hmac-sha1': result = xmlsec.transformHmacSha1Id() elif formatstring == 'hmac-sha224': result = xmlsec.transformHmacSha224Id() elif formatstring == 'hmac-sha256': result = xmlsec.transformHmacSha256Id() elif formatstring == 'hmac-sha384': result = xmlsec.transformHmacSha384Id() elif formatstring == 'hmac-sha512': result = xmlsec.transformHmacSha512Id() elif formatstring == 'hmac-md5': result = xmlsec.transformMd5Id() elif formatstring == 'ripemd160': result = xmlsec.transformRipemd160Id() elif formatstring == 'rsa-md5': result = xmlsec.transformRsaMd5Id() elif formatstring == 'rsa-ripemd160': result = xmlsec.transformRsaRipemd160Id() elif formatstring == 'rsa-sha1': result = xmlsec.transformRsaSha1Id() elif formatstring == 'rsa-sha224': result = xmlsec.transformRsaSha224Id() elif formatstring == 'rsa-sha256': result = xmlsec.transformRsaSha256Id() elif formatstring == 'rsa-sha384': result = xmlsec.transformRsaSha384Id() elif formatstring == 'rsa-sha512': result = xmlsec.transformRsaSha512Id() elif formatstring == 'rsa-pkcs1': result = xmlsec.transformRsaPkcs1Id() elif formatstring == 'rsa-oaep': result = xmlsec.transformRsaOaepId() elif formatstring == 'sha1': result = xmlsec.transformSha1Id() elif formatstring == 'sha224': result = xmlsec.transformSha224Id() elif formatstring == 'sha256': result = xmlsec.transformSha256Id() elif formatstring == 'sha384': result = xmlsec.transformSha384Id() elif formatstring == 'sha512': result = xmlsec.transformSha512Id() elif formatstring == 'base64': result = xmlsec.transformBase64Id() elif formatstring == 'inc-c14n': result = xmlsec.transformInclC14NId() elif formatstring == 'inc-c14n-with-comments': result = xmlsec.transformInclC14NWithCommentsId() elif formatstring == 'exc-c14n': result = xmlsec.transformExclC14NId() elif formatstring == 'exc-c14n-with-comments': result = xmlsec.transformExclC14NWithCommentsId() elif formatstring in ('enveloped', 'enveloped-signature'): result = xmlsec.transformEnvelopedId() elif formatstring in ('xpath', 'xpath-19991116', 'xmldsig-filter'): result = xmlsec.transformXPathId() elif formatstring in ('xpath2', 'xmldsig-filter2'): result = xmlsec.transformXPath2Id() elif formatstring == 'xpointer': result = xmlsec.transformXPointerId() elif formatstring in ('xslt', 'xslt-19991116'): result = xmlsec.transformXsltId() elif formatstring == 'remove-xml-tags-transform': result = xmlsec.transformRemoveXmlTagsC14NId() elif formatstring == 'visa3d-hack': result = xmlsec.transformVisa3DHackId() else: raise DSigError('Unknown transform: %s' % formatstring) if result is None: raise DSigError('Transform %s not available' % formatstring) else: return result
def _determine_transform_format(formatstring): """Translates strings to all transform methods of the pyXMLsec library. This should actually sort out which value could be used where, but for now, it works :-). """ if formatstring == 'aes128-cbc': result = xmlsec.transformAes128CbcId() elif formatstring == 'aes192-cbc': result = xmlsec.transformAes192CbcId() elif formatstring == 'aes256-cbc': result = xmlsec.transformAes256CbcId() elif formatstring == 'kw-aes128': result = xmlsec.transformKWAes128Id() elif formatstring == 'kw-aes192': result = xmlsec.transformKWAes192Id() elif formatstring == 'kw-aes256': result = xmlsec.transformKWAes256Id() elif formatstring == 'des3-cbc': result = xmlsec.transformDes3CbcId() elif formatstring == 'kw-des3': result = xmlsec.transformKWDes3Id() elif formatstring == 'dsa-sha1': result = xmlsec.transformDsaSha1Id() elif formatstring == 'hmac-md5': result = xmlsec.transformHmacMd5Id() elif formatstring == 'hmac-ripemd160': result = xmlsec.transformHmacRipemd160Id() elif formatstring == 'hmac-sha1': result = xmlsec.transformHmacSha1Id() elif formatstring == 'hmac-sha224': result = xmlsec.transformHmacSha224Id() elif formatstring == 'hmac-sha256': result = xmlsec.transformHmacSha256Id() elif formatstring == 'hmac-sha384': result = xmlsec.transformHmacSha384Id() elif formatstring == 'hmac-sha512': result = xmlsec.transformHmacSha512Id() elif formatstring == 'hmac-md5': result = xmlsec.transformMd5Id() elif formatstring == 'ripemd160': result = xmlsec.transformRipemd160Id() elif formatstring == 'rsa-md5': result = xmlsec.transformRsaMd5Id() elif formatstring == 'rsa-ripemd160': result = xmlsec.transformRsaRipemd160Id() elif formatstring == 'rsa-sha1': result = xmlsec.transformRsaSha1Id() elif formatstring == 'rsa-sha224': result = xmlsec.transformRsaSha224Id() elif formatstring == 'rsa-sha256': result = xmlsec.transformRsaSha256Id() elif formatstring == 'rsa-sha384': result = xmlsec.transformRsaSha384Id() elif formatstring == 'rsa-sha512': result = xmlsec.transformRsaSha512Id() elif formatstring == 'rsa-pkcs1': result = xmlsec.transformRsaPkcs1Id() elif formatstring == 'rsa-oaep': result = xmlsec.transformRsaOaepId() elif formatstring == 'sha1': result = xmlsec.transformSha1Id() elif formatstring == 'sha224': result = xmlsec.transformSha224Id() elif formatstring == 'sha256': result = xmlsec.transformSha256Id() elif formatstring == 'sha384': result = xmlsec.transformSha384Id() elif formatstring == 'sha512': result = xmlsec.transformSha512Id() elif formatstring == 'base64': result = xmlsec.transformBase64Id() elif formatstring == 'inc-c14n': result = xmlsec.transformInclC14NId() elif formatstring == 'inc-c14n-with-comments': result = xmlsec.transformInclC14NWithCommentsId() elif formatstring == 'exc-c14n': result = xmlsec.transformExclC14NId() elif formatstring == 'exc-c14n-with-comments': result = xmlsec.transformExclC14NWithCommentsId() elif formatstring in ('enveloped', 'enveloped-signature'): result = xmlsec.transformEnvelopedId() elif formatstring in ('xpath', 'xpath-19991116', 'xmldsig-filter'): result = xmlsec.transformXPathId() elif formatstring in ('xpath2', 'xmldsig-filter2'): result = xmlsec.transformXPath2Id() elif formatstring == 'xpointer': result = xmlsec.transformXPointerId() elif formatstring in ('xslt', 'xslt-19991116'): result = xmlsec.transformXsltId() elif formatstring == 'remove-xml-tags-transform': result = xmlsec.transformRemoveXmlTagsC14NId() elif formatstring == 'visa3d-hack': result = xmlsec.transformVisa3DHackId() else: raise XMLDSIGError('Unknown transform: %s' % formatstring) if result is None: raise XMLDSIGError('Transform %s not available' % formatstring) else: return result