Documentation.
This commit is contained in:
@@ -646,6 +646,10 @@ class CryptoBackend():
|
||||
|
||||
|
||||
class CryptoBackendXmlSec1(CryptoBackend):
|
||||
"""
|
||||
CryptoBackend implementation using external binary xmlsec1 to sign
|
||||
and verify XML documents.
|
||||
"""
|
||||
|
||||
__DEBUG = 0
|
||||
|
||||
@@ -680,6 +684,17 @@ class CryptoBackendXmlSec1(CryptoBackend):
|
||||
|
||||
def sign_statement(self, statement, class_name, key_file, node_id,
|
||||
id_attr):
|
||||
"""
|
||||
Sign an XML statement.
|
||||
|
||||
:param statement: The statement to be signed
|
||||
:param class_name: string like 'urn:oasis:names:...:Assertion'
|
||||
:param key_file: The file where the key can be found
|
||||
:param node_id:
|
||||
:param id_attr: The attribute name for the identifier, normally one of
|
||||
'id','Id' or 'ID'
|
||||
:return: The signed statement
|
||||
"""
|
||||
|
||||
_, fil = make_temp("%s" % statement, decode=False)
|
||||
|
||||
@@ -705,9 +720,20 @@ class CryptoBackendXmlSec1(CryptoBackend):
|
||||
except DecryptError:
|
||||
raise Exception("Signing failed")
|
||||
|
||||
def validate_signature(self, enctext, cert_file, cert_type, node_name,
|
||||
def validate_signature(self, signedtext, cert_file, cert_type, node_name,
|
||||
node_id, id_attr):
|
||||
_, fil = make_temp(enctext, decode=False)
|
||||
"""
|
||||
Validate signature on XML document.
|
||||
|
||||
:param signedtext: The XML document as a string
|
||||
:param cert_file: The public key that was used to sign the document
|
||||
:param cert_type: The file type of the certificate
|
||||
:param node_name: The name of the class that is signed
|
||||
:param node_id: The identifier of the node
|
||||
:param id_attr: Should normally be one of "id", "Id" or "ID"
|
||||
:return: Boolean True if the signature was correct otherwise False.
|
||||
"""
|
||||
_, fil = make_temp(signedtext, decode=False)
|
||||
|
||||
com_list = [self.xmlsec, "--verify",
|
||||
"--pubkey-cert-%s" % cert_type, cert_file,
|
||||
@@ -767,25 +793,63 @@ class CryptoBackendXmlSec1(CryptoBackend):
|
||||
return p_out, p_err, ntf.read()
|
||||
|
||||
class CryptoBackendXMLSecurity(CryptoBackend):
|
||||
"""
|
||||
CryptoBackend implementation using pyXMLSecurity to sign and verify
|
||||
XML documents.
|
||||
|
||||
Encrypt and decrypt is currently unsupported by pyXMLSecurity.
|
||||
|
||||
pyXMLSecurity uses lxml (libxml2) to parse XML data, but otherwise
|
||||
try to get by with native Python code. It does native Python RSA
|
||||
signatures, or alternatively PyKCS11 to offload cryptographic work
|
||||
to an external PKCS#11 module.
|
||||
"""
|
||||
|
||||
def __init__(self, debug=False):
|
||||
CryptoBackend.__init__(self)
|
||||
self.debug = debug
|
||||
|
||||
def sign_statement(self, statement, _class_name, key_file, _nodeid,
|
||||
_id_attr):
|
||||
"""
|
||||
Sign an XML statement.
|
||||
|
||||
The parameters actually used in this CryptoBackend
|
||||
implementation are :
|
||||
|
||||
:param statement: XML as string
|
||||
:param key_file: xmlsec key_spec string(), filename,
|
||||
"pkcs11://" URI or PEM data
|
||||
:returns: Signed XML as string
|
||||
"""
|
||||
import xmlsec
|
||||
import lxml.etree
|
||||
xml = xmlsec.parse_xml(statement)
|
||||
signed = xmlsec.sign(xml, key_file)
|
||||
return lxml.etree.tostring(signed, xml_declaration=True)
|
||||
|
||||
def validate_signature(self, enctext, cert_file, cert_type, _node_name,
|
||||
def validate_signature(self, signedtext, cert_file, cert_type, _node_name,
|
||||
_node_id, _id_attr):
|
||||
"""
|
||||
Validate signature on XML document.
|
||||
|
||||
The parameters actually used in this CryptoBackend
|
||||
implementation are :
|
||||
|
||||
:param signedtext: The signed XML data as string
|
||||
:param cert_file: xmlsec key_spec string(), filename,
|
||||
"pkcs11://" URI or PEM data
|
||||
:param cert_type: string, must be 'pem' for now
|
||||
:returns: True on successful validation, False otherwise
|
||||
"""
|
||||
if cert_type != "pem":
|
||||
raise Unsupported("Only PEM certs supported here")
|
||||
import xmlsec
|
||||
xml = xmlsec.parse_xml(enctext)
|
||||
return xmlsec.verify(xml, cert_file)
|
||||
xml = xmlsec.parse_xml(signedtext)
|
||||
try:
|
||||
return xmlsec.verify(xml, cert_file)
|
||||
except xmlsec.XMLSigException:
|
||||
return False
|
||||
|
||||
def security_context(conf, debug=None):
|
||||
""" Creates a security context based on the configuration
|
||||
@@ -843,7 +907,7 @@ class SecurityContext(object):
|
||||
else:
|
||||
self.template = template
|
||||
|
||||
self.key_type = encrypt_key_type
|
||||
self.encrypt_key_type = encrypt_key_type
|
||||
|
||||
def correctly_signed(self, xml, must=False):
|
||||
logger.info("verify correct signature")
|
||||
@@ -862,7 +926,7 @@ class SecurityContext(object):
|
||||
:result: An encrypted XML text
|
||||
"""
|
||||
if not key_type:
|
||||
key_type = self.key_type
|
||||
key_type = self.encrypt_key_type
|
||||
if not template:
|
||||
template = self.template
|
||||
|
||||
@@ -876,11 +940,11 @@ class SecurityContext(object):
|
||||
"""
|
||||
return self.crypto.decrypt(enctext, self.key_file)
|
||||
|
||||
def verify_signature(self, enctext, cert_file=None, cert_type="pem",
|
||||
def verify_signature(self, signedtext, cert_file=None, cert_type="pem",
|
||||
node_name=NODE_NAME, node_id=None, id_attr=""):
|
||||
""" Verifies the signature of a XML document.
|
||||
|
||||
:param enctext: The XML document as a string
|
||||
:param signedtext: The XML document as a string
|
||||
:param cert_file: The public key that was used to sign the document
|
||||
:param cert_type: The file type of the certificate
|
||||
:param node_name: The name of the class that is signed
|
||||
@@ -894,7 +958,7 @@ class SecurityContext(object):
|
||||
cert_file = self.cert_file
|
||||
cert_type = self.cert_type
|
||||
|
||||
return verify_signature(enctext, self.crypto, cert_file, cert_type,
|
||||
return verify_signature(signedtext, self.crypto, cert_file, cert_type,
|
||||
node_name, self.debug, node_id, id_attr)
|
||||
|
||||
def _check_signature(self, decoded_xml, item, node_name=NODE_NAME,
|
||||
@@ -971,9 +1035,9 @@ class SecurityContext(object):
|
||||
the entity that sent the info use that, if not use the key that are in
|
||||
the message if any.
|
||||
|
||||
:param decoded_xml:
|
||||
:param decoded_xml: The SAML message as a XML string
|
||||
:param msgtype:
|
||||
:param must:
|
||||
:param must: Whether there must be a signature
|
||||
:param origdoc:
|
||||
:return:
|
||||
"""
|
||||
@@ -1087,6 +1151,7 @@ class SecurityContext(object):
|
||||
|
||||
:param decoded_xml: The SAML message as a XML string
|
||||
:param must: Whether there must be a signature
|
||||
:param origdoc:
|
||||
:return: None if the signature can not be verified otherwise an instance
|
||||
"""
|
||||
|
||||
@@ -1130,8 +1195,10 @@ class SecurityContext(object):
|
||||
"""Sign a SAML statement.
|
||||
|
||||
:param statement: The statement to be signed
|
||||
:param class_name: string like 'urn:oasis:names:...:Assertion'
|
||||
:param key: The key to be used for the signing, either this or
|
||||
:param key_file: The file where the key can be found
|
||||
:param node_id:
|
||||
:param id_attr: The attribute name for the identifier, normally one of
|
||||
'id','Id' or 'ID'
|
||||
:return: The signed statement
|
||||
@@ -1218,6 +1285,7 @@ def pre_signature_part(ident, public_key=None, identifier=None):
|
||||
:param ident: The identifier of the assertion, so you know which assertion
|
||||
was signed
|
||||
:param public_key: The base64 part of a PEM file
|
||||
:param identifier:
|
||||
:return: A preset signature part
|
||||
"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user