Last active
October 10, 2022 10:55
-
-
Save badri/0cec99762f60eb4cc4e894368382cab0 to your computer and use it in GitHub Desktop.
SAML3 working setup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import jwt | |
from datetime import datetime, timedelta | |
import ipaddress | |
import time | |
from cryptography.hazmat.primitives import serialization | |
from cryptography.x509 import load_pem_x509_certificate | |
# pip3 install signxml | |
from lxml import etree | |
from signxml import XMLSigner, XMLVerifier | |
def generate_selfsigned_cert(hostname, ip_addresses=None, key=None): | |
"""Generates self signed certificate for a hostname, and optional IP addresses.""" | |
from cryptography import x509 | |
from cryptography.x509.oid import NameOID | |
from cryptography.hazmat.primitives import hashes | |
from cryptography.hazmat.backends import default_backend | |
from cryptography.hazmat.primitives import serialization | |
from cryptography.hazmat.primitives.asymmetric import rsa | |
# Generate our key | |
if key is None: | |
key = rsa.generate_private_key( | |
public_exponent=65537, | |
key_size=768, | |
backend=default_backend(), | |
) | |
name = x509.Name([ | |
x509.NameAttribute(NameOID.COMMON_NAME, hostname) | |
]) | |
# best practice seem to be to include the hostname in the SAN, which *SHOULD* mean COMMON_NAME is ignored. | |
alt_names = [x509.DNSName(hostname)] | |
# allow addressing by IP, for when you don't have real DNS (common in most testing scenarios | |
if ip_addresses: | |
for addr in ip_addresses: | |
# openssl wants DNSnames for ips... | |
alt_names.append(x509.DNSName(addr)) | |
# ... whereas golang's crypto/tls is stricter, and needs IPAddresses | |
# note: older versions of cryptography do not understand ip_address objects | |
alt_names.append(x509.IPAddress(ipaddress.ip_address(addr))) | |
san = x509.SubjectAlternativeName(alt_names) | |
# path_len=0 means this cert can only sign itself, not other certs. | |
basic_contraints = x509.BasicConstraints(ca=True, path_length=0) | |
now = datetime.utcnow() | |
cert = ( | |
x509.CertificateBuilder() | |
.subject_name(name) | |
.issuer_name(name) | |
.public_key(key.public_key()) | |
.serial_number(1000) | |
.not_valid_before(now) | |
.not_valid_after(now + timedelta(days=10*365)) | |
.add_extension(basic_contraints, False) | |
.add_extension(san, False) | |
.sign(key, hashes.SHA256(), default_backend()) | |
) | |
cert_pem = cert.public_bytes(encoding=serialization.Encoding.PEM) | |
key_pem = key.private_bytes( | |
encoding=serialization.Encoding.PEM, | |
format=serialization.PrivateFormat.TraditionalOpenSSL, | |
encryption_algorithm=serialization.NoEncryption(), | |
) | |
return cert_pem, key_pem | |
# RS384, RS512 | |
def generate_token(private_key, expiry_hours, kid, typ="JWT", alg="RS256"): | |
future = datetime.now() + timedelta(hours=expiry_hours) | |
exp = int(time.mktime(future.timetuple())) | |
return jwt.encode({"some": "payload", "exp": exp}, private_key, algorithm=alg, headers={"kid": kid, "typ": typ, "alg": alg,},) | |
def get_public_key(cert_str): | |
cert_obj = load_pem_x509_certificate(cert_str) | |
public_key = cert_obj.public_key() | |
pem = public_key.public_bytes( | |
encoding=serialization.Encoding.PEM, | |
format=serialization.PublicFormat.SubjectPublicKeyInfo, | |
) | |
return pem.decode('utf-8') | |
""" | |
cert, private_key = generate_selfsigned_cert('example.com') | |
print(cert) | |
print(private_key) | |
token = generate_token(private_key, 1, "17GLrwRZj5LzsI7lNyxTJd0EGPeXYT6qbb7lcLsCTwQ", "JWS") | |
print(token) | |
public_key = get_public_key(cert) | |
print(public_key) | |
""" | |
data_to_sign = "<Test/>" | |
## get cert and key from gen-keys.py | |
def get_signed_saml(data_to_sign: str, key: str, cert: str): | |
root = etree.fromstring(data_to_sign) | |
signed_root = XMLSigner(c14n_algorithm="http://www.w3.org/2001/10/xml-exc-c14n#").sign(root, key=key, cert=cert) | |
return etree.tostring(signed_root, encoding='unicode') | |
# verified data is one without the signature | |
def get_verified_data(signed_xml: str, cert: str): | |
signed_root = etree.fromstring(signed_xml) | |
verified_data = XMLVerifier().verify(signed_root, x509_cert=cert).signed_xml | |
return etree.tostring(verified_data, encoding='unicode') | |
""" | |
<Test> | |
<ds:Signature | |
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> | |
<ds:SignedInfo> | |
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> | |
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> | |
<ds:Reference URI=""> | |
<ds:Transforms> | |
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> | |
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> | |
</ds:Transforms> | |
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> | |
<ds:DigestValue>KP3ncf09YSgkeTt+i4PR+W0AMvUTo7M8gu0z15piPMc=</ds:DigestValue> | |
</ds:Reference> | |
</ds:SignedInfo> | |
<ds:SignatureValue>C5lootquj8G4nJL2nQKm/G98mBXAjoZfCV7JsLOe42SMeci+ECGSvzJi1hQKBSocy4iT+2B2by6b5fycku6QejSTeJTq3FEu8ouIezK1g/nWL4540F31LQcRZ1rJMvGt6XjfuopuOoxmXmILWUS8LkjWKyhpDVoq9xWPeddRXg2C7VFanx5nADn+r9m2fpJ+McfCKYCqeoFk/pyUPs9jwS89P5wbkopJQzRkcg8/XTPckTZ/WsDNpP1rqNibTukxRzbtrSHSnvWFCpTNhqnJAia+10rjqPn5YtdS83YTD1R2Rp3LF1vu+gPudsc8QZ6rfkyV2JPT96jkweCLHZFPvQ==</ds:SignatureValue> | |
<ds:KeyInfo> | |
<ds:X509Data> | |
<ds:X509Certificate>MIICmjCCAYICCQCo5HSg9asgUDANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDAR0\nZXN0MB4XDTIyMTAwNjA1MTI0N1oXDTIyMTAwNzA1MTI0N1owDzENMAsGA1UEAwwE\ndGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKNPZGV4Z6lLMlAx\nwpgd/h7hkhnsPKNYd8tWJz4WL5+/JS1ga9Wk6qz4IxX7NHLsIa+ybzLUEZmsoHs3\n9glnchDf+rAgT0zB/tbL5KVeKr/dankm6DSN7A+UieE9IQHN2YY3sjVQiE9C6Owi\ns8rmJhP7uOouSXv/qHePURXpfnGoCZe6HWtSnk2H0IEWM0rgDngi92e2cgGctfXE\nQtoVLrxNb8rThEI47+HaACjE66OthwGsq24k9Fl4o5gUJaKhEKoH9G71UBLqpn/i\nsYI2CKKQO0OswRWRRPRdg97mtINCTUW6r4cUHnvXoRwPvz3Kb+SM+c3uUT5o+eFN\nKbDWZKECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAoBYJQdsUoYOC6iTIPjYFwu6i\nJj+UkX0H5PdaDrG+GiDSp5q18pvGHvlST6oCM3fouXQ7V+ufMaSzG/tsYNQitNfB\nLN9Py13jNj8EkraVKuolSmQfd9ct1u1n8wfDd9pwyAOBQYGeHjQtf12TE84/XBnV\nb1vYkKDnTLasa3i6aosk1i6JgObYamJ5F/Gu9UmVFlWcQWVIjMn7wQ2hu8xGrLtJ\nQC3bKcotM31uFk+2QIApUb3/4ouNY2ytHYkQB5VnVbl/bqpTiwUkrfWMEE5VJAiP\nzd8CPbd2mdbFmYs2ojPJCVTOXv4X4RGwViVxI5qNx1fWS89U6Q1EtQGZNc34WQ==\n</ds:X509Certificate> | |
</ds:X509Data> | |
</ds:KeyInfo> | |
</ds:Signature> | |
</Test> | |
""" | |
""" | |
<Test> | |
<ds:Signature | |
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> | |
<ds:SignedInfo> | |
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> | |
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> | |
<ds:Reference URI=""> | |
<ds:Transforms> | |
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> | |
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> | |
</ds:Transforms> | |
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> | |
<ds:DigestValue>KP3ncf09YSgkeTt+i4PR+W0AMvUTo7M8gu0z15piPMc=</ds:DigestValue> | |
</ds:Reference> | |
</ds:SignedInfo> | |
<ds:SignatureValue>n2eQW4CLddrL3sl7TZREO03psJ8gTV9cdWVvoRhM75Ypa7sKwRmckEw8Pz3CycaZI/or5XQcactY8Lnr2jNaN+ifbJVQQwRguI89VQGI5UsRX9K9ommYqChXSoA4LA0I</ds:SignatureValue> | |
<ds:KeyInfo> | |
<ds:X509Data> | |
<ds:X509Certificate>MIIBiTCCAROgAwIBAgICA+gwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAwwLZXhh\nbXBsZS5jb20wHhcNMjIxMDA2MTAwNTQ5WhcNMzIxMDAzMTAwNTQ5WjAWMRQwEgYD\nVQQDDAtleGFtcGxlLmNvbTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDs9GE3HOar\nEUsjWFATw/+h/73GxarU2/iHFuOTwGeZTCDI+Ay3TRfv+GZVUlSlPUHwuZYqP1++\nrGYcBtrvu78DgYtWsLsEPdcVa6HkeKM6UarN9Q2A5e7gn2zGYWxtpuMCAwEAAaMr\nMCkwDwYDVR0TBAgwBgEB/wIBADAWBgNVHREEDzANggtleGFtcGxlLmNvbTANBgkq\nhkiG9w0BAQsFAANhAERnjq9SMzRGIzOb5N3JAuv1w18GSceKjqNGscisyVkIEWTf\n5hUm2NaVrFA65o7STucxdxN5Y7ydBVvDY+7pA8TicqE36BKwXC3cUU5HGyQw+D1K\ndnff2J0hDORtyhLsxw==\n</ds:X509Certificate> | |
</ds:X509Data> | |
</ds:KeyInfo> | |
</ds:Signature> | |
</Test> | |
""" | |
""" | |
<Test> | |
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> | |
<ds:SignedInfo> | |
<ds:SignatureValue>C5lootquj8G4nJL2nQKm/G98mBXAjoZfCV7JsLOe42SMeci+ECGSvzJi1hQKBSocy4iT+2B2by6b5fycku6QejSTeJTq3FEu8ouIezK1g/nWL4540F31LQcRZ1rJMvGt6XjfuopuOoxmXmILWUS8LkjWKyhpDVoq9xWPeddRXg2C7VFanx5nADn+r9m2fpJ+McfCKYCqeoFk/pyUPs9jwS89P5wbkopJQzRkcg8/XTPckTZ/WsDNpP1rqNibTukxRzbtrSHSnvWFCpTNhqnJAia+10rjqPn5YtdS83YTD1R2Rp3LF1vu+gPudsc8QZ6rfkyV2JPT96jkweCLHZFPvQ==</ds:SignatureValue> | |
</ds:SignedInfo> | |
</ds:Signature> | |
</Test> | |
""" | |
""" | |
public_key = '-----BEGIN PUBLIC KEY-----\nMHwwDQYJKoZIhvcNAQEBBQADawAwaAJhAOz0YTcc5qsRSyNYUBPD/6H/vcbFqtTb\n+IcW45PAZ5lMIMj4DLdNF+/4ZlVSVKU9QfC5lio/X76sZhwG2u+7vwOBi1awuwQ9\n1xVroeR4ozpRqs31DYDl7uCfbMZhbG2m4wIDAQAB\n-----END PUBLIC KEY-----\n' | |
private_key = '-----BEGIN RSA PRIVATE KEY-----\nMIIBzAIBAAJhAOz0YTcc5qsRSyNYUBPD/6H/vcbFqtTb+IcW45PAZ5lMIMj4DLdN\nF+/4ZlVSVKU9QfC5lio/X76sZhwG2u+7vwOBi1awuwQ91xVroeR4ozpRqs31DYDl\n7uCfbMZhbG2m4wIDAQABAmEA4IyuW+Ydilu3EuWr7S8+X6zVkTrdKx7SJGLCg9A/\n3PxRzWGT21lJp/WENLLy2Cx1L+HOSQ1XVaCUD4KKOY6YpDpPMa6OYBRq+7JhasIc\nQtNJk67LQdLsye/XNAWFUB7xAjEA+vPa92brCLMFGQDbZ1GUQe/pfw6eoFWCg9TC\nlfaKdDvqd2ygYupMmNxWrSlt11elAjEA8bhzE6sarsTunj0JOBk8MmzGmirP6qTK\nlsLMwMehZbCpf4uOGURCwP7K7jkzan3nAjEA98NKrHgwFKaqocT22Urx1SfIoGkO\ns7243e9xLh37FEcTdlUJBJ/OgB0KdmwwxisBAjA4R6TrkGwvAwU37Kgn2qBMcU0w\negVc8a+FuKdpv1FR1vcwDjMwqNcODoT7QHA7PEMCMQDvv3k5nFwQ2+wnDGQs00vg\nX77tghZPvWmYfMNWKFNCNPz2gJ4YL7jCU3aotyzEDYQ=\n-----END RSA PRIVATE KEY-----\n' | |
cert = '-----BEGIN CERTIFICATE-----\nMIIBiTCCAROgAwIBAgICA+gwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAwwLZXhh\nbXBsZS5jb20wHhcNMjIxMDA2MTAwNTQ5WhcNMzIxMDAzMTAwNTQ5WjAWMRQwEgYD\nVQQDDAtleGFtcGxlLmNvbTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDs9GE3HOar\nEUsjWFATw/+h/73GxarU2/iHFuOTwGeZTCDI+Ay3TRfv+GZVUlSlPUHwuZYqP1++\nrGYcBtrvu78DgYtWsLsEPdcVa6HkeKM6UarN9Q2A5e7gn2zGYWxtpuMCAwEAAaMr\nMCkwDwYDVR0TBAgwBgEB/wIBADAWBgNVHREEDzANggtleGFtcGxlLmNvbTANBgkq\nhkiG9w0BAQsFAANhAERnjq9SMzRGIzOb5N3JAuv1w18GSceKjqNGscisyVkIEWTf\n5hUm2NaVrFA65o7STucxdxN5Y7ydBVvDY+7pA8TicqE36BKwXC3cUU5HGyQw+D1K\ndnff2J0hDORtyhLsxw==\n-----END CERTIFICATE-----\n' | |
""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local libxml2 = require "xmlua.libxml2" | |
local stringx = require "pl.stringx" | |
local kong = kong | |
local table_concat = table.concat | |
local base64_decode = ngx.decode_base64 | |
local pkey = require("resty.openssl.pkey") | |
local ffi = require("ffi") | |
local loaded, xml2 = pcall(ffi.load, "xml2") | |
if not loaded then | |
xml2 = ffi.load("libxml2.so.2") | |
end | |
local expadom = require "expadom" | |
if not pcall(ffi.typeof, "struct _xmlOutputBuffer") then | |
ffi.cdef[[ | |
typedef unsigned char xmlChar; | |
typedef struct _xmlBuffer xmlBuffer; | |
typedef xmlBuffer *xmlBufferPtr; | |
typedef struct _xmlCharEncodingHandler xmlCharEncodingHandler; | |
typedef xmlCharEncodingHandler *xmlCharEncodingHandlerPtr; | |
typedef int (*xmlOutputWriteCallback) (void * context, const char * buffer, int len); | |
typedef int (*xmlOutputCloseCallback) (void * context); | |
struct _xmlOutputBuffer { | |
void* context; | |
xmlOutputWriteCallback writecallback; | |
xmlOutputCloseCallback closecallback; | |
xmlCharEncodingHandlerPtr encoder; /* I18N conversions to UTF-8 */ | |
xmlBufferPtr buffer; /* Local buffer encoded in UTF-8 or ISOLatin */ | |
xmlBufferPtr conv; /* if encoder != NULL buffer for output */ | |
int written; /* total number of byte written */ | |
int error; | |
}; | |
typedef struct _xmlOutputBuffer xmlOutputBuffer; | |
typedef xmlOutputBuffer *xmlOutputBufferPtr; | |
xmlOutputBufferPtr xmlAllocOutputBuffer (xmlCharEncodingHandlerPtr encoder); | |
xmlOutputBufferPtr xmlOutputBufferCreateBuffer (xmlBufferPtr buffer, xmlCharEncodingHandlerPtr encoder); | |
int xmlOutputBufferClose (xmlOutputBufferPtr out); | |
int xmlC14NDocSaveTo (xmlDocPtr doc, | |
xmlNodeSetPtr nodes, | |
int mode, /* a xmlC14NMode */ | |
xmlChar **inclusive_ns_prefixes, | |
int with_comments, | |
xmlOutputBufferPtr buf); | |
]] | |
end | |
local function __xmlParserVersionIsAvailable() | |
local success, err = pcall(function() | |
local func = xml2.__xmlParserVersion | |
type(func) | |
end) | |
return success, err | |
end | |
local function __xmlC14NDocSaveToIsAvailable() | |
local success, err = pcall(function() | |
local func = xml2.xmlC14NDocSaveTo | |
type(func) | |
end) | |
return success, err | |
end | |
local function xmlOutputBufferCreate(buffer) | |
return ffi.gc(xml2.xmlOutputBufferCreateBuffer(buffer, nil), xml2.xmlOutputBufferClose) | |
end | |
-- normalize given xml string | |
local function c14n(xml,inclusive_ns_prefixes) | |
local xmlParserVersion | |
if __xmlParserVersionIsAvailable() then | |
xmlParserVersion = xml2.__xmlParserVersion()[0] | |
else | |
xmlParserVersion = xml2.xmlParserVersion | |
end | |
-- ngx.print("XML parser version: ", xmlParserVersion) | |
local ok, err = __xmlC14NDocSaveToIsAvailable() | |
if ok then | |
-- ngx.say("function xmlC14NDocSaveTo() is available") | |
else | |
ngx.print("function xmlC14NDocSaveTo() is not available: ", err) | |
return nil | |
end | |
local context = libxml2.xmlNewParserCtxt() | |
local document = libxml2.xmlCtxtReadMemory(context, xml) | |
local buffer = libxml2.xmlBufferCreate() | |
local output_buffer = xmlOutputBufferCreate(buffer) | |
local inclusive_ns_prefixes_array = nil | |
if inclusive_ns_prefixes then | |
local parsed_prefixes = stringx.split(inclusive_ns_prefixes, " ") | |
inclusive_ns_prefixes_array = ffi.new('xmlChar*[?]', #parsed_prefixes+1) | |
for i, namespace in ipairs(parsed_prefixes) do | |
local c_ns = ffi.new("unsigned char[?]", #namespace+1, namespace) | |
ffi.copy(c_ns, namespace) | |
inclusive_ns_prefixes_array[i-1] = c_ns | |
end | |
inclusive_ns_prefixes_array[#parsed_prefixes] = nil | |
end | |
xml2.xmlC14NDocSaveTo(document, nil, 1, inclusive_ns_prefixes_array, 0, output_buffer) | |
local content = libxml2.xmlBufferGetContent(buffer) | |
return content | |
end | |
local function verify_signature(xml_saml, sig_method, public_key) | |
local sig_elem = xml_saml:getElementsByTagNameNS("*", "SignatureValue")[1] | |
if sig_elem then | |
local sig_val = sig_elem.childNodes[1].data | |
local signed_elem = xml_saml:getElementsByTagNameNS("*", "SignedInfo")[1] | |
local signed_elem_str = table_concat(signed_elem:write({},{})) | |
ngx.print('-- SIGNED ELE --\n') | |
ngx.say(signed_elem_str) | |
local canon_signed = c14n(signed_elem_str, "ds") | |
ngx.print('\n-- CANON SIGNED --\n') | |
ngx.say(canon_signed) | |
local pub, err = pkey.new(public_key) | |
if not pub then | |
ngx.say('no pk ----', err) | |
return | |
end | |
ngx.print(sig_val) | |
local sig, err = base64_decode(sig_val) | |
if not sig then | |
return false, "failed base64-decode of signature: " .. err | |
end | |
local digest = require("resty.openssl.digest").new(sig_method) | |
digest:update(canon_signed) | |
local ok, err = pub:verify(sig, digest) | |
if ok then | |
ngx.say("- OK -") | |
return true | |
else | |
ngx.say("- NOT OK -") | |
return nil, err and ("Verification failed: " .. tostring(err)) or "Verification failed" | |
end | |
else | |
ngx.say('no sig') | |
return false, "signature value not found" | |
end | |
end | |
local saml = [[<Test><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><ds:Reference URI=""><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>KP3ncf09YSgkeTt+i4PR+W0AMvUTo7M8gu0z15piPMc=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>n2eQW4CLddrL3sl7TZREO03psJ8gTV9cdWVvoRhM75Ypa7sKwRmckEw8Pz3CycaZI/or5XQcactY8Lnr2jNaN+ifbJVQQwRguI89VQGI5UsRX9K9ommYqChXSoA4LA0I</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIBiTCCAROgAwIBAgICA+gwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAwwLZXhh | |
bXBsZS5jb20wHhcNMjIxMDA2MTAwNTQ5WhcNMzIxMDAzMTAwNTQ5WjAWMRQwEgYD | |
VQQDDAtleGFtcGxlLmNvbTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDs9GE3HOar | |
EUsjWFATw/+h/73GxarU2/iHFuOTwGeZTCDI+Ay3TRfv+GZVUlSlPUHwuZYqP1++ | |
rGYcBtrvu78DgYtWsLsEPdcVa6HkeKM6UarN9Q2A5e7gn2zGYWxtpuMCAwEAAaMr | |
MCkwDwYDVR0TBAgwBgEB/wIBADAWBgNVHREEDzANggtleGFtcGxlLmNvbTANBgkq | |
hkiG9w0BAQsFAANhAERnjq9SMzRGIzOb5N3JAuv1w18GSceKjqNGscisyVkIEWTf | |
5hUm2NaVrFA65o7STucxdxN5Y7ydBVvDY+7pA8TicqE36BKwXC3cUU5HGyQw+D1K | |
dnff2J0hDORtyhLsxw== | |
</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></Test> | |
]] | |
local xml_parsed = expadom.parseDocument(saml) | |
if not xml_parsed then | |
ngx.say('unable to parse') | |
end | |
--local k = "MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhAOz0YTcc5qsRSyNYUBPD/6H/vcbFqtTb+IcW45PAZ5lMIMj4DLdNF+/4ZlVSVKU9QfC5lio/X76sZhwG2u+7vwOBi1awuwQ91xVroeR4ozpRqs31DYDl7uCfbMZhbG2m4wIDAQAB" | |
--local public_key = "-----BEGIN PUBLIC KEY-----\n" .. k .. "\n-----END PUBLIC KEY-----" | |
local public_key = [[-----BEGIN PUBLIC KEY----- | |
MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhAOz0YTcc5qsRSyNYUBPD/6H/vcbFqtTb | |
+IcW45PAZ5lMIMj4DLdNF+/4ZlVSVKU9QfC5lio/X76sZhwG2u+7vwOBi1awuwQ9 | |
1xVroeR4ozpRqs31DYDl7uCfbMZhbG2m4wIDAQAB | |
-----END PUBLIC KEY-----]] | |
local ret = verify_signature(xml_parsed, "SHA256", public_key) | |
ngx.say(ret) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
>>> data_to_sign = '<Test/>' | |
>>> ret = get_signed_saml(data_to_sign, private_key, cert) | |
>>> ret | |
'<Test><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><ds:Reference URI=""><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>KP3ncf09YSgkeTt+i4PR+W0AMvUTo7M8gu0z15piPMc=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>n2eQW4CLddrL3sl7TZREO03psJ8gTV9cdWVvoRhM75Ypa7sKwRmckEw8Pz3CycaZI/or5XQcactY8Lnr2jNaN+ifbJVQQwRguI89VQGI5UsRX9K9ommYqChXSoA4LA0I</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIBiTCCAROgAwIBAgICA+gwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAwwLZXhh\nbXBsZS5jb20wHhcNMjIxMDA2MTAwNTQ5WhcNMzIxMDAzMTAwNTQ5WjAWMRQwEgYD\nVQQDDAtleGFtcGxlLmNvbTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDs9GE3HOar\nEUsjWFATw/+h/73GxarU2/iHFuOTwGeZTCDI+Ay3TRfv+GZVUlSlPUHwuZYqP1++\nrGYcBtrvu78DgYtWsLsEPdcVa6HkeKM6UarN9Q2A5e7gn2zGYWxtpuMCAwEAAaMr\nMCkwDwYDVR0TBAgwBgEB/wIBADAWBgNVHREEDzANggtleGFtcGxlLmNvbTANBgkq\nhkiG9w0BAQsFAANhAERnjq9SMzRGIzOb5N3JAuv1w18GSceKjqNGscisyVkIEWTf\n5hUm2NaVrFA65o7STucxdxN5Y7ydBVvDY+7pA8TicqE36BKwXC3cUU5HGyQw+D1K\ndnff2J0hDORtyhLsxw==\n</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></Test>' | |
>>> print(ret) | |
<Test><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><ds:Reference URI=""><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>KP3ncf09YSgkeTt+i4PR+W0AMvUTo7M8gu0z15piPMc=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>n2eQW4CLddrL3sl7TZREO03psJ8gTV9cdWVvoRhM75Ypa7sKwRmckEw8Pz3CycaZI/or5XQcactY8Lnr2jNaN+ifbJVQQwRguI89VQGI5UsRX9K9ommYqChXSoA4LA0I</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIBiTCCAROgAwIBAgICA+gwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAwwLZXhh | |
bXBsZS5jb20wHhcNMjIxMDA2MTAwNTQ5WhcNMzIxMDAzMTAwNTQ5WjAWMRQwEgYD | |
VQQDDAtleGFtcGxlLmNvbTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQDs9GE3HOar | |
EUsjWFATw/+h/73GxarU2/iHFuOTwGeZTCDI+Ay3TRfv+GZVUlSlPUHwuZYqP1++ | |
rGYcBtrvu78DgYtWsLsEPdcVa6HkeKM6UarN9Q2A5e7gn2zGYWxtpuMCAwEAAaMr | |
MCkwDwYDVR0TBAgwBgEB/wIBADAWBgNVHREEDzANggtleGFtcGxlLmNvbTANBgkq | |
hkiG9w0BAQsFAANhAERnjq9SMzRGIzOb5N3JAuv1w18GSceKjqNGscisyVkIEWTf | |
5hUm2NaVrFA65o7STucxdxN5Y7ydBVvDY+7pA8TicqE36BKwXC3cUU5HGyQw+D1K | |
dnff2J0hDORtyhLsxw== | |
</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></Test> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment