diff --git a/src/signed-xml.ts b/src/signed-xml.ts
index 13de8fbb..8c24b5fe 100644
--- a/src/signed-xml.ts
+++ b/src/signed-xml.ts
@@ -194,7 +194,7 @@ export class SignedXml {
if (publicCertMatches.length > 0) {
x509Certs = publicCertMatches
- .map((c) => `${utils.pemToDer(c)}`)
+ .map((c) => `${utils.pemToDer(c).toString("base64")}`)
.join("");
}
diff --git a/src/utils.ts b/src/utils.ts
index 3146cc5b..4009b9c7 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -142,11 +142,18 @@ export function normalizePem(pem: string): string {
/**
* @param pem The PEM-encoded base64 certificate to strip headers from
*/
-export function pemToDer(pem: string): string {
- return pem
- .replace(/(\r\n|\r)/g, "\n")
- .replace(/-----BEGIN [A-Z\x20]{1,48}-----\n?/, "")
- .replace(/-----END [A-Z\x20]{1,48}-----\n?/, "");
+export function pemToDer(pem: string): Buffer {
+ if (!PEM_FORMAT_REGEX.test(pem.trim())) {
+ throw new Error("Invalid PEM format.");
+ }
+
+ return Buffer.from(
+ pem
+ .replace(/(\r\n|\r)/g, "")
+ .replace(/-----BEGIN [A-Z\x20]{1,48}-----\n?/, "")
+ .replace(/-----END [A-Z\x20]{1,48}-----\n?/, ""),
+ "base64",
+ );
}
/**
@@ -155,15 +162,20 @@ export function pemToDer(pem: string): string {
*/
export function derToPem(
der: string | Buffer,
- pemLabel: "CERTIFICATE" | "PRIVATE KEY" | "RSA PUBLIC KEY",
+ pemLabel?: "CERTIFICATE" | "PRIVATE KEY" | "RSA PUBLIC KEY",
): string {
- const base64Der = Buffer.isBuffer(der) ? der.toString("latin1").trim() : der.trim();
+ const base64Der = Buffer.isBuffer(der)
+ ? der.toString("base64").trim()
+ : der.replace(/(\r\n|\r)/g, "").trim();
if (PEM_FORMAT_REGEX.test(base64Der)) {
return normalizePem(base64Der);
}
if (BASE64_REGEX.test(base64Der)) {
+ if (pemLabel == null) {
+ throw new Error("PEM label is required when DER is given.");
+ }
const pem = `-----BEGIN ${pemLabel}-----\n${base64Der}\n-----END ${pemLabel}-----`;
return normalizePem(pem);
diff --git a/test/static/client_public.der b/test/static/client_public.der
new file mode 100644
index 00000000..1fe1f1b9
Binary files /dev/null and b/test/static/client_public.der differ
diff --git a/test/utils-tests.spec.ts b/test/utils-tests.spec.ts
index ab89a2f1..561d4fc5 100644
--- a/test/utils-tests.spec.ts
+++ b/test/utils-tests.spec.ts
@@ -12,7 +12,6 @@ describe("Utils tests", function () {
pemAsArray[pemAsArray.length - 1]
}`;
- // @ts-expect-error FIXME
expect(utils.derToPem(nonNormalizedPem)).to.equal(normalizedPem);
});
@@ -25,8 +24,45 @@ describe("Utils tests", function () {
});
it("will throw if the format is neither PEM nor DER", function () {
- // @ts-expect-error FIXME
expect(() => utils.derToPem("not a pem")).to.throw();
});
+
+ it("will return a normalized PEM format when given a DER Buffer", function () {
+ const normalizedPem = fs.readFileSync("./test/static/client_public.pem", "latin1");
+ const derBuffer = fs.readFileSync("./test/static/client_public.der");
+
+ expect(utils.derToPem(derBuffer, "CERTIFICATE")).to.equal(normalizedPem);
+ });
+
+ it("will return a normalized PEM format when given a base64 string with line breaks", function () {
+ const normalizedPem = fs.readFileSync("./test/static/client_public.pem", "latin1");
+ const base64String = fs.readFileSync("./test/static/client_public.der", "base64");
+
+ expect(utils.derToPem(base64String, "CERTIFICATE")).to.equal(normalizedPem);
+ });
+
+ it("will throw if the DER string is not base64 encoded", function () {
+ expect(() => utils.derToPem("not base64", "CERTIFICATE")).to.throw();
+ });
+
+ it("will throw if the PEM label is not provided", function () {
+ const derBuffer = fs.readFileSync("./test/static/client_public.der");
+ expect(() => utils.derToPem(derBuffer)).to.throw();
+ });
+ });
+
+ describe("pemToDer", function () {
+ it("will return a Buffer of binary DER when given a normalized PEM format", function () {
+ const pem = fs.readFileSync("./test/static/client_public.pem", "latin1");
+ const derBuffer = fs.readFileSync("./test/static/client_public.der");
+
+ const result = utils.pemToDer(pem);
+ expect(result).to.be.instanceOf(Buffer);
+ expect(result).to.deep.equal(derBuffer);
+ });
+
+ it("will throw if the format is not PEM", function () {
+ expect(() => utils.pemToDer("not a pem")).to.throw();
+ });
});
});