Skip to content

Instantly share code, notes, and snippets.

@badri
Last active October 10, 2022 10:55
Show Gist options
  • Save badri/0cec99762f60eb4cc4e894368382cab0 to your computer and use it in GitHub Desktop.
Save badri/0cec99762f60eb4cc4e894368382cab0 to your computer and use it in GitHub Desktop.
SAML3 working setup
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'
"""
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)
>>> 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