I'm use xml-crypto node.js package to sign xml. When I use signed xml document in saml 2.0 I am getting an error: org.opensaml.xmlsec.signature.support.SignatureException: Signature cryptographic validation not successful My metthod full code:
import { Injectable, Optional } from "@nestjs/common";
import { SignedXml } from "xml-crypto";
import * as p12 from "p12-pem";
async getAuthRequest(): Promise<any> {
const date = new Date();
const xml = `<?xml version="1.0" encoding="utf-8" ?>
<saml2p:AuthnRequest Destination="${this.config.url}SingleSignOnService" AssertionConsumerServiceURL="https://url/artifactResolves" IssueInstant="${date.toISOString()}" Version="2.0" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:eidas="http://eidas.europa.eu/saml-extensions">
<saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://izzinakarte.pl</saml2:Issuer>
<saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"/>
<saml2p:RequestedAuthnContext Comparison="minimum">
<saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://eidas.europa.eu/LoA/high</saml2:AuthnContextClassRef>
</saml2p:RequestedAuthnContext>
</saml2p:AuthnRequest>`;
const {pemKey, pemCertificate, commonName} = p12.getPemFromP12("certs/sign.p12", this.config.signPassword);
const sign = new SignedXml();
sign.addReference(
"//*[local-name(.)='AuthnRequest']",
[
"http://www.w3.org/2000/09/xmldsig#enveloped-signature",
"http://www.w3.org/2001/10/xml-exc-c14n#",
],
"http://www.w3.org/2001/04/xmlenc#sha256"
);
sign.signingKey = pemKey
.replace("-----BEGIN RSA PRIVATE KEY-----", "-----BEGIN RSA PRIVATE KEY-----\n")
.replace("-----END RSA PRIVATE KEY-----", "\n-----END RSA PRIVATE KEY-----")
// @ts-ignore
sign.keyInfoProvider = new KeyInfoProvider(pemCertificate);
sign.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
sign.signatureAlgorithm =
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
sign.computeSignature(xml, {
prefix: "ds",
location: { reference: "//*[local-name(.)='Issuer']", action: "after" },
});
const signedXml = sign.getSignedXml().replace("Id=", "ID=");
const buff = Buffer.from(signedXml);
const base64data = buff.toString("base64");
return base64data;
}
Problem solved. I had to explicitly insert the identifier so that _0 would not be inserted.
<saml2p:AuthnRequest ID="ID-${Guid.raw()}"