Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for sha256-rsa-MGF1 signing algorithm (#328) #488

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

cornzz
Copy link

@cornzz cornzz commented Feb 13, 2025

Solves #328

@cjbarth
Copy link
Contributor

cjbarth commented Feb 13, 2025

Thank you very much for your contribution. Can you please include tests?

@cornzz
Copy link
Author

cornzz commented Feb 14, 2025

@cjbarth Could you give me a hint where to start? What exactly should be tested?
Im a bit lost, there are no tests testing each of the signing methods, just for sha1. Also, the result of sha256 with mgf1 signing is not deterministic, so i cant just compare the signature to a hardcoded value as is being done in all other tests. Likewise in node-saml. There I tried writing a test that uses validateSignature to validate the generated signature but its not working as I cant get it to parse the generated signature correctly. I dont have much experience working with XML.

@srd90
Copy link

srd90 commented Feb 15, 2025

... I dont have much experience working with XML.

@cornzz When I used version of xml-crypto from your pull request (your PR's commit version ef49b7e ) to run this code:

// this example was written for author of
// https://github.com/node-saml/xml-crypto/pull/488
// so that author can/may use this as an example how to
// generate e.g. test material for PR or for node-saml project
// side repository
//
// This script was written using xml-crypto from aforementioned
// PR exact commit version was ef49b7e
//
// this script is also slightly modified version of
// https://github.com/node-saml/passport-saml/discussions/836#discussioncomment-4638714
// 1) added namespaces to xpath statements
// 2) seems to work with xml-crypto 6.0.0 based codebase
// 3) added idpCert to keyinfo (added implicitly by xml-crypto when signing)
// 4) modified so that signatureAlgorithm can be provided as parameter
//    for signSamlAuthnResponse

const SignedXml = require("xml-crypto").SignedXml;

// actual signAuthnResponseMessage function (with message and assertion signing)
// is at the end of this example...following stuff is just to test
// example signAuthnResponseMessage

// Result(s) of signAuthnResponseMessage function was tested with samltool's
// SAML Response signature and xml schema validations

// --- Start dummy test material -----

// this is simulating IdP which signs AuthnResonse thus we need
// IdP's priavte key
// copied from:
// https://github.com/node-saml/passport-saml/blob/72effd8c9a694eb295a007b6900ba7e71bbe0a0d/test/static/key.pem
const IDP_PRIVATE_KEY = `
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAxG3ouM7U+fXbJt69X1H6d4UNg/uRr06pFuU9RkfIwNC+yaXy
ptqB3ynXKsL7BFt4DCd0fflRvJAx3feJIDp16wN9GDVHcufWMYPhh2j5HcTW/j9J
oIJzGhJyvO00YKBt+hHy83iN1SdChKv5y0iSyiPP5GnqFw+ayyHoM6hSO0PqBou1
Xb0ZSIE+DHosBnvVna5w2AiPY4xrJl9yZHZ4Q7DfMiYTgstjETio4bX+6oLiBnYk
tn7DjdEslqhffVme4PuBxNojI+uCeg/sn4QVLd/iogMJfDWNuLD8326Mi/FE9cCR
vFlvAiMSaebMI3zPaySsxTK7Zgj5TpEbmbHI9wIDAQABAoIBAF/Hh/a1Q7wuWZH2
gjh8bLjis9hrTnpAzMpRNTOTxRvfrWf99vfNDA6ZBEXhlSxmvX6PronOjEB5vxcQ
oFiKqPzTUqf/MruguBykxc+VLAOL+5k1mt0dPqqz3CarMyL6lyWcou59FgudfR3c
DY1F8e2G0NP7oR1lioEKI4MszAwBEUt6oB4wDkGBv31uUbqtJZlxid9qOeMZxSCl
/uzd32wOwc/zWPCS2mtsE2PScq5Wzep6EGQEDRno0WbfkxHn+CZxvRYv5XVWtyUD
yCBrKuGQhRCCp6RO0x+39qxtXyT4m2ehwJb0wVmTPQ6e4ZayjRSlYHJI4+YPcdgc
WeT4HOECgYEA/SidmPth4jfQY7H6gv1wryNCNHsWssYiittsjsEv//McQR1Nsnoi
bU6RJTqpNFU0PPDgf9oh4W6Jxg8uHeuOcykacPhtlC9CotRYSJrxaOefW72G+ZWP
VlnErdJWPyb61olLKOH/lyXCbs7k3JltPqJwJGdt+9N9eu+N3D6+B80CgYEAxqJL
+J3UJVUSpLfkgnp03IglAeABEoCb1LzO8G63dHxucCP+Jt/enB1qSZ8ez+VwACzh
eCSFwzdL7Jqh0KJmcJf67c6YXZDfgT9oxWf6sY5KuljWvt6uvpvAATaHDM6Mvzyj
vlc/d+8uwed/Slbq2EfeTzPP6goK3ppfbBQFx9MCgYEA4JTWcm+X31J6WOb8AJaL
D6OsyNflRAVHgX206VNynJH0H8O6OLnmrqeDVc6baqSnqeRalLFTWyRvrreqxrpA
beMp5MxOkaX3bHIKO6bQwKqyEXWqNuG5/fW26CjvgCi5X/b+KS+MSW8i9KAwIY8u
feEmsPTcegmdiKDZbWhvtoUCgYBJooq1TJUDjekOZRlyAUFnK5VEf60GFeUu1RuF
6BVcOnCaY81ozd7xUro/Npyuhyig+AJRjoCD4PDlcmGAPWPqY3zjQY4cSYOBn2cQ
nz5BKjWrpRlewqBXCtf/2x3vcnacwjcVbbSamnFj8pSuk1AWA3Z3OAbghP6IjQPI
xhdqfwKBgBUG49pMk1yYldtrDWQnGg/73nKXcnxyRus8uus51eLFUUaTDyp2HMKY
DQer/NkQDDf26Ze1nBWURVPoMSU98JixBQjeKn3MX39PHtwFh6s3mxwLlzyxjAcu
MmFNzbu+qfEJ7pFmNaYR83s52qs6GyfclVPB8g6ICV5c98VoFfqB
-----END RSA PRIVATE KEY-----
`;

// not needed by this sample code. IdP's cert is added just to
// have all necessary information in one place to test that
// signing works (i.e. if you want to use certificate to test
// that signatures are valid you don't have to look all over the
// places).
// copied from:
// https://github.com/node-saml/passport-saml/blob/72effd8c9a694eb295a007b6900ba7e71bbe0a0d/test/static/cert.pem
const IDP_CERT = `
-----BEGIN CERTIFICATE-----
MIIDtTCCAp2gAwIBAgIJAKg4VeVcIDz1MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTUwODEzMDE1NDIwWhcNMTUwOTEyMDE1NDIwWjBF
MQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAxG3ouM7U+fXbJt69X1H6d4UNg/uRr06pFuU9RkfIwNC+yaXyptqB3ynX
KsL7BFt4DCd0fflRvJAx3feJIDp16wN9GDVHcufWMYPhh2j5HcTW/j9JoIJzGhJy
vO00YKBt+hHy83iN1SdChKv5y0iSyiPP5GnqFw+ayyHoM6hSO0PqBou1Xb0ZSIE+
DHosBnvVna5w2AiPY4xrJl9yZHZ4Q7DfMiYTgstjETio4bX+6oLiBnYktn7DjdEs
lqhffVme4PuBxNojI+uCeg/sn4QVLd/iogMJfDWNuLD8326Mi/FE9cCRvFlvAiMS
aebMI3zPaySsxTK7Zgj5TpEbmbHI9wIDAQABo4GnMIGkMB0GA1UdDgQWBBSVGgvo
W4MhMuzBGce29PY8vSzHFzB1BgNVHSMEbjBsgBSVGgvoW4MhMuzBGce29PY8vSzH
F6FJpEcwRTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV
BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAKg4VeVcIDz1MAwGA1UdEwQF
MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJu1rqs+anD74dbdwgd3CnqnQsQDJiEX
mBhG2leaGt3ve9b/9gKaJg2pyb2NyppDe1uLqh6nNXDuzg1oNZrPz5pJL/eCXPl7
FhxhMUi04TtLf8LeNTCIWYZiFuO4pmhohHcv8kRvYR1+6SkLTC8j/TZerm7qvesS
iTQFNapa1eNdVQ8nFwVkEtWl+JzKEM1BlRcn42sjJkijeFp7DpI7pU+PnYeiaXpR
v5pJo8ogM1iFxN+SnfEs0EuQ7fhKIG9aHKi7bKZ7L6SyX7MDIGLeulEU6lf5D9Bf
XNmcMambiS0pXhL2QXajt96UBq8FT2KNXY8XNtR4y6MyyCzhaiZZcc8=
-----END CERTIFICATE-----
`;

// just some example authn response for testing signing...
// copied (and modified) from https://github.com/node-saml/passport-saml/issues/419
const sampleSamlLoginResponse = (() => {
  const nameId = "[email protected]";
  const inResponseTo = "TBD_inresponse-value";
  const sessionIndex = "TBD_session-index-value";
  const notBefore = "1980-01-01T01:00:00Z"
  const issueInstant = "1980-01-01T01:01:00Z";
  const notOnOrAfter = "4980-01-01T01:01:00Z";
  const issuer = "idp-issuer-value";
  const audience = "audience-value";
  const destination = "https://TBD-ACS-URL";

  return `<samlp:Response
    xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
    ID="_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    Version="2.0"
    IssueInstant="${issueInstant}"
    Destination="${destination}"
    InResponseTo="${inResponseTo}">
    <saml:Issuer>${issuer}</saml:Issuer>
    <samlp:Status>
        <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
    </samlp:Status>
    <saml:Assertion
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        ID="_bbbbbbbbbbbbbbbbbbbbbbbb"
        Version="2.0" IssueInstant="${issueInstant}">
        <saml:Issuer>${issuer}</saml:Issuer>
        <saml:Subject>
            <saml:NameID
                SPNameQualifier="${audience}"
                Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">${nameId}</saml:NameID>
            <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml:SubjectConfirmationData
                    NotOnOrAfter="${notOnOrAfter}"
                    Recipient="${destination}"
                    InResponseTo="${inResponseTo}"/>
            </saml:SubjectConfirmation>
        </saml:Subject>
        <saml:Conditions
            NotBefore="${notBefore}"
            NotOnOrAfter="${notOnOrAfter}">
            <saml:AudienceRestriction>
                <saml:Audience>${audience}</saml:Audience>
            </saml:AudienceRestriction>
        </saml:Conditions>
        <saml:AuthnStatement
            AuthnInstant="${issueInstant}"
            SessionNotOnOrAfter="${notOnOrAfter}"
            SessionIndex="${sessionIndex}">
            <saml:AuthnContext>
                <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
            </saml:AuthnContext>
        </saml:AuthnStatement>
    </saml:Assertion>
</samlp:Response>`
})();

// --- End dummy test material -----

const signSamlAuthnResponse = (
  idpCert,
  idpPrivateKey,
  signatureAlgorithm,
  inputSamlAuthnResponseMsg,
  wantMessageSigned = true,
  wantAssertionSigned = true
) => {
  const signAssertion = () => {
    const sig = new SignedXml({ publicCert: idpCert, privateKey: idpPrivateKey });
    sig.addReference({
      // NOTE: assume exactly one (unencrypted) assertion
      //
      // if you want to use (signed) encrypted assertions modify this function to
      // first sign unencrypted assertion with IdP's key and then encrypt
      // Assertion with SP's certificate/public key and replace unencrypted
      // assertion with EncryptedAssertion
      xpath: "(" +
             "/*[namespace-uri()='urn:oasis:names:tc:SAML:2.0:protocol' and local-name()='Response']" +
             "/*[namespace-uri()='urn:oasis:names:tc:SAML:2.0:assertion' and local-name()='Assertion']" +
             ")" +
             "[1]",
      transforms: [
        "http://www.w3.org/2000/09/xmldsig#enveloped-signature",
        "http://www.w3.org/2001/10/xml-exc-c14n#"
      ],
      digestAlgorithm: "http://www.w3.org/2001/04/xmlenc#sha256"
    });
    sig.signatureAlgorithm = signatureAlgorithm;
    sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
    sig.computeSignature(
      inputSamlAuthnResponseMsg,
      {
        // according to:
        // https://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd
        // Assertion's ds:Signature must be after Assertion/Issuer
        location: {
          reference: "/*[namespace-uri()='urn:oasis:names:tc:SAML:2.0:protocol' and local-name()='Response']" +
                     "/*[namespace-uri()='urn:oasis:names:tc:SAML:2.0:assertion' and local-name()='Assertion']" +
                     "/*[namespace-uri()='urn:oasis:names:tc:SAML:2.0:assertion' and local-name()='Issuer']",
          action: "after"
        }
      }
    );
    return sig.getSignedXml();
  };

  const signMessage = (responseMessage) => {
    const sig = new SignedXml({ publicCert: idpCert, privateKey: idpPrivateKey });
    sig.addReference({
      xpath: "/*[namespace-uri()='urn:oasis:names:tc:SAML:2.0:protocol' and local-name()='Response']",
      transforms: [
        "http://www.w3.org/2000/09/xmldsig#enveloped-signature",
        "http://www.w3.org/2001/10/xml-exc-c14n#"
      ],
      digestAlgorithm: "http://www.w3.org/2001/04/xmlenc#sha256"
    });
    sig.signatureAlgorithm = signatureAlgorithm;
    sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
    sig.computeSignature(
      responseMessage,
      {
        // according to:
        // https://docs.oasis-open.org/security/saml/v2.0/saml-schema-protocol-2.0.xsd
        // Response's ds:Signature must be after Response/Issuer
        location: {
          reference: "/*[namespace-uri()='urn:oasis:names:tc:SAML:2.0:protocol' and local-name()='Response']" +
                     "/*[namespace-uri()='urn:oasis:names:tc:SAML:2.0:assertion' and local-name()='Issuer']",
          action: "after"
        }
      }
    );
    return sig.getSignedXml();
  };

  let authnResponse = (wantAssertionSigned ? signAssertion() : inputSamlAuthnResponseMsg);
  authnResponse = (wantMessageSigned ? signMessage(authnResponse) : authnResponse);
  return authnResponse;
};
 
console.log(
  signSamlAuthnResponse(
    IDP_CERT, // placed to keyinfo x509 data
    IDP_PRIVATE_KEY,
    // signarure algorithms to choose from:
    // MGF1 is related to https://github.com/node-saml/xml-crypto/pull/488
    "http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1",
//    "http://www.w3.org/2000/09/xmldsig#rsa-sha1",
//    "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
//    "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
    sampleSamlLoginResponse,
    true,
    true
  )
);

Result is (note as author states MGF1 adds salt to signature so signature value change each time you execute script)

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" Version="2.0" IssueInstant="1980-01-01T01:01:00Z" Destination="https://TBD-ACS-URL" InResponseTo="TBD_inresponse-value">
    <saml:Issuer>idp-issuer-value</saml:Issuer><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><SignatureMethod Algorithm="http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1"/><Reference URI="#_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><DigestValue>EG39Z3F19EfUHJDgC+tXRDzBAdJf2sb9zfb5dS+j38c=</DigestValue></Reference></SignedInfo><SignatureValue>upKVKqdxrzzBmzJc/fHZ2ZgIROFbpxgPFumHbRzPWdDxYPRF5xDS/4bJj6rbPyQUufcc/6MkNJiCrvt1t2eDtWxLMo6nBU5Xj324nutjpeTu3BdlacSayRMDOeAPHCStehMyDxMj+IcKcAeEY4GHsstPfheheUcUb8JV26AZRdxItEilCDyq9+Lk7OO/GhNdidYSFpJBqXs9obWXJkoX2M84WjT9Lbla3Ek/2GC4ApUfbMSAVIVWzUcMNlX2A86Ktpck2+XgRJ+AjZXsarcPcFUQl4DVNbrbMkiUbwaWRaddknGw1aA3RQ1o2qrQZBD7fYaJ8ehHzZOqY3lFS/14Lg==</SignatureValue><KeyInfo><X509Data><X509Certificate>MIIDtTCCAp2gAwIBAgIJAKg4VeVcIDz1MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTUwODEzMDE1NDIwWhcNMTUwOTEyMDE1NDIwWjBFMQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxG3ouM7U+fXbJt69X1H6d4UNg/uRr06pFuU9RkfIwNC+yaXyptqB3ynXKsL7BFt4DCd0fflRvJAx3feJIDp16wN9GDVHcufWMYPhh2j5HcTW/j9JoIJzGhJyvO00YKBt+hHy83iN1SdChKv5y0iSyiPP5GnqFw+ayyHoM6hSO0PqBou1Xb0ZSIE+DHosBnvVna5w2AiPY4xrJl9yZHZ4Q7DfMiYTgstjETio4bX+6oLiBnYktn7DjdEslqhffVme4PuBxNojI+uCeg/sn4QVLd/iogMJfDWNuLD8326Mi/FE9cCRvFlvAiMSaebMI3zPaySsxTK7Zgj5TpEbmbHI9wIDAQABo4GnMIGkMB0GA1UdDgQWBBSVGgvoW4MhMuzBGce29PY8vSzHFzB1BgNVHSMEbjBsgBSVGgvoW4MhMuzBGce29PY8vSzHF6FJpEcwRTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAKg4VeVcIDz1MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJu1rqs+anD74dbdwgd3CnqnQsQDJiEXmBhG2leaGt3ve9b/9gKaJg2pyb2NyppDe1uLqh6nNXDuzg1oNZrPz5pJL/eCXPl7FhxhMUi04TtLf8LeNTCIWYZiFuO4pmhohHcv8kRvYR1+6SkLTC8j/TZerm7qvesSiTQFNapa1eNdVQ8nFwVkEtWl+JzKEM1BlRcn42sjJkijeFp7DpI7pU+PnYeiaXpRv5pJo8ogM1iFxN+SnfEs0EuQ7fhKIG9aHKi7bKZ7L6SyX7MDIGLeulEU6lf5D9BfXNmcMambiS0pXhL2QXajt96UBq8FT2KNXY8XNtR4y6MyyCzhaiZZcc8=</X509Certificate></X509Data></KeyInfo></Signature>
    <samlp:Status>
        <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
    </samlp:Status>
    <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="_bbbbbbbbbbbbbbbbbbbbbbbb" Version="2.0" IssueInstant="1980-01-01T01:01:00Z">
        <saml:Issuer>idp-issuer-value</saml:Issuer><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><SignatureMethod Algorithm="http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1"/><Reference URI="#_bbbbbbbbbbbbbbbbbbbbbbbb"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><DigestValue>pSPi0rNAYnJkM1Ec3KF7657lJrkXRkOENc/U/CG0Uu4=</DigestValue></Reference></SignedInfo><SignatureValue>LXcxG4SC3E6nfQJTMIielnyb6Tad7xWxmxjQQUlcdcT5oAWG9xWjKPRoW/RWrNbJt1PFAXAs9hIj/Hiy/YoWKv026qzSS2zuQs0iPxgNeMRPRMY+oVIePW8Uh1LPJMEqHyBaWmBWp1w+KkDBSCaiRL9CkEEwxznUt9HJJ8ViF14MeGDadoduj+EjzPJcfLqQ66vR1/bN//FsTWEY2viXYp/LTkypxxliD3yyNMgL4QhNTgIL0FbdRO8YNa3szrbk1/5PJc4I1SuS8B8cx5bW0YwDDVH2LgFH4WG8qssM0xv17KTDlCXS0QtCjNOMHj7hC8CNDUWCSFr9ROjbH4JjQQ==</SignatureValue><KeyInfo><X509Data><X509Certificate>MIIDtTCCAp2gAwIBAgIJAKg4VeVcIDz1MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTUwODEzMDE1NDIwWhcNMTUwOTEyMDE1NDIwWjBFMQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxG3ouM7U+fXbJt69X1H6d4UNg/uRr06pFuU9RkfIwNC+yaXyptqB3ynXKsL7BFt4DCd0fflRvJAx3feJIDp16wN9GDVHcufWMYPhh2j5HcTW/j9JoIJzGhJyvO00YKBt+hHy83iN1SdChKv5y0iSyiPP5GnqFw+ayyHoM6hSO0PqBou1Xb0ZSIE+DHosBnvVna5w2AiPY4xrJl9yZHZ4Q7DfMiYTgstjETio4bX+6oLiBnYktn7DjdEslqhffVme4PuBxNojI+uCeg/sn4QVLd/iogMJfDWNuLD8326Mi/FE9cCRvFlvAiMSaebMI3zPaySsxTK7Zgj5TpEbmbHI9wIDAQABo4GnMIGkMB0GA1UdDgQWBBSVGgvoW4MhMuzBGce29PY8vSzHFzB1BgNVHSMEbjBsgBSVGgvoW4MhMuzBGce29PY8vSzHF6FJpEcwRTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAKg4VeVcIDz1MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJu1rqs+anD74dbdwgd3CnqnQsQDJiEXmBhG2leaGt3ve9b/9gKaJg2pyb2NyppDe1uLqh6nNXDuzg1oNZrPz5pJL/eCXPl7FhxhMUi04TtLf8LeNTCIWYZiFuO4pmhohHcv8kRvYR1+6SkLTC8j/TZerm7qvesSiTQFNapa1eNdVQ8nFwVkEtWl+JzKEM1BlRcn42sjJkijeFp7DpI7pU+PnYeiaXpRv5pJo8ogM1iFxN+SnfEs0EuQ7fhKIG9aHKi7bKZ7L6SyX7MDIGLeulEU6lf5D9BfXNmcMambiS0pXhL2QXajt96UBq8FT2KNXY8XNtR4y6MyyCzhaiZZcc8=</X509Certificate></X509Data></KeyInfo></Signature>
        <saml:Subject>
            <saml:NameID SPNameQualifier="audience-value" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">[email protected]</saml:NameID>
            <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml:SubjectConfirmationData NotOnOrAfter="4980-01-01T01:01:00Z" Recipient="https://TBD-ACS-URL" InResponseTo="TBD_inresponse-value"/>
            </saml:SubjectConfirmation>
        </saml:Subject>
        <saml:Conditions NotBefore="1980-01-01T01:00:00Z" NotOnOrAfter="4980-01-01T01:01:00Z">
            <saml:AudienceRestriction>
                <saml:Audience>audience-value</saml:Audience>
            </saml:AudienceRestriction>
        </saml:Conditions>
        <saml:AuthnStatement AuthnInstant="1980-01-01T01:01:00Z" SessionNotOnOrAfter="4980-01-01T01:01:00Z" SessionIndex="TBD_session-index-value">
            <saml:AuthnContext>
                <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
            </saml:AuthnContext>
        </saml:AuthnStatement>
    </saml:Assertion>
</samlp:Response>

When aforementioned result is copy pasted to https://tools.chilkat.io/xmlDsigVerify.cshtml
it says that:

NumSignatures: 2

Signature 1

Signature Verified
Number of Reference Digests = 1
Reference 1 digest is valid.

Signature 2

Signature Verified
Number of Reference Digests = 1
Reference 1 digest is valid.

So it seems that at least one unrelated 3rd party tool understands signatures generated with xml-crypto's MGF1.


For readability here is aforementioned output as pretty printed xml:

<?xml version="1.0"?>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" Version="2.0" IssueInstant="1980-01-01T01:01:00Z" Destination="https://TBD-ACS-URL" InResponseTo="TBD_inresponse-value">
  <saml:Issuer>idp-issuer-value</saml:Issuer>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
      <SignatureMethod Algorithm="http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1"/>
      <Reference URI="#_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
          <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
        <DigestValue>EG39Z3F19EfUHJDgC+tXRDzBAdJf2sb9zfb5dS+j38c=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>upKVKqdxrzzBmzJc/fHZ2ZgIROFbpxgPFumHbRzPWdDxYPRF5xDS/4bJj6rbPyQUufcc/6MkNJiCrvt1t2eDtWxLMo6nBU5Xj324nutjpeTu3BdlacSayRMDOeAPHCStehMyDxMj+IcKcAeEY4GHsstPfheheUcUb8JV26AZRdxItEilCDyq9+Lk7OO/GhNdidYSFpJBqXs9obWXJkoX2M84WjT9Lbla3Ek/2GC4ApUfbMSAVIVWzUcMNlX2A86Ktpck2+XgRJ+AjZXsarcPcFUQl4DVNbrbMkiUbwaWRaddknGw1aA3RQ1o2qrQZBD7fYaJ8ehHzZOqY3lFS/14Lg==</SignatureValue>
    <KeyInfo>
      <X509Data>
        <X509Certificate>MIIDtTCCAp2gAwIBAgIJAKg4VeVcIDz1MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTUwODEzMDE1NDIwWhcNMTUwOTEyMDE1NDIwWjBFMQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxG3ouM7U+fXbJt69X1H6d4UNg/uRr06pFuU9RkfIwNC+yaXyptqB3ynXKsL7BFt4DCd0fflRvJAx3feJIDp16wN9GDVHcufWMYPhh2j5HcTW/j9JoIJzGhJyvO00YKBt+hHy83iN1SdChKv5y0iSyiPP5GnqFw+ayyHoM6hSO0PqBou1Xb0ZSIE+DHosBnvVna5w2AiPY4xrJl9yZHZ4Q7DfMiYTgstjETio4bX+6oLiBnYktn7DjdEslqhffVme4PuBxNojI+uCeg/sn4QVLd/iogMJfDWNuLD8326Mi/FE9cCRvFlvAiMSaebMI3zPaySsxTK7Zgj5TpEbmbHI9wIDAQABo4GnMIGkMB0GA1UdDgQWBBSVGgvoW4MhMuzBGce29PY8vSzHFzB1BgNVHSMEbjBsgBSVGgvoW4MhMuzBGce29PY8vSzHF6FJpEcwRTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAKg4VeVcIDz1MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJu1rqs+anD74dbdwgd3CnqnQsQDJiEXmBhG2leaGt3ve9b/9gKaJg2pyb2NyppDe1uLqh6nNXDuzg1oNZrPz5pJL/eCXPl7FhxhMUi04TtLf8LeNTCIWYZiFuO4pmhohHcv8kRvYR1+6SkLTC8j/TZerm7qvesSiTQFNapa1eNdVQ8nFwVkEtWl+JzKEM1BlRcn42sjJkijeFp7DpI7pU+PnYeiaXpRv5pJo8ogM1iFxN+SnfEs0EuQ7fhKIG9aHKi7bKZ7L6SyX7MDIGLeulEU6lf5D9BfXNmcMambiS0pXhL2QXajt96UBq8FT2KNXY8XNtR4y6MyyCzhaiZZcc8=</X509Certificate>
      </X509Data>
    </KeyInfo>
  </Signature>
  <samlp:Status>
    <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
  </samlp:Status>
  <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="_bbbbbbbbbbbbbbbbbbbbbbbb" Version="2.0" IssueInstant="1980-01-01T01:01:00Z">
    <saml:Issuer>idp-issuer-value</saml:Issuer>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
      <SignedInfo>
        <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
        <SignatureMethod Algorithm="http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1"/>
        <Reference URI="#_bbbbbbbbbbbbbbbbbbbbbbbb">
          <Transforms>
            <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
            <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
          </Transforms>
          <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
          <DigestValue>pSPi0rNAYnJkM1Ec3KF7657lJrkXRkOENc/U/CG0Uu4=</DigestValue>
        </Reference>
      </SignedInfo>
      <SignatureValue>LXcxG4SC3E6nfQJTMIielnyb6Tad7xWxmxjQQUlcdcT5oAWG9xWjKPRoW/RWrNbJt1PFAXAs9hIj/Hiy/YoWKv026qzSS2zuQs0iPxgNeMRPRMY+oVIePW8Uh1LPJMEqHyBaWmBWp1w+KkDBSCaiRL9CkEEwxznUt9HJJ8ViF14MeGDadoduj+EjzPJcfLqQ66vR1/bN//FsTWEY2viXYp/LTkypxxliD3yyNMgL4QhNTgIL0FbdRO8YNa3szrbk1/5PJc4I1SuS8B8cx5bW0YwDDVH2LgFH4WG8qssM0xv17KTDlCXS0QtCjNOMHj7hC8CNDUWCSFr9ROjbH4JjQQ==</SignatureValue>
      <KeyInfo>
        <X509Data>
          <X509Certificate>MIIDtTCCAp2gAwIBAgIJAKg4VeVcIDz1MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTUwODEzMDE1NDIwWhcNMTUwOTEyMDE1NDIwWjBFMQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxG3ouM7U+fXbJt69X1H6d4UNg/uRr06pFuU9RkfIwNC+yaXyptqB3ynXKsL7BFt4DCd0fflRvJAx3feJIDp16wN9GDVHcufWMYPhh2j5HcTW/j9JoIJzGhJyvO00YKBt+hHy83iN1SdChKv5y0iSyiPP5GnqFw+ayyHoM6hSO0PqBou1Xb0ZSIE+DHosBnvVna5w2AiPY4xrJl9yZHZ4Q7DfMiYTgstjETio4bX+6oLiBnYktn7DjdEslqhffVme4PuBxNojI+uCeg/sn4QVLd/iogMJfDWNuLD8326Mi/FE9cCRvFlvAiMSaebMI3zPaySsxTK7Zgj5TpEbmbHI9wIDAQABo4GnMIGkMB0GA1UdDgQWBBSVGgvoW4MhMuzBGce29PY8vSzHFzB1BgNVHSMEbjBsgBSVGgvoW4MhMuzBGce29PY8vSzHF6FJpEcwRTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAKg4VeVcIDz1MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJu1rqs+anD74dbdwgd3CnqnQsQDJiEXmBhG2leaGt3ve9b/9gKaJg2pyb2NyppDe1uLqh6nNXDuzg1oNZrPz5pJL/eCXPl7FhxhMUi04TtLf8LeNTCIWYZiFuO4pmhohHcv8kRvYR1+6SkLTC8j/TZerm7qvesSiTQFNapa1eNdVQ8nFwVkEtWl+JzKEM1BlRcn42sjJkijeFp7DpI7pU+PnYeiaXpRv5pJo8ogM1iFxN+SnfEs0EuQ7fhKIG9aHKi7bKZ7L6SyX7MDIGLeulEU6lf5D9BfXNmcMambiS0pXhL2QXajt96UBq8FT2KNXY8XNtR4y6MyyCzhaiZZcc8=</X509Certificate>
        </X509Data>
      </KeyInfo>
    </Signature>
    <saml:Subject>
      <saml:NameID SPNameQualifier="audience-value" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">[email protected]</saml:NameID>
      <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
        <saml:SubjectConfirmationData NotOnOrAfter="4980-01-01T01:01:00Z" Recipient="https://TBD-ACS-URL" InResponseTo="TBD_inresponse-value"/>
      </saml:SubjectConfirmation>
    </saml:Subject>
    <saml:Conditions NotBefore="1980-01-01T01:00:00Z" NotOnOrAfter="4980-01-01T01:01:00Z">
      <saml:AudienceRestriction>
        <saml:Audience>audience-value</saml:Audience>
      </saml:AudienceRestriction>
    </saml:Conditions>
    <saml:AuthnStatement AuthnInstant="1980-01-01T01:01:00Z" SessionNotOnOrAfter="4980-01-01T01:01:00Z" SessionIndex="TBD_session-index-value">
      <saml:AuthnContext>
        <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
      </saml:AuthnContext>
    </saml:AuthnStatement>
  </saml:Assertion>
</samlp:Response>

@cornzz feel free to "downscale"/modify this script to generate more simple test material e.g. for signature verfication tests (especially for xml-crypto which doesn't have to have e.g. verbose SAML messages in test material sets).

@cornzz
Copy link
Author

cornzz commented Feb 17, 2025

@srd90 thank you very much! Ill look into it tomorrow and add some tests

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants