def sign_xmlstring(self, xmlstring): """ Sign xmlstring using the signature template in xmlstring. The certificate from cert_file is placed in the <dsig:X509Data/> node. - xmlstring: str, XML data containing an XML-DSig template. Returns a string containing the signed XML data. Raises an exception if an error occurs. """ # try block to ensure cleanup is called even if an exception is raised: try: # Create signature context self._create_context() # Load template doc = self._parse_xmlstring(xmlstring) # find the XML-DSig start node node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) if node is None: raise RuntimeError, "Error: XML-DSIG node not found" # Sign the template if self.dsig_ctx.sign(node) < 0: raise RuntimeError, "Error: signature failed" output = str(doc) finally: # cleanup, even if an exception has been raised: self._cleanup_context() if doc is not None: doc.freeDoc() # return output if no exception was raised: return output
def received(self, context): self.poruka_odgovor = context.reply libxml2.initParser() libxml2.substituteEntitiesDefault(1) xmlsec.init() xmlsec.cryptoAppInit(None) xmlsec.cryptoInit() mngr = xmlsec.KeysMngr() xmlsec.cryptoAppDefaultKeysMngrInit(mngr) mngr.certLoad(verifyCertFile, xmlsec.KeyDataFormatPem, xmlsec.KeyDataTypeTrusted) doc = libxml2.parseDoc(context.reply) xmlsec.addIDs(doc, doc.getRootElement(), ['Id']) node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) dsig_ctx = xmlsec.DSigCtx(mngr) dsig_ctx.verify(node) if (dsig_ctx.status == xmlsec.DSigStatusSucceeded): self.valid_signature = 1 xmlsec.cryptoShutdown() xmlsec.cryptoAppShutdown() xmlsec.shutdown() libxml2.cleanupParser() return context
def received(self, context): self.poruka_odgovor = context.reply libxml2.initParser() libxml2.substituteEntitiesDefault(1) xmlsec.init() xmlsec.cryptoAppInit(None) xmlsec.cryptoInit() mngr = xmlsec.KeysMngr() xmlsec.cryptoAppDefaultKeysMngrInit(mngr) #mngr.certLoad(verifyCertFile, xmlsec.KeyDataFormatPem, xmlsec.KeyDataTypeTrusted) mngr.certLoad(certFile, xmlsec.KeyDataFormatPem, xmlsec.KeyDataTypeTrusted) doc = libxml2.parseDoc(context.reply) xmlsec.addIDs(doc, doc.getRootElement(), ['Id']) node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) dsig_ctx = xmlsec.DSigCtx(mngr) dsig_ctx.verify(node) if(dsig_ctx.status == xmlsec.DSigStatusSucceeded): self.valid_signature = 1 xmlsec.cryptoShutdown() xmlsec.cryptoAppShutdown() xmlsec.shutdown() libxml2.cleanupParser() return context
def _signXML(xml): dsigctx = None doc = None try: # initialization libxml2.initParser() libxml2.substituteEntitiesDefault(1) if xmlsec.init() < 0: raise SignatureError('xmlsec init failed') if xmlsec.checkVersion() != 1: raise SignatureError('incompatible xmlsec library version %s' % str(xmlsec.checkVersion())) if xmlsec.cryptoAppInit(None) < 0: raise SignatureError('crypto initialization failed') if xmlsec.cryptoInit() < 0: raise SignatureError('xmlsec-crypto initialization failed') # load the input doc = libxml2.parseDoc(xml) if not doc or not doc.getRootElement(): raise SignatureError('error parsing input xml') node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) if not node: raise SignatureError("couldn't find root node") dsigctx = xmlsec.DSigCtx() key = xmlsec.cryptoAppKeyLoad(key_file, xmlsec.KeyDataFormatPem, key_pwd, None, None) if not key: raise SignatureError('failed to load the private key %s' % key_file) dsigctx.signKey = key if key.setName(key_file) < 0: raise SignatureError('failed to set key name') if xmlsec.cryptoAppKeyCertLoad(key, cert_file, xmlsec.KeyDataFormatPem) < 0: print "Error: failed to load pem certificate \"%s\"" % cert_file return cleanup(doc, dsigctx) # sign if dsigctx.sign(node) < 0: raise SignatureError('signing failed') signed_xml = doc.serialize() finally: if dsigctx: dsigctx.destroy() if doc: doc.freeDoc() xmlsec.cryptoShutdown() xmlsec.shutdown() libxml2.cleanupParser() return signed_xml
def sign_xml(xml, key_file, cert_file=None): # Load template doc = libxml2.parseDoc(xml) if doc is None or doc.getRootElement() is None: cleanup(doc) raise saml2.Error("Error: unable to parse string \"%s\"" % xml) node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) if node is None: cleanup(doc) raise saml2.Error("Error: start node not found.") # Create signature context, we don't need keys manager in this example dsig_ctx = xmlsec.DSigCtx() if dsig_ctx is None: cleanup(doc) raise saml2.Error("Error: failed to create signature context") # Load private key, assuming that there is not password key = xmlsec.cryptoAppKeyLoad(key_file, xmlsec.KeyDataFormatPem, None, None, None) if key is None: cleanup(doc, dsig_ctx) raise saml2.Error( "Error: failed to load private pem key from \"%s\"" % key_file) dsig_ctx.signKey = key if cert_file is not None: if xmlsec.cryptoAppKeyCertLoad( dsig_ctx.signKey, cert_file, xmlsec.KeyDataFormatPem) < 0: cleanup(doc, dsig_ctx) raise saml2.Error( "Error: failed to load cert pem from \"%s\"" % cert_file) else: pass # Set key name to the file name, this is just an example! if key.setName(key_file) < 0: cleanup(doc, dsig_ctx) raise saml2.Error( "Error: failed to set key name for key from \"%s\"" % key_file) return cleanup(doc, dsig_ctx) # Sign the template if dsig_ctx.sign(node) < 0: cleanup(doc, dsig_ctx) raise saml2.Error("Error: signature failed") # signed document to string ret = doc.__str__() # Success cleanup(doc, dsig_ctx, 1) return ret
def get_signature(self, envelope): with LibXML2ParsedDocument(envelope) as doc: root = doc.getRootElement() xmlsec.addIDs(doc, root, ["Id"]) signNode = xmlsec.findNode(root, xmlsec.NodeSignature, xmlsec.DSigNs) with XmlSecSignatureContext(self) as dsig_ctx: if dsig_ctx.sign(signNode) < 0: raise RuntimeError("signature failed") return doc.serialize()
def get_signature(self, envelope): with LibXML2ParsedDocument(envelope) as doc: root = doc.getRootElement() xmlsec.addIDs(doc, root, ['Id']) signNode = xmlsec.findNode(root, xmlsec.NodeSignature, xmlsec.DSigNs) with XmlSecSignatureContext(self) as dsig_ctx: if dsig_ctx.sign(signNode) < 0: raise RuntimeError('signature failed') return doc.serialize()
def verify_file(self, xml_file, key_file): assert(xml_file) assert(key_file) # Load XML file 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\"" % tmpl_file) return self.cleanup(doc) # Find start node node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) # 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) # Load private key, assuming that there is not password key = xmlsec.cryptoAppKeyLoad(key_file, xmlsec.KeyDataFormatPem, None, None, None) if key is None: log.error("Failed to load private pem key from \"%s\"" % key_file) return self.cleanup(doc, dsig_ctx) dsig_ctx.signKey = key # Set key name to the file name, this is just an example! if not self.check_filename(key_file): return self.cleanup(doc, dsig_ctx) if key.setName(key_file) < 0: log.error("Failed to set key name for key from \"%s\"" % key_file) return self.cleanup(doc, dsig_ctx) # Verify signature if dsig_ctx.verify(node) < 0: log.error("Signature verify failed") return self.cleanup(doc, dsig_ctx) # Print verification result to stdout if dsig_ctx.status == xmlsec.DSigStatusSucceeded: log.debug("Signature is OK") else: log.error("Signature is INVALID") # Success return self.cleanup(doc, dsig_ctx, 1)
def decrypt_file(enc_file, key_file): assert(enc_file) assert(key_file) # Load template doc = libxml2.parseFile(enc_file) if doc is None or doc.getRootElement() is None: print "Error: unable to parse file \"%s\"" % enc_file return cleanup(doc) # Find start node node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeEncryptedData, xmlsec.EncNs) if node is None: print "Error: start node not found in \"%s\"" % tmpl_file return cleanup(doc) # Create encryption context, we don't need keys manager in this example enc_ctx = xmlsec.EncCtx(None) if enc_ctx is None: print "Error: failed to create encryption context" return cleanup(doc) # Load DES key key = xmlsec.keyReadBinaryFile(xmlsec.keyDataDesId(), key_file) if key is None: print "Error failed to load DES key from binary file \"%s\"" % key_file return cleanup(doc, enc_ctx) # 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, enc_ctx) enc_ctx.encKey = key # Decrypt the data if enc_ctx.decrypt(node) < 0 or enc_ctx.result is None: print "Error: decryption failed" return cleanup(doc, enc_ctx) # Print decrypted data to stdout if enc_ctx.resultReplaced != 0: print "Decrypted XML data:" doc.dump("-") else: print "Decrypted binary data (%d bytes):" % enc_ctx.result.getSize() print enc_ctx.result.getData() # Success return cleanup(doc, enc_ctx, 1)
def decrypt_file(enc_file, key_file): assert (enc_file) assert (key_file) # Load template doc = libxml2.parseFile(enc_file) if doc is None or doc.getRootElement() is None: print "Error: unable to parse file \"%s\"" % enc_file return cleanup(doc) # Find start node node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeEncryptedData, xmlsec.EncNs) if node is None: print "Error: start node not found in \"%s\"" % tmpl_file return cleanup(doc) # Create encryption context, we don't need keys manager in this example enc_ctx = xmlsec.EncCtx(None) if enc_ctx is None: print "Error: failed to create encryption context" return cleanup(doc) # Load DES key key = xmlsec.keyReadBinaryFile(xmlsec.keyDataDesId(), key_file) if key is None: print "Error failed to load DES key from binary file \"%s\"" % key_file return cleanup(doc, enc_ctx) # 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, enc_ctx) enc_ctx.encKey = key # Decrypt the data if enc_ctx.decrypt(node) < 0 or enc_ctx.result is None: print "Error: decryption failed" return cleanup(doc, enc_ctx) # Print decrypted data to stdout if enc_ctx.resultReplaced != 0: print "Decrypted XML data:" doc.dump("-") else: print "Decrypted binary data (%d bytes):" % enc_ctx.result.getSize() print enc_ctx.result.getData() # Success return cleanup(doc, enc_ctx, 1)
def verify_xml(xml, key_file): doc = libxml2.parseDoc(xml) if doc is None or doc.getRootElement() is None: cleanup(doc) raise saml2.Error("Error: unable to parse file \"%s\"" % tmpl_file) # Find start node node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) # Create signature context, we don't need keys manager in this example dsig_ctx = xmlsec.DSigCtx() if dsig_ctx is None: cleanup(doc) raise saml2.Error("Error: failed to create signature context") # Load public key, assuming that there is not password if key_file.endswith(".der"): key = xmlsec.cryptoAppKeyLoad(key_file, xmlsec.KeyDataFormatDer, None, None, None) else: key = xmlsec.cryptoAppKeyLoad(key_file, xmlsec.KeyDataFormatPem, None, None, None) if key is None: cleanup(doc, dsig_ctx) raise saml2.Error("Error: failed to load public key from \"%s\"" % key_file) dsig_ctx.signKey = key # Set key name to the file name, this is just an example! if key.setName(key_file) < 0: cleanup(doc, dsig_ctx) raise saml2.Error("Error: failed to set key name for key from \"%s\"" % key_file) # Verify signature if dsig_ctx.verify(node) < 0: cleanup(doc, dsig_ctx) raise saml2.Error("Error: signature verify") # Print verification result to stdout if dsig_ctx.status == xmlsec.DSigStatusSucceeded: ret = 0 else: ret = -1 # Success cleanup(doc, dsig_ctx) return ret
def _parse_dsig_xml(body): """Parse the given XML body into a libxml2 object, and retrieve the DSigNs node. Returns the libxml2 doc and node. """ # Reparse using libxml2 doc = libxml2.parseDoc(body) if doc is None or doc.getRootElement() is None: raise XMLDSIGError("Failed feeding xml to libxml2") # find the Signature node node = xmlsec.findNode(doc, xmlsec.NodeSignature, xmlsec.DSigNs) if node is None: raise XMLDSIGError("Failed finding signature root node.") return doc, node
def _parse_enc_xml(body): """Parse the given XML body into a libxml2 object, and retrieve the EncNs node. Returns the libxml2 doc and node. """ # Reparse using libxml2 doc = libxml2.parseDoc(body) if doc is None or doc.getRootElement() is None: raise XMLDSIGError("Failed feeding xml to libxml2") # find the Signature node node = xmlsec.findNode(doc, xmlsec.NodeEncryptedData, xmlsec.EncNs) if node is None: raise XMLDSIGError("Failed finding encryption root node.") return doc, node
def _parse_enc_xml(body): """Parse the given XML body into a libxml2 object, and retrieve the EncNs node. Returns the libxml2 doc and node. """ # Reparse using libxml2 doc = libxml2.parseDoc(body) if doc is None or doc.getRootElement() is None: raise DSigError("Failed feeding xml to libxml2") # find the Signature node node = xmlsec.findNode(doc, xmlsec.NodeEncryptedData, xmlsec.EncNs) if node is None: raise DSigError("Failed finding encryption root node.") return doc, node
def sign_file(tmpl_file, key_file): assert(tmpl_file) assert(key_file) # Load template doc = libxml2.parseFile(tmpl_file) if doc is None or doc.getRootElement() is None: print "Error: unable to parse file \"%s\"" % tmpl_file return -1 # Find start node node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) if node is None: print "Error: start node not found in \"%s\"" % tmpl_file 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(node) < 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 encrypt_file(tmpl_file, key_file, data, dataSize): assert(tmpl_file) assert(key_file) assert(data) # Load template doc = libxml2.parseFile(tmpl_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.NodeEncryptedData, xmlsec.EncNs) if node is None: print "Error: start node not found in \"%s\"" % tmpl_file return cleanup(doc) # Create encryption context, we don't need keys manager in this example enc_ctx = xmlsec.EncCtx(None) if enc_ctx is None: print "Error: failed to create encryption context" return cleanup(doc) # Load DES key, assuming that there is not password key = xmlsec.keyReadBinaryFile(xmlsec.keyDataDesId(), key_file) if key is None: print "Error failed to load DES key from binary file \"%s\"" % key_file return cleanup(doc, enc_ctx) # 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, enc_ctx) enc_ctx.encKey = key # Encrypt the data if enc_ctx.binaryEncrypt(node, data, dataSize) < 0: print "Error: encryption failed" return cleanup(doc, enc_ctx) doc.dump("-") # Success return cleanup(doc, enc_ctx, 1)
def sign_file(tmpl_file, key_file): assert (tmpl_file) assert (key_file) # Load template doc = libxml2.parseFile(tmpl_file) if doc is None or doc.getRootElement() is None: print "Error: unable to parse file \"%s\"" % tmpl_file return -1 # Find start node node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) if node is None: print "Error: start node not found in \"%s\"" % tmpl_file 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(node) < 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 decrypt_file(mngr, enc_file): assert(mngr) assert(enc_file) # Load template if not check_filename(enc_file): return -1 doc = libxml2.parseFile(enc_file) if doc is None or doc.getRootElement() is None: print "Error: unable to parse file \"%s\"" % enc_file return cleanup(doc) # Find start node node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeEncryptedData, xmlsec.EncNs) if node is None: print "Error: start node not found in \"%s\"" % tmpl_file return cleanup(doc) # Create encryption context enc_ctx = xmlsec.EncCtx(mngr) if enc_ctx is None: print "Error: failed to create encryption context" return cleanup(doc) # Decrypt the data if enc_ctx.decrypt(node) < 0 or enc_ctx.result is None: print "Error: decryption failed" return cleanup(doc, enc_ctx) # Print decrypted data to stdout if enc_ctx.resultReplaced != 0: print "Decrypted XML data:" doc.dump("-") else: print "Decrypted binary data (%d bytes):" % enc_ctx.result.getSize() print enc_ctx.result.getData() # Success return cleanup(doc, enc_ctx, 1)
def decrypt_file(mngr, enc_file): assert (mngr) assert (enc_file) # Load template if not check_filename(enc_file): return -1 doc = libxml2.parseFile(enc_file) if doc is None or doc.getRootElement() is None: print "Error: unable to parse file \"%s\"" % enc_file return cleanup(doc) # Find start node node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeEncryptedData, xmlsec.EncNs) if node is None: print "Error: start node not found in \"%s\"" % tmpl_file return cleanup(doc) # Create encryption context enc_ctx = xmlsec.EncCtx(mngr) if enc_ctx is None: print "Error: failed to create encryption context" return cleanup(doc) # Decrypt the data if enc_ctx.decrypt(node) < 0 or enc_ctx.result is None: print "Error: decryption failed" return cleanup(doc, enc_ctx) # Print decrypted data to stdout if enc_ctx.resultReplaced != 0: print "Decrypted XML data:" doc.dump("-") else: print "Decrypted binary data (%d bytes):" % enc_ctx.result.getSize() print enc_ctx.result.getData() # Success return cleanup(doc, enc_ctx, 1)
def verify_xmlstring(self, xmlstring): """ Verify signature in xmlstring using the loaded certificate. - xmlstring: str, XML data containing an XML-DSig signature. Returns True if the signature is valid, False otherwise. Raises an exception if an error occurs. """ doc = None # try block to ensure cleanup is called even if an exception is raised: try: # Create signature context self._create_context() # Load XML data doc = self._parse_xmlstring(xmlstring) # find the XML-DSig start node node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) if node is None: raise RuntimeError, "Error: XML-DSIG node not found" # Verify signature if self.dsig_ctx.verify(node) < 0: # An error occured, the signature could not be verified raise RuntimeError, "Error: An error occured, the signature could not be verified" if self.dsig_ctx.status == xmlsec.DSigStatusSucceeded: # Signature is OK return True else: # Signature is INVALID return False finally: # cleanup, even if an exception has been raised: self._cleanup_context() if doc is not None: doc.freeDoc() # return output if no exception was raised: return output
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) # Verify signature if dsig_ctx.verify(node) < 0: print "Error: signature verify" 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 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) # Verify signature if dsig_ctx.verify(node) < 0: print "Error: signature verify" 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 _verifyXML(self, xml): import libxml2 import xmlsec dsigctx = None doc = None try: # initialization libxml2.initParser() libxml2.substituteEntitiesDefault(1) if xmlsec.init() < 0: raise SignatureError('xmlsec init failed') if xmlsec.checkVersion() != 1: raise SignatureError('incompatible xmlsec library version %s' % str(xmlsec.checkVersion())) if xmlsec.cryptoAppInit(None) < 0: raise SignatureError('crypto initialization failed') if xmlsec.cryptoInit() < 0: raise SignatureError('xmlsec-crypto initialization failed') # load the input doc = libxml2.parseDoc(xml) if not doc or not doc.getRootElement(): raise SignatureError('error parsing input xml') node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) if not node: raise SignatureError("couldn't find root node") dsigctx = xmlsec.DSigCtx() key = xmlsec.cryptoAppKeyLoad(self.key_file, xmlsec.KeyDataFormatPem, self.key_pwd, None, None) if not key: raise SignatureError('failed to load the private key %s' % self.key_file) dsigctx.signKey = key if key.setName(self.key_file) < 0: raise SignatureError('failed to set key name') if xmlsec.cryptoAppKeyCertLoad(key, self.cert_file, xmlsec.KeyDataFormatPem) < 0: print "Error: failed to load pem certificate \"%s\"" % self.cert_file return self.cleanup(doc, dsigctx) # verify if dsigctx.verify(node) < 0: raise SignatureError('verification failed') if dsigctx.status == xmlsec.DSigStatusSucceeded: self.log("Signature is OK") is_valid = True else: self.log("***************** Signature is INVALID ********************") is_valid = False finally: if dsigctx: dsigctx.destroy() if doc: doc.freeDoc() xmlsec.cryptoShutdown() xmlsec.shutdown() libxml2.cleanupParser() return is_valid
def _signXML(self, xml): import libxml2 import xmlsec dsigctx = None doc = None try: # initialization libxml2.initParser() libxml2.substituteEntitiesDefault(1) if xmlsec.init() < 0: raise SignatureError('xmlsec init failed') if xmlsec.checkVersion() != 1: raise SignatureError('incompatible xmlsec library version %s' % str(xmlsec.checkVersion())) if xmlsec.cryptoAppInit(None) < 0: raise SignatureError('crypto initialization failed') if xmlsec.cryptoInit() < 0: raise SignatureError('xmlsec-crypto initialization failed') # load the input doc = libxml2.parseDoc(xml) if not doc or not doc.getRootElement(): raise SignatureError('error parsing input xml') node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) if not node: raise SignatureError("couldn't find root node") # load the private key key = xmlsec.cryptoAppKeyLoad(self.key_file, xmlsec.KeyDataFormatPem, self.key_pwd, None, None) if not key: raise SignatureError('failed to load the private key %s' % self.key_file) if xmlsec.cryptoAppKeyCertLoad(key, self.cert_file, xmlsec.KeyDataFormatPem) < 0: print "Error: failed to load pem certificate \"%s\"" % self.cert_file return self.cleanup(doc, dsigctx) keymngr = xmlsec.KeysMngr() xmlsec.cryptoAppDefaultKeysMngrInit(keymngr) xmlsec.cryptoAppDefaultKeysMngrAdoptKey(keymngr, key) dsigctx = xmlsec.DSigCtx(keymngr) if key.setName(self.key_file) < 0: raise SignatureError('failed to set key name') # sign if dsigctx.sign(node) < 0: raise SignatureError('signing failed') signed_xml = doc.serialize() finally: if dsigctx: dsigctx.destroy() if doc: doc.freeDoc() xmlsec.cryptoShutdown() xmlsec.shutdown() libxml2.cleanupParser() return signed_xml
def assina_xml(self, xml): self._inicia_funcoes_externas() xml = self._prepara_doc_xml(xml) # # Colocamos o texto no avaliador XML # doc_xml = libxml2.parseMemory(xml.encode("utf-8"), len(xml.encode("utf-8"))) # # Separa o nó da assinatura # noh_assinatura = xmlsec.findNode(doc_xml.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) # # Arquivos temporários são criados com o certificado no formato PEM # temp_chave = tempfile.NamedTemporaryFile("w") temp_chave.write(self.chave) temp_chave.flush() temp_certificado = tempfile.NamedTemporaryFile("w") temp_certificado.write(self.certificado) temp_certificado.flush() # # Buscamos chave e certificado no arquivo temporário e inserimos no "chaveiro" # chaveiro = xmlsec.KeysMngr() xmlsec.cryptoAppDefaultKeysMngrInit(chaveiro) chave = xmlsec.cryptoAppKeyLoad( filename=temp_chave.name, format=xmlsec.KeyDataFormatPem, pwd=None, pwdCallback=None, pwdCallbackCtx=None ) certificado = xmlsec.cryptoAppKeyCertLoad(chave, filename=temp_certificado.name, format=xmlsec.KeyDataFormatPem) xmlsec.cryptoAppDefaultKeysMngrAdoptKey(chaveiro, chave) # # Cria a variável de chamada (callable) da função de assinatura, usando o "chaveiro" # assinador = xmlsec.DSigCtx(chaveiro) # # Atribui a chave ao assinador # assinador.signKey = chave # # Realiza a assinatura # assinador.sign(noh_assinatura) # # Guarda o status # status = assinador.status # # Libera a memória ocupada pelo assinador manualmente # assinador.destroy() # # Arquivos temporários são deletados do disco # temp_chave.close() temp_certificado.close() if status != xmlsec.DSigStatusSucceeded: # # Libera a memória ocupada pelo documento xml manualmente # doc_xml.freeDoc() self._finaliza_funcoes_externas() raise RuntimeError('Erro ao realizar a assinatura do arquivo; status: "' + str(status) + '"') # # Elimina do xml assinado a cadeia certificadora, deixando somente # o certificado que assinou o documento # xpath = doc_xml.xpathNewContext() xpath.xpathRegisterNs(u"sig", NAMESPACE_SIG) certificados = xpath.xpathEval(u"//sig:X509Data/sig:X509Certificate") for i in range(len(certificados) - 1): certificados[i].unlinkNode() certificados[i].freeNode() # # Retransforma o documento xml em texto # xml = doc_xml.serialize() # # Libera a memória ocupada pelo documento xml manualmente # doc_xml.freeDoc() self._finaliza_funcoes_externas() xml = self._finaliza_xml(xml) return xml
def verifica_assinatura_xml(self, xml): self._inicia_funcoes_externas() xml = self._prepara_doc_xml(xml) # # Colocamos o texto no avaliador XML # doc_xml = libxml2.parseMemory(xml.encode('utf-8'), len(xml.encode('utf-8'))) # # Separa o nó da assinatura # noh_assinatura = xmlsec.findNode(doc_xml.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) # # Prepara o gerenciador dos certificados confiáveis para verificação # certificados_confiaveis = xmlsec.KeysMngr() xmlsec.cryptoAppDefaultKeysMngrInit(certificados_confiaveis) # # Prepara a cadeia certificadora # certificados = os.listdir(DIRNAME + '/cadeia-certificadora/certificados') certificados.sort() for certificado in certificados: certificados_confiaveis.certLoad(filename=str(DIRNAME + '/cadeia-certificadora/certificados/' + certificado), format=xmlsec.KeyDataFormatPem, type=xmlsec.KeyDataTypeTrusted) # # Cria a variável de chamada (callable) da função de assinatura/verificação, # agora passando quais autoridades certificadoras são consideradas # confiáveis # verificador = xmlsec.DSigCtx(certificados_confiaveis) # # Separa o certificado que assinou o arquivo, e prepara a instância # com os dados desse certificado # certificado = xmlsec.findNode(noh_assinatura, xmlsec.NodeX509Certificate, xmlsec.DSigNs).content self.prepara_certificado_txt(certificado) # # Recupera a chave do certificado que assinou o documento, e altera # a data que será usada para fazer a verificação, para que a assinatura # seja validada mesmo que o certificado já tenha expirado # Para isso, define a data de validação para a data de início da validade # do certificado # Essa data deve ser informada como um inteiro tipo "unixtime" # noh_chave = xmlsec.findNode(noh_assinatura, xmlsec.NodeKeyInfo, xmlsec.DSigNs) manipulador_chave = xmlsec.KeyInfoCtx(mngr=certificados_confiaveis) manipulador_chave.certsVerificationTime = mktime(self.data_inicio_validade.timetuple()) # # Cria uma chave vazia e recupera a chave, dizendo ao verificador que # é essa a chave que deve ser usada na validação da assinatura # verificador.signKey = xmlsec.Key() xmlsec.keyInfoNodeRead(noh_chave, verificador.signKey, manipulador_chave) # # Realiza a verificação # verificador.verify(noh_assinatura) # # Guarda o status # status = verificador.status resultado = status == xmlsec.DSigStatusSucceeded # # Libera a memória ocupada pelo verificador manualmente # verificador.destroy() certificados_confiaveis.destroy() if status != xmlsec.DSigStatusSucceeded: # # Libera a memória ocupada pelo documento xml manualmente # doc_xml.freeDoc() self._finaliza_funcoes_externas() raise RuntimeError('Erro ao validar a assinatura do arquivo; status: "' + str(status) + '"') # # Libera a memória ocupada pelo documento xml manualmente # doc_xml.freeDoc() self._finaliza_funcoes_externas() return resultado
def assina_xml(self, xml): self._inicia_funcoes_externas() xml = self._prepara_doc_xml(xml) # # Colocamos o texto no avaliador XML # doc_xml = libxml2.parseMemory(xml.encode('utf-8'), len(xml.encode('utf-8'))) # # Separa o nó da assinatura # noh_assinatura = xmlsec.findNode(doc_xml.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) # # Cria a variável de chamada (callable) da função de assinatura # assinador = xmlsec.DSigCtx() # # Buscamos a chave no arquivo do certificado # chave = xmlsec.cryptoAppKeyLoad(filename=str(self.arquivo), format=xmlsec.KeyDataFormatPkcs12, pwd=str(self.senha), pwdCallback=None, pwdCallbackCtx=None) # # Atribui a chave ao assinador # assinador.signKey = chave # # Realiza a assinatura # assinador.sign(noh_assinatura) # # Guarda o status # status = assinador.status # # Libera a memória ocupada pelo assinador manualmente # assinador.destroy() if status != xmlsec.DSigStatusSucceeded: # # Libera a memória ocupada pelo documento xml manualmente # doc_xml.freeDoc() self._finaliza_funcoes_externas() raise RuntimeError('Erro ao realizar a assinatura do arquivo; status: "' + str(status) + '"') # # Elimina do xml assinado a cadeia certificadora, deixando somente # o certificado que assinou o documento # 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() # # Retransforma o documento xml em texto # xml = doc_xml.serialize() # # Libera a memória ocupada pelo documento xml manualmente # doc_xml.freeDoc() self._finaliza_funcoes_externas() xml = self._finaliza_xml(xml) return xml
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 assina_xml(self, xml): self._inicia_funcoes_externas() xml = self._prepara_doc_xml(xml) # # Colocamos o texto no avaliador XML # doc_xml = libxml2.parseMemory(xml.encode('utf-8'), len(xml.encode('utf-8'))) # # Separa o nó da assinatura # noh_assinatura = xmlsec.findNode(doc_xml.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) # # Arquivos temporários são criados com o certificado no formato PEM # temp_chave = tempfile.NamedTemporaryFile('w') temp_chave.write(self.chave) temp_chave.flush() temp_certificado = tempfile.NamedTemporaryFile('w') temp_certificado.write(self.certificado) temp_certificado.flush() # # Buscamos chave e certificado no arquivo temporário e inserimos no "chaveiro" # chaveiro = xmlsec.KeysMngr() xmlsec.cryptoAppDefaultKeysMngrInit(chaveiro) chave = xmlsec.cryptoAppKeyLoad(filename=temp_chave.name, format=xmlsec.KeyDataFormatPem, pwd=None, pwdCallback=None, pwdCallbackCtx=None) certificado = xmlsec.cryptoAppKeyCertLoad( chave, filename=temp_certificado.name, format=xmlsec.KeyDataFormatPem) xmlsec.cryptoAppDefaultKeysMngrAdoptKey(chaveiro, chave) # # Cria a variável de chamada (callable) da função de assinatura, usando o "chaveiro" # assinador = xmlsec.DSigCtx(chaveiro) # # Atribui a chave ao assinador # assinador.signKey = chave # # Realiza a assinatura # assinador.sign(noh_assinatura) # # Guarda o status # status = assinador.status # # Libera a memória ocupada pelo assinador manualmente # assinador.destroy() # # Arquivos temporários são deletados do disco # temp_chave.close() temp_certificado.close() if status != xmlsec.DSigStatusSucceeded: # # Libera a memória ocupada pelo documento xml manualmente # doc_xml.freeDoc() self._finaliza_funcoes_externas() raise RuntimeError( 'Erro ao realizar a assinatura do arquivo; status: "' + str(status) + '"') # # Elimina do xml assinado a cadeia certificadora, deixando somente # o certificado que assinou o documento # xpath = doc_xml.xpathNewContext() xpath.xpathRegisterNs(u'sig', NAMESPACE_SIG) certificados = xpath.xpathEval(u'//sig:X509Data/sig:X509Certificate') for i in range(len(certificados) - 1): certificados[i].unlinkNode() certificados[i].freeNode() # # Retransforma o documento xml em texto # xml = doc_xml.serialize() # # Libera a memória ocupada pelo documento xml manualmente # doc_xml.freeDoc() self._finaliza_funcoes_externas() xml = self._finaliza_xml(xml) return xml
def signRequest(file, request, dtd="http://dmswww.stsci.edu/dtd/sso/distribution.dtd", cgi="https://archive.stsci.edu/cgi-bin/dads.cgi", mission='HST'): global usexml if usexml: try: keysmngr = xmlsec.KeysMngr() if keysmngr is None: raise RuntimeError("Error: failed to create keys manager.") if xmlsec.cryptoAppDefaultKeysMngrInit(keysmngr) < 0: keysmngr.destroy() raise RuntimeError("Error: failed to initialize keys manager.") key = xmlsec.cryptoAppKeyLoad(filename = file, pwd = None, format = xmlsec.KeyDataFormatPem, pwdCallback = None, pwdCallbackCtx = None) if xmlsec.cryptoAppDefaultKeysMngrAdoptKey(keysmngr, key) < 0: keysmngr.destroy() raise RuntimeError("Error: failed to load key into keys manager") dsig_ctx = xmlsec.DSigCtx(keysmngr) # Match the dtd and replace it. pat = re.compile("(^.*<!DOCTYPE.*distributionRequest[^>]*SYSTEM[ \t]*\")([^\"]*)(\"[^>]*>.*$)", re.DOTALL) m = pat.match(request) request = m.group(1)+dtd+m.group(3) ctxt = libxml2.createMemoryParserCtxt(request, len(request)) ctxt.validate(1) ctxt.parseDocument() doc = ctxt.doc() if doc is None or doc.getRootElement() is None: keysmngr.destroy() raise RuntimeError("Error: unable to parse XML data") # find the XML-DSig start node node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) if node is None: fragment = libxml2.parseDoc("""<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> <SignedInfo> <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> <Reference URI="#distributionRequest"> <Transforms> <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#WithComments" /> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <DigestValue></DigestValue> </Reference> </SignedInfo> <SignatureValue></SignatureValue> <KeyInfo> <KeyValue><RSAKeyValue> <Modulus></Modulus> <Exponent></Exponent> </RSAKeyValue></KeyValue> </KeyInfo> </Signature> """) # remove the xml header on the front of the document fragment fragment = fragment.getRootElement() # getElementsByTagName doesn't exist here for some reason, have to use xpath ctxt = doc.xpathNewContext() nodeList = ctxt.xpathEval("/distributionRequest") for child in nodeList: child.addChild(fragment) if child.prop('Id') == None: child.setProp('Id', 'distributionRequest') node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) # Remove passwords ctxt = doc.xpathNewContext() nodeList = ctxt.xpathEval('//requester') for child in nodeList: child.unsetProp('archivePassword') nodeList = ctxt.xpathEval('//ftp') for child in nodeList: if child.hasProp('loginPassword'): child.unsetProp('loginPassword') warnings.warn('ftp password is not allowed in user requests.') # Sign the template, or resign existing block status = dsig_ctx.sign(node) output = str(doc) doc.freeDoc() keysmngr.destroy() if status < 0: raise RuntimeError("Error: signature failed") return output except: usexml=False return signRequest(file, request, dtd, cgi) else: values = {'request' : request, 'privatekey' : open(file).read(), 'mission' : mission } data = urlencode(values).encode("utf-8") req = Request(url=cgi, data=data) f = urlopen(req) return f.read()
def signRequest(file, request): keysmngr = xmlsec.KeysMngr() if keysmngr is None: raise RuntimeError, "Error: failed to create keys manager." if xmlsec.cryptoAppDefaultKeysMngrInit(keysmngr) < 0: keysmngr.destroy() raise RuntimeError, "Error: failed to initialize keys manager." key = xmlsec.cryptoAppKeyLoad(filename = file, pwd = None, format = xmlsec.KeyDataFormatPem, pwdCallback = None, pwdCallbackCtx = None) if xmlsec.cryptoAppDefaultKeysMngrAdoptKey(keysmngr, key) < 0: keysmngr.destroy() raise RuntimeError, "Error: failed to load key into keys manager" dsig_ctx = xmlsec.DSigCtx(keysmngr) # Match the dtd and replace it. pat = re.compile("(^.*<!DOCTYPE.*distributionRequest[^>]*SYSTEM[ \t]*\")([^\"]*)(\"[^>]*>.*$)", re.DOTALL) m = pat.match(request) request = m.group(1)+"http://dmswww.stsci.edu/dtd/sso/distribution.dtd"+m.group(3) ctxt = libxml2.createMemoryParserCtxt(request, len(request)) ctxt.validate(1) ctxt.parseDocument() doc = ctxt.doc() if doc is None or doc.getRootElement() is None: keysmngr.destroy() raise RuntimeError, "Error: unable to parse XML data" # find the XML-DSig start node node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) if node is None: fragment = libxml2.parseDoc("""<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> <SignedInfo> <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> <Reference URI="#distributionRequest"> <Transforms> <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#WithComments" /> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <DigestValue></DigestValue> </Reference> </SignedInfo> <SignatureValue></SignatureValue> <KeyInfo> <KeyValue><RSAKeyValue> <Modulus></Modulus> <Exponent></Exponent> </RSAKeyValue></KeyValue> </KeyInfo> </Signature> """) # remove the xml header on the front of the document fragment fragment = fragment.getRootElement() # getElementsByTagName doesn't exist here for some reason, have to use xpath ctxt = doc.xpathNewContext() nodeList = ctxt.xpathEval("/distributionRequest") for child in nodeList: child.addChild(fragment) if child.prop('Id') == None: child.setProp('Id', 'distributionRequest') node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, xmlsec.DSigNs) # Remove passwords ctxt = doc.xpathNewContext() nodeList = ctxt.xpathEval('//requester') for child in nodeList: child.unsetProp('archivePassword') nodeList = ctxt.xpathEval('//ftp') for child in nodeList: if child.hasProp('loginPassword'): child.unsetProp('loginPassword') warnings.warn('ftp password is not allowed in user requests.') # Sign the template, or resign existing block status = dsig_ctx.sign(node) output = str(doc) doc.freeDoc() keysmngr.destroy() if status < 0: raise RuntimeError, "Error: signature failed" return output
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)