Comments (10)
xmldsigjs
works in nodejs and browser. For nodejs you need crypto engine which implements WebCrypto API.
Here is simple code you can try
Install dependencies
npm install node-webcrypto-ossl xmldsigjs
Init key and cert files.
NOTE: files must be in DER format. WebCrypto allows to import object from DER or JWK formats. If you have PEM you have to convert it or update JS to do it from app.
openssl genrsa -out key.pem
openssl pkcs8 -topk8 -inform PEM -outform DER -in key.pem -out key.der -nocrypt
openssl rsa -in key.pem -pubout -outform DER -out pubkey.der
openssl req -x509 -key key.pem -outform DER -out cert.der -days 365
index.js
// @ts-check
const fs = require("fs");
const xmldsigjs = require("xmldsigjs");
const OSSLCrypto = require("node-webcrypto-ossl");
const crypto = new OSSLCrypto();
// Set crypto for XmlDSig (it uses browser's crypto by default);
xmldsigjs.Application.setEngine("OpenSSL", crypto);
function checkFile(filename) {
if (!fs.existsSync(filename)) {
throw new Error(`File '${filename}' not found`);
}
}
// Loads private key from DER file
function loadPrivateKey(filename, alg) {
return Promise.resolve()
.then(() => {
checkFile(filename);
const der = fs.readFileSync(filename);
return crypto.subtle.importKey("pkcs8", der, alg, false, ["sign"]);
});
}
// Loads public key from DER file
function loadPublicKey(filename, alg) {
return Promise.resolve()
.then(() => {
checkFile(filename);
const der = fs.readFileSync(filename);
return crypto.subtle.importKey("spki", der, alg, true, ["verify"]);
});
}
// Loads certificate from DER file and returns it in BASE64
function loadCert(filename) {
return Promise.resolve()
.then(() => {
checkFile(filename);
const der = fs.readFileSync(filename);
return der.toString("base64");
});
}
// Signs xml document and adds public key and x509 certificate to it
function signXml(alg, privateKey, publicKey, xml, x509) {
return Promise.resolve()
.then(() => {
let signature = new xmldsigjs.SignedXml();
return signature.Sign( // Signing document
alg, // algorithm
privateKey, // key
xmldsigjs.Parse(xml), // document
{ // options
keyValue: publicKey,
references: [
{ hash: "SHA-512", transforms: ["enveloped", "c14n"] },
],
x509: [x509],
})
.then(() => {
return signature.toString()
})
})
}
// Main
(() => {
const alg = {
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-256",
};
let privateKey, publicKey, certificate;
return Promise.resolve()
.then(() => {
// Get private key
return loadPrivateKey("key.der", alg)
.then((key) => {
privateKey = key;
})
})
.then(() => {
// Get public key
return loadPublicKey("pubkey.der", alg)
.then((key) => {
publicKey = key;
})
})
.then(() => {
// get certificate
return loadCert("cert.der")
.then((cert) => {
certificate = cert;
})
})
.then(() => {
// Sign document
return signXml(
alg,
privateKey,
publicKey,
"<root><child>Some text</child></root>",
certificate
)
.then((xmlString) => {
console.log(xmlString);
})
})
})()
.catch((err) => {
console.error(err);
});
run app
node index > signed.xml
You can check your signed xml online on aleksey.com
from xmldsigjs.
Thanks for the prompt response. I am able to generate signedxml but it has default prefix which I don't want. Also, I want to add 'X509SubjectName' under 'X509Data' node. I am building it for a 3rd party which only accepts in a specific format. Please provide guidance.
from xmldsigjs.
Xmldsigjs API supports must support this. I'll update example a bit later
from xmldsigjs.
Does above comment mean that it doesn't support these functionality as of now?
from xmldsigjs.
It supports. I can't update code from phone
from xmldsigjs.
No, he just needs to find time to update the sample
from xmldsigjs.
Great. Awaiting the update from @microshine.
from xmldsigjs.
I updated above code a bit
// Loads certificate from DER file
function loadCert(filename) {
return Promise.resolve()
.then(() => {
checkFile(filename);
const der = fs.readFileSync(filename);
return new xmldsigjs.X509Certificate(der);
});
}
// Signs xml document and adds public key and x509 certificate to it
function signXml(alg, privateKey, publicKey, xml, x509) {
return Promise.resolve()
.then(() => {
let signature = new xmldsigjs.SignedXml();
// Add X509Data
const X509Data = new xmldsigjs.KeyInfoX509Data()
X509Data.AddSubjectName(x509.Subject);
X509Data.AddCertificate(x509);
X509Data.AddIssuerSerial(x509.Issuer, x509.SerialNumber);
signature.XmlSignature.KeyInfo.Add(X509Data);
return signature.Sign( // Signing document
alg, // algorithm
privateKey, // key
xmldsigjs.Parse(xml), // document
{ // options
keyValue: publicKey,
references: [
{ hash: "SHA-512", transforms: ["enveloped", "c14n"] },
],
})
.then(() => {
return signature.toString()
})
})
}
This allows to get X509Data like
<ds:X509Data>
<ds:X509IssuerSerial>
<ds:X509IssuerName>C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=My cert</ds:X509IssuerName>
<ds:X509SerialNumber>14245677082242946981</ds:X509SerialNumber>
</ds:X509IssuerSerial>
<ds:X509SubjectName>C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=My cert</ds:X509SubjectName>
<ds:X509Certificate>MIIDgTCCAmmgAwIBAgIJAMWyz9RYA5elMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEDAOBgNVBAMMB015IGNlcnQwHhcNMTcwNzExMTIyNzIwWhcNMTgwNzExMTIyNzIwWjBXMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRAwDgYDVQQDDAdNeSBjZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw6gvnGXHmvaF8J+PxeGpzBBAglWI9rYeUuvYa0NEgaK62qyM7tk/5YotMoxUlLnsbppG5ttajyA23Q72oVHUyo/tez1ZRfRKl+VOhAL7aiLm/jH4QwnJ6pQVzFWz2KY94Nja1vqfpnSLpLv8s065jgCNH5llL4QBlR15a+NUWXJIccEFmr9J+lC6ymbbbNrqBk2QFSEwNiUpp8LOTzO/Sk8JFnbpT5/Lnif1OxQBQm9JUnjR42TL9rCh51iEJJEp3+8yZxEKD6lOP5SyH2DqfbET6kcw5f0EDigcm87R+qoz+3tcH1GCGIlkdKnE5Iw9cKopQRkSHHz3sRYG3I43mwIDAQABo1AwTjAdBgNVHQ4EFgQUvxWd0AuVuqtO/6yu54rlSLBFs2gwHwYDVR0jBBgwFoAUvxWd0AuVuqtO/6yu54rlSLBFs2gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAoXQhlJ3GC+NoRamL7kLvHCLtVOIN7Cpg41Xp/zUONhs6iap5yTmsa0TVi6pWbnOei5H0lgZFu1Yh6cAAspK9DQwtqEMNb3Cmsy+65Z61EL41QtC0lm2NLVtQo7FtsPiGmor80TsUaKWTyDv5luKePMvGXSFQ6d5K+g6AQmNV21l1AYXIxZfq9hTsV2p8gHkX7pHzs6orzC6kkbMalzRc5cadwkaTu7jqdJd+b3PRPde+rP7jSBDnLgo2vPzLok9FlFEf17WZPbisSPcsyBXY/sVDez8m/KIRnwEj4Fbi22KXCtjaWnnO6xcC1fTYXQus4QLFPcfnNqKIQ8r1ciMrwg==</ds:X509Certificate>
</ds:X509Data>
But prefix changing has a problem
from xmldsigjs.
Hi @microshine,
I generated the desired output using the following code but it has 3 problem: -
- Fails Signature Verification
- XML Header is missing
- Reference Tag is missing URI
Can you help me fix errors?
Thanks
// @ts-check
const fs = require("fs");
const xmldsigjs = require("xmldsigjs");
const OSSLCrypto = require("node-webcrypto-ossl");
const crypto = new OSSLCrypto();
xmldsigjs.Signature.prefix = "";
xmldsigjs.DigestMethod.prefix = "";
xmldsigjs.CanonicalizationMethod.prefix = "";
xmldsigjs.KeyInfo.prefix = "";
xmldsigjs.Transform.prefix = "";
xmldsigjs.Transforms.prefix = "";
xmldsigjs.Reference.prefix = "";
xmldsigjs.References.prefix = "";
xmldsigjs.SignedInfo.prefix = "";
xmldsigjs.SignatureMethod.prefix = "";
xmldsigjs.Signature.items.SignatureValue.prefix = "";
xmldsigjs.Reference.items.DigestValue.prefix = ""
xmldsigjs.KeyInfoX509Data.prefix = "";
// Set crypto for XmlDSig (it uses browser's crypto by default);
xmldsigjs.Application.setEngine("OpenSSL", crypto);
function checkFile(filename) {
if (!fs.existsSync(filename)) {
throw new Error(`File '${filename}' not found`);
}
}
// Loads private key from DER file
function loadPrivateKey(filename, alg) {
return Promise.resolve()
.then(() => {
checkFile(filename);
const der = fs.readFileSync(filename);
return crypto.subtle.importKey("pkcs8", der, alg, false, ["sign"]);
});
}
// Loads public key from DER file
function loadPublicKey(filename, alg) {
return Promise.resolve()
.then(() => {
checkFile(filename);
const der = fs.readFileSync(filename);
return crypto.subtle.importKey("spki", der, alg, true, ["verify"]);
});
}
// Loads certificate from DER file and returns it in BASE64
function loadCert(filename) {
return Promise.resolve()
.then(() => {
checkFile(filename);
const der = fs.readFileSync(filename);
return new xmldsigjs.X509Certificate(der);
});
}
// Signs xml document and adds public key and x509 certificate to it
function signXml(alg, privateKey, publicKey, xml, x509) {
return Promise.resolve()
.then(() => {
let signature = new xmldsigjs.SignedXml();
// Add x509 certificate
const X509Data = new xmldsigjs.KeyInfoX509Data()
X509Data.AddSubjectName(x509.Subject);
X509Data.AddCertificate(x509);
signature.XmlSignature.KeyInfo.Add(X509Data);
return signature.Sign( // Signing document
alg, // algorithm
privateKey, // key
xmldsigjs.Parse(xml), // document
{ // options
references: [
{ hash: "SHA-1", transforms: ["enveloped"] },
]
})
.then(() => {
return signature.toString()
})
})
}
// Main
(() => {
const alg = {
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-1",
};
let privateKey, publicKey, certificate;
return Promise.resolve()
.then(() => {
// Get private key
return loadPrivateKey("key.der", alg)
.then((key) => {
privateKey = key;
})
})
.then(() => {
// Get public key
return loadPublicKey("pubkey.der", alg)
.then((key) => {
publicKey = key;
})
})
.then(() => {
// get certificate
return loadCert("cert.der")
.then((cert) => {
certificate = cert;
})
})
.then(() => {
// Sign document
return signXml(
alg,
privateKey,
publicKey,
'<?xml version="1.0" encoding="UTF-8"?><OTP aspId="UTII-900" ver="1.0" ts="2017-07-11T18:37:17.692" uid="789456123654" txn="f37f4548-1dbd-4489-ba44-a9b02573dffb"></OTP>',
certificate
)
.then((xmlString) => {
console.log(xmlString);
})
})
})()
.catch((err) => {
console.error(err);
});
Desired Output
<?xml version="1.0" encoding="UTF-8"?>
<OTP aspId="UTII-900" ts="2016-05-16T12:13:58.315" txn="050b6a62-841d-42b5-8e63-6e034ea0f75f" uid="789456123654" ver="1.0">
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>MUakshYMaksbPAXKpv1o7zK3c1A=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>
YcOJfkczUdlfvs3bN7dzuNLCwDhAGavnDwR6O1EeB0ENJQKkaHHV882wp8kPF+Y2B7Snu/UeKDJ7p42kd0fng1jHRKJj7ltN0h5S2rH7FxrCV9v/MAnzxjilb6juVdaVIwaBq+jPCDo7sXGUvwOXF+rQT2bcbwfhQHHvMo4OMfoV3576c/XAec4Bn0rLKv40qf8sls8/i9OZyMfIIJ+cNPprTyIyId0kidER+d8pb8cwQd3rgTTKe0emgQgbUCWt07GcLK8HjdE8CgHLISAWLR3FyHqM+XeGv7Xc+YBaY1ca7DKs4Oe/uMPizkO/PIps4wgEGbuXafVPDEuTN/Vurw==
</SignatureValue>
<KeyInfo>
<X509Data>
<X509SubjectName>
ST=MAHARASHTRA,2.5.4.17=#0c06343030363134,2.5.4.5=#134038393832373944353736343135453130364537344430334532393542433338423041453335463733413142323334393746463145444244464432384338413631,CN=VICHARE SANDEEP,OU=INFORMATION TECHNOLOGY,O=UTI INFRASTRUCTURE TECHNOLOGY AND SERVICES LIMITED,C=IN
</X509SubjectName>
<X509Certificate>
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
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</OTP>
Actual Output
<OTP aspId="UTII-900" ver="1.0" ts="2017-07-11T18:37:17.692" uid="789456123654" txn="f37f4548-1dbd-4489-ba44-a9b02573dffb">
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference>
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>nf9oQPVj6b1eBotzjL9zY5Zjnkw=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>
wihjNbjPFnf6fniQ6qjWfNIUwpNdxDepHHGuj4c1RHOEntd1GdmSw/CCG4eO8IIWv76hgpVzpVw965kn/W0x/Q==
</SignatureValue>
<KeyInfo>
<X509Data>
<X509SubjectName>
C=IN, ST=Uttar-Pradesh, L=Noida, O=Tarsiers Technologies Pvt Ltd, CN=Shobha Singhal, [email protected]
</X509SubjectName>
<X509Certificate>
MIIDNzCCAuGgAwIBAgIJAP4+kHY1VqGRMA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJJTjEWMBQGA1UECBMNVXR0YXItUHJhZGVzaDEOMAwGA1UEBxMFTm9pZGExJjAkBgNVBAoTHVRhcnNpZXJzIFRlY2hub2xvZ2llcyBQdnQgTHRkMRcwFQYDVQQDEw5TaG9iaGEgU2luZ2hhbDEjMCEGCSqGSIb3DQEJARYUY29udGFjdHNAdGFyc2llcnMuaW4wHhcNMTcwNzExMTMzMDUyWhcNMTgwNzExMTMzMDUyWjCBmzELMAkGA1UEBhMCSU4xFjAUBgNVBAgTDVV0dGFyLVByYWRlc2gxDjAMBgNVBAcTBU5vaWRhMSYwJAYDVQQKEx1UYXJzaWVycyBUZWNobm9sb2dpZXMgUHZ0IEx0ZDEXMBUGA1UEAxMOU2hvYmhhIFNpbmdoYWwxIzAhBgkqhkiG9w0BCQEWFGNvbnRhY3RzQHRhcnNpZXJzLmluMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAOJ6bgnfYXGXQUiYhIxoR1+nq/wR9wTMR6mEKY9bi/vGTO6tq37jhiWr5kqhJaOiBREcaTSfuhLBqZ75+Aix7u8CAwEAAaOCAQQwggEAMB0GA1UdDgQWBBRkAYe+ek9zFoHUtqGfmQSdCzCgqDCB0AYDVR0jBIHIMIHFgBRkAYe+ek9zFoHUtqGfmQSdCzCgqKGBoaSBnjCBmzELMAkGA1UEBhMCSU4xFjAUBgNVBAgTDVV0dGFyLVByYWRlc2gxDjAMBgNVBAcTBU5vaWRhMSYwJAYDVQQKEx1UYXJzaWVycyBUZWNobm9sb2dpZXMgUHZ0IEx0ZDEXMBUGA1UEAxMOU2hvYmhhIFNpbmdoYWwxIzAhBgkqhkiG9w0BCQEWFGNvbnRhY3RzQHRhcnNpZXJzLmluggkA/j6QdjVWoZEwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAANBACavhhBL+KawZGPe90JbDXgGPZMV9KIbd4YrOL9vvHDCBK7z1itE/TWwHHnx+JnLWsEQx8RgmGMsrHeViQhOY7o=
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</OTP>
from xmldsigjs.
@alphanso
I updates script.
- updates prefix for xmldsig
- adds URI to Reference
// @ts-check
const fs = require("fs");
const xmldsigjs = require("xmldsigjs");
const OSSLCrypto = require("node-webcrypto-ossl");
const crypto = new OSSLCrypto();
// Set crypto for XmlDSig (it uses browser's crypto by default);
xmldsigjs.Application.setEngine("OpenSSL", crypto);
function hackXmlDSigPrefix(prefix) {
xmldsigjs.XmlSignature.DefaultPrefix = prefix;
for (const key in xmldsigjs) {
const object = xmldsigjs[key];
if (object.namespaceURI === xmldsigjs.XmlSignature.NamespaceURI) {
object.prefix = prefix;
}
for (const i in object.items) {
const item = object.items[i];
if (item.namespaceURI === xmldsigjs.XmlSignature.NamespaceURI) {
item.prefix = prefix;
}
}
}
}
function checkFile(filename) {
if (!fs.existsSync(filename)) {
throw new Error(`File '${filename}' not found`);
}
}
// Loads private key from DER file
function loadPrivateKey(filename, alg) {
return Promise.resolve()
.then(() => {
checkFile(filename);
const der = fs.readFileSync(filename);
return crypto.subtle.importKey("pkcs8", der, alg, false, ["sign"]);
});
}
// Loads public key from DER file
function loadPublicKey(filename, alg) {
return Promise.resolve()
.then(() => {
checkFile(filename);
const der = fs.readFileSync(filename);
return crypto.subtle.importKey("spki", der, alg, true, ["verify"]);
});
}
// Loads certificate from DER file
function loadCert(filename) {
return Promise.resolve()
.then(() => {
checkFile(filename);
const der = fs.readFileSync(filename);
return new xmldsigjs.X509Certificate(der);
});
}
// Signs xml document and adds public key and x509 certificate to it
function signXml(alg, privateKey, publicKey, xml, x509) {
return Promise.resolve()
.then(() => {
let signature = new xmldsigjs.SignedXml();
// Add X509Data
const X509Data = new xmldsigjs.KeyInfoX509Data()
X509Data.AddSubjectName(x509.Subject);
X509Data.AddCertificate(x509);
X509Data.AddIssuerSerial(x509.Issuer, x509.SerialNumber);
signature.XmlSignature.KeyInfo.Add(X509Data);
return signature.Sign( // Signing document
alg, // algorithm
privateKey, // key
xmldsigjs.Parse(xml), // document
{ // options
keyValue: publicKey,
references: [
{ hash: "SHA-512", transforms: ["enveloped", "c14n"], uri: `id("root-id")` },
],
})
.then(() => {
return signature.toString()
})
})
}
// Main
(() => {
const alg = {
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-256",
};
let privateKey, publicKey, certificate;
return Promise.resolve()
.then(() => {
hackXmlDSigPrefix("dsig");
// Get private key
return loadPrivateKey("key.der", alg)
.then((key) => {
privateKey = key;
})
})
.then(() => {
// Get public key
return loadPublicKey("pubkey.der", alg)
.then((key) => {
publicKey = key;
})
})
.then(() => {
// get certificate
return loadCert("cert.der")
.then((cert) => {
certificate = cert;
})
})
.then(() => {
// Sign document
return signXml(
alg,
privateKey,
publicKey,
`<root id="root-id"><child>Some text</child></root>`,
certificate
)
.then((xmlString) => {
// output signed xml
console.log(xmlString);
})
})
})()
.catch((err) => {
console.error(err);
});
<root id="root-id">
<child>Some text</child>
<dsig:Signature
xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
<dsig:SignedInfo>
<dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<dsig:Reference URI="id("root-id")">
<dsig:Transforms>
<dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<dsig:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/>
<dsig:DigestValue>ury5ZNtzrhhk0tlpM/dUmeth3VFoftfJxd9winqbTye1aWfJMhadkMCEr8P/HWodeTwWTyCLw85ZbAENNi6v9w==</dsig:DigestValue>
</dsig:Reference>
</dsig:SignedInfo>
<dsig:SignatureValue>fEVRdKkXLLyuqqWQRjgRsJsK+W+qzm2dBfyBD7in/YfX9BSURKxy7GhrYU/6BCu5lnWGbGxClnX53n0XDllDnZGRN8TOHtbt6Svg5fnKCo6MTnwMuyx5M4L4Y8keYAWPOQJQaQuDP+yBC1bv+jmciakiNwh0F3J9vQ7N2Ja+YQIKJ3w8ZjKrgh60NTT3BOJFEqkHaR4511XtjURCR5NrAnWg890Og3lpPv9bBlEnpH++tq/TBuohlESkSqU/rhLvuNhQ3SLYckQiOJdOMguUMd2U6oG0Z4VWqiNJgq4N8S8eTHHiI27VM9AQKtCp3iL4kSekiIccEJZqmfkwVpwc8g==</dsig:SignatureValue>
<dsig:KeyInfo>
<dsig:X509Data>
<dsig:X509IssuerSerial>
<dsig:X509IssuerName>C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=My cert</dsig:X509IssuerName>
<dsig:X509SerialNumber>14245677082242946981</dsig:X509SerialNumber>
</dsig:X509IssuerSerial>
<dsig:X509SubjectName>C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=My cert</dsig:X509SubjectName>
<dsig:X509Certificate>MIIDgTCCAmmgAwIBAgIJAMWyz9RYA5elMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEDAOBgNVBAMMB015IGNlcnQwHhcNMTcwNzExMTIyNzIwWhcNMTgwNzExMTIyNzIwWjBXMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRAwDgYDVQQDDAdNeSBjZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw6gvnGXHmvaF8J+PxeGpzBBAglWI9rYeUuvYa0NEgaK62qyM7tk/5YotMoxUlLnsbppG5ttajyA23Q72oVHUyo/tez1ZRfRKl+VOhAL7aiLm/jH4QwnJ6pQVzFWz2KY94Nja1vqfpnSLpLv8s065jgCNH5llL4QBlR15a+NUWXJIccEFmr9J+lC6ymbbbNrqBk2QFSEwNiUpp8LOTzO/Sk8JFnbpT5/Lnif1OxQBQm9JUnjR42TL9rCh51iEJJEp3+8yZxEKD6lOP5SyH2DqfbET6kcw5f0EDigcm87R+qoz+3tcH1GCGIlkdKnE5Iw9cKopQRkSHHz3sRYG3I43mwIDAQABo1AwTjAdBgNVHQ4EFgQUvxWd0AuVuqtO/6yu54rlSLBFs2gwHwYDVR0jBBgwFoAUvxWd0AuVuqtO/6yu54rlSLBFs2gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAoXQhlJ3GC+NoRamL7kLvHCLtVOIN7Cpg41Xp/zUONhs6iap5yTmsa0TVi6pWbnOei5H0lgZFu1Yh6cAAspK9DQwtqEMNb3Cmsy+65Z61EL41QtC0lm2NLVtQo7FtsPiGmor80TsUaKWTyDv5luKePMvGXSFQ6d5K+g6AQmNV21l1AYXIxZfq9hTsV2p8gHkX7pHzs6orzC6kkbMalzRc5cadwkaTu7jqdJd+b3PRPde+rP7jSBDnLgo2vPzLok9FlFEf17WZPbisSPcsyBXY/sVDez8m/KIRnwEj4Fbi22KXCtjaWnnO6xcC1fTYXQus4QLFPcfnNqKIQ8r1ciMrwg==</dsig:X509Certificate>
</dsig:X509Data>
<dsig:KeyValue>
<dsig:RSAKeyValue>
<dsig:Modulus>w6gvnGXHmvaF8J+PxeGpzBBAglWI9rYeUuvYa0NEgaK62qyM7tk/5YotMoxUlLnsbppG5ttajyA23Q72oVHUyo/tez1ZRfRKl+VOhAL7aiLm/jH4QwnJ6pQVzFWz2KY94Nja1vqfpnSLpLv8s065jgCNH5llL4QBlR15a+NUWXJIccEFmr9J+lC6ymbbbNrqBk2QFSEwNiUpp8LOTzO/Sk8JFnbpT5/Lnif1OxQBQm9JUnjR42TL9rCh51iEJJEp3+8yZxEKD6lOP5SyH2DqfbET6kcw5f0EDigcm87R+qoz+3tcH1GCGIlkdKnE5Iw9cKopQRkSHHz3sRYG3I43mw==</dsig:Modulus>
<dsig:Exponent>AQAB</dsig:Exponent>
</dsig:RSAKeyValue>
</dsig:KeyValue>
</dsig:KeyInfo>
</dsig:Signature>
</root>
from xmldsigjs.
Related Issues (20)
- How Can I verify a file with a External Certificate file (.cer) HOT 2
- XML error HOT 1
- canonicalization result incorrect if default `xmlns` presents and text node contains `&` HOT 7
- XmlDsigEnvelopedSignatureTransform shouldn't remove all found Signatures HOT 3
- Uncaught ReferenceError: regeneratorRuntime is not defined - non-functional in browser HOT 3
- problems compiling with typescript HOT 5
- One <Transform> and c14n HOT 10
- Namespace prefix on root creates invalid signatures HOT 7
- Signature\KeyInfo\KeyName support
- How to verify when the signature is in a different file than the content? HOT 14
- Support for multiple content references to external files HOT 3
- How to set CanonicalizationMethod or default ? HOT 2
- Cannot apply transform to SignedProperties
- Cannot `Verify` signature with transforms applied HOT 5
- How to setEngine for OpenSSL without node-webcrypto-ossl
- Update dependencies HOT 1
- Need to update dependencies
- modify default reference HOT 1
- Question about ApplyTransformers
- Example for Enveloping signature
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from xmldsigjs.