diff --git a/src/signed-xml.ts b/src/signed-xml.ts index 5dc18aa6..2fb3a7fc 100644 --- a/src/signed-xml.ts +++ b/src/signed-xml.ts @@ -216,9 +216,9 @@ export class SignedXml { */ static getCertFromKeyInfo(keyInfo?: Node | null): string | null { if (keyInfo != null) { - const certs = xpath.select1(".//*[local-name(.)='X509Certificate']", keyInfo); - if (isDomNode.isNodeLike(certs)) { - return utils.derToPem(certs.textContent || "", "CERTIFICATE"); + const cert = xpath.select1(".//*[local-name(.)='X509Certificate']", keyInfo); + if (isDomNode.isNodeLike(cert)) { + return utils.derToPem(cert.textContent ?? "", "CERTIFICATE"); } } diff --git a/src/utils.ts b/src/utils.ts index c706f8b0..60982869 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -177,11 +177,14 @@ export function derToPem( return normalizePem(base64Der); } - if (BASE64_REGEX.test(base64Der)) { + if (BASE64_REGEX.test(base64Der.replace(/ /g, ""))) { if (pemLabel == null) { throw new Error("PEM label is required when DER is given."); } - const pem = `-----BEGIN ${pemLabel}-----\n${base64Der}\n-----END ${pemLabel}-----`; + const pem = `-----BEGIN ${pemLabel}-----\n${base64Der.replace( + / /g, + "", + )}\n-----END ${pemLabel}-----`; return normalizePem(pem); } diff --git a/test/static/keyinfo - pretty-printed.xml b/test/static/keyinfo - pretty-printed.xml new file mode 100644 index 00000000..d48b61e4 --- /dev/null +++ b/test/static/keyinfo - pretty-printed.xml @@ -0,0 +1,68 @@ + + + https://evil-corp.com + + + uAP/VBhhaK2+Bn1lYjHB5tSHTcE=Q2F/63pvENmI+eURRIRmVI1fNpW+CxDan6YmGo2G5il+XOx72sBHS+FspoWDyezYUfO/Wfi+tBupK + /9eHOeg60uPUkQFwkdPmUsH2hJAPVCatQReSUJDhHCO6a2rrQixecPDBhzJjstCpibgvgNzevVVu + 9h3eMH/BNzdwO5EbnVTcb2JQj2F18MAh1LlVMBWWDaZmIQTk7npMY/NVEajM1fbwXyrPdNRU8poK + bjVoM7IL9s0TesQIeyQ01QOQQQ3kHZWnoqlWE6VbbTqHwuidfkqaQLLvF9sDneqXKBa7y2YEJXVm4 + GMzNoL/JOdSuNnU3rF0ET8UDSleV953/lbUA== +MIIDtTCCAp2gAwIBAgIJAKg4VeVcIDz1MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAlVTMRMwE + QYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMT + UwODEzMDE1NDIwWhcNMTUwOTEyMDE1NDIwWjBFMQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1 + TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEF + AAOCAQ8AMIIBCgKCAQEAxG3ouM7U+fXbJt69X1H6d4UNg/uRr06pFuU9RkfIwNC+yaXyptqB3ynXK + sL7BFt4DCd0fflRvJAx3feJIDp16wN9GDVHcufWMYPhh2j5HcTW/j9JoIJzGhJyvO00YKBt+hHy83 + iN1SdChKv5y0iSyiPP5GnqFw+ayyHoM6hSO0PqBou1Xb0ZSIE+DHosBnvVna5w2AiPY4xrJl9yZHZ + 4Q7DfMiYTgstjETio4bX+6oLiBnYktn7DjdEslqhffVme4PuBxNojI+uCeg/sn4QVLd/iogMJfDWN + uLD8326Mi/FE9cCRvFlvAiMSaebMI3zPaySsxTK7Zgj5TpEbmbHI9wIDAQABo4GnMIGkMB0GA1UdD + gQWBBSVGgvoW4MhMuzBGce29PY8vSzHFzB1BgNVHSMEbjBsgBSVGgvoW4MhMuzBGce29PY8vSzHF6 + FJpEcwRTELMAkGA1UEBhMCVVMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV + 0IFdpZGdpdHMgUHR5IEx0ZIIJAKg4VeVcIDz1MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD + ggEBAJu1rqs+anD74dbdwgd3CnqnQsQDJiEXmBhG2leaGt3ve9b/9gKaJg2pyb2NyppDe1uLqh6nN + XDuzg1oNZrPz5pJL/eCXPl7FhxhMUi04TtLf8LeNTCIWYZiFuO4pmhohHcv8kRvYR1+6SkLTC8j/T + Zerm7qvesSiTQFNapa1eNdVQ8nFwVkEtWl+JzKEM1BlRcn42sjJkijeFp7DpI7pU+PnYeiaXpRv5p + Jo8ogM1iFxN+SnfEs0EuQ7fhKIG9aHKi7bKZ7L6SyX7MDIGLeulEU6lf5D9BfXNmcMambiS0pXhL2 + QXajt96UBq8FT2KNXY8XNtR4y6MyyCzhaiZZcc8= + + + + + https://evil-corp.com + + vincent.vega@evil-corp.com + + + + + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + + + + + + + vincent.vega@evil-corp.com + + + + Vincent + + + + VEGA + + + + 123 Main St. +Suite 11 + + + + + diff --git a/test/static/keyinfo.pem b/test/static/keyinfo.pem new file mode 100644 index 00000000..5cd2aa71 --- /dev/null +++ b/test/static/keyinfo.pem @@ -0,0 +1,22 @@ +-----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----- diff --git a/test/utils-tests.spec.ts b/test/utils-tests.spec.ts index 561d4fc5..b5fe41aa 100644 --- a/test/utils-tests.spec.ts +++ b/test/utils-tests.spec.ts @@ -1,6 +1,9 @@ import * as fs from "fs"; import * as utils from "../src/utils"; import { expect } from "chai"; +import * as xmldom from "@xmldom/xmldom"; +import * as xpath from "xpath"; +import * as isDomNode from "@xmldom/is-dom-node"; describe("Utils tests", function () { describe("derToPem", function () { @@ -41,6 +44,18 @@ describe("Utils tests", function () { expect(utils.derToPem(base64String, "CERTIFICATE")).to.equal(normalizedPem); }); + it("will return a normalized PEM format when given a base64 string with line breaks and spaces at the line breaks", function () { + const xml = new xmldom.DOMParser().parseFromString( + fs.readFileSync("./test/static/keyinfo - pretty-printed.xml", "latin1"), + ); + const cert = xpath.select1(".//*[local-name(.)='X509Certificate']", xml); + isDomNode.assertIsNodeLike(cert); + + const normalizedPem = fs.readFileSync("./test/static/keyinfo.pem", "latin1"); + + expect(utils.derToPem(cert.textContent ?? "", "CERTIFICATE")).to.equal(normalizedPem); + }); + it("will throw if the DER string is not base64 encoded", function () { expect(() => utils.derToPem("not base64", "CERTIFICATE")).to.throw(); });