### Install xmldom Parser
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Install the `xmldom` package, which is used in the examples for parsing XML documents.
```shell
npm install @xmldom/xmldom
```
--------------------------------
### Signed XML with KeyInfo Element
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
This example shows the structure of a signature that includes a KeyInfo element containing an X509Certificate, which is generated when the publicCert and getKeyInfoContent properties are set.
```xml
...[signature info removed]...
vhWzpQyIYuncHUZV9W...[long base64 removed]...
MIIGYjCCBJagACCBN...[long base64 removed]...
```
--------------------------------
### Generated Signed XML Structure
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
This is an example of the XML document after being signed. It includes the original content and the added signature block.
```xml
Harry Potter
cdiS43aFDQMnb3X8yaIUej3+z9Q=
vhWzpQyIYuncHUZV9W...[long base64 removed]...
```
--------------------------------
### Run Project Tests
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Execute the project's test suite using npm. This command utilizes Mocha and Chai for testing.
```shell
npm test
```
--------------------------------
### Customize SignedXml Constructor Options
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Pass options to the `SignedXml` constructor to customize the verification process. `publicCert` is used for verification, and `getCertFromKeyInfo` can be customized to extract the certificate from the KeyInfo element.
```javascript
new SignedXml({
publicCert: client_public_pem,
getCertFromKeyInfo: () => null,
});
```
--------------------------------
### Import Modules for XML Signing
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Import necessary modules from the xml-crypto library and the file system for signing operations.
```javascript
var SignedXml = require("xml-crypto").SignedXml,
fs = require("fs");
```
--------------------------------
### Implement Custom Canonicalization Algorithm
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Implement a custom canonicalization algorithm, similar to a transformation, but applied to SignedInfo. The process method should return the canonical string representation of the node.
```javascript
function MyCanonicalization() {
/*given a node (from the xmldom module) return its canonical representation (as string)*/
this.process = function (node) {
//you should apply your transformation before returning
return "< x/>";
};
this.getAlgorithmName = function () {
return "http://myCanonicalization";
};
}
```
--------------------------------
### Sign XML with Custom Algorithms
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Configure and compute the signature for an XML document using custom algorithms for signature, canonicalization, transformation, and digest. Ensure private key and certificate are loaded.
```javascript
function signXml(xml, xpath, key, dest) {
var options = {
publicCert: fs.readFileSync("my_public_cert.pem", "latin1"),
privateKey: fs.readFileSync(key),
/*configure the signature object to use the custom algorithms*/
signatureAlgorithm: "http://mySignatureAlgorithm",
canonicalizationAlgorithm: "http://MyCanonicalization",
};
var sig = new SignedXml(options);
sig.addReference({
xpath: "//*[local-name(.)='x']",
transforms: ["http://MyTransformation"],
digestAlgorithm: "http://myDigestAlgorithm",
});
sig.addReference({
xpath,
transforms: ["http://MyTransformation"],
digestAlgorithm: "http://myDigestAlgorithm",
});
sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
sig.signatureAlgorithm = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
sig.computeSignature(xml);
fs.writeFileSync(dest, sig.getSignedXml());
}
var xml = "" + "" + "Harry Potter" + "";
("");
signXml(xml, "//*[local-name(.)='book']", "client.pem", "result.xml");
```
--------------------------------
### SignedXml Constructor
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
The SignedXml constructor initializes an object for signing and verifying XML documents. It accepts an optional options object to configure its behavior.
```APIDOC
## SignedXml Constructor
### Description
Initializes a SignedXml object for signing and verifying XML documents.
### Parameters
#### Options
- **idMode** (string) - Optional - Default `null`. If 'wssecurity', creates/validates IDs with the ws-security namespace.
- **idAttribute** (string) - Optional - Default `Id`, `ID`, or `id`. The name of the attribute containing the element's ID.
- **privateKey** (string or Buffer) - Optional - Default `null`. The private key for signing.
- **publicCert** (string or Buffer) - Optional - Default `null`. The public certificate for verification.
- **signatureAlgorithm** (string) - Optional. The signature algorithm to use.
- **canonicalizationAlgorithm** (string) - Optional - Default `undefined`. The canonicalization algorithm to use.
- **inclusiveNamespacesPrefixList** (string) - Optional - Default `null`. A list of namespace prefixes to include during canonicalization.
- **implicitTransforms** (string[]) - Optional - Default `[]`. A list of implicit transforms for verification.
- **keyInfoAttributes** (object) - Optional - Default `{}`. Attributes to add to the KeyInfo node.
- **getKeyInfoContent** (function) - Optional - Default `SignedXml.getKeyInfoContent`. Function to get KeyInfo node content.
- **getCertFromKeyInfo** (function) - Optional - Default `noop`. Function to get certificate from KeyInfo node.
```
--------------------------------
### Verify XML Signature
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Load an XML document, parse it, select the signature element, and use `SignedXml` to verify the signature against the provided XML. Ensure the `publicCert` is loaded from a file.
```javascript
var select = require("xml-crypto").xpath,
dom = require("@xmldom/xmldom").DOMParser,
SignedXml = require("xml-crypto").SignedXml,
fs = require("fs");
var xml = fs.readFileSync("signed.xml").toString();
var doc = new dom().parseFromString(xml);
// DO NOT attempt to parse whatever data object you have here in `doc`
// and then use it to verify the signature. This can lead to security issues.
// i.e. BAD: parseAssertion(doc),
// good: see below
var signature = select(
doc,
"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']",
)[0];
var sig = new SignedXml({ publicCert: fs.readFileSync("client_public.pem") });
sig.loadSignature(signature);
try {
var res = sig.checkSignature(xml);
} catch (ex) {
console.log(ex);
}
```
--------------------------------
### Sign XML Document with xml-crypto
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Use this code to sign an XML document. Ensure you have a 'client.pem' file for the private key. The output will be saved to 'signed.xml'.
```javascript
var SignedXml = require("xml-crypto").SignedXml,
fs = require("fs");
var xml = "" + "" + "Harry Potter" + "" + "";
var sig = new SignedXml({ privateKey: fs.readFileSync("client.pem") });
sig.addReference({
xpath: "//*[local-name(.)='book']",
digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1",
transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"],
});
sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
sig.signatureAlgorithm = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
sig.computeSignature(xml);
fs.writeFileSync("signed.xml", sig.getSignedXml());
```
--------------------------------
### Convert PFX Certificate to PEM Format
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Use the openssl command-line tool to convert a .pfx certificate file to the PEM format, which is required for signing operations.
```shell
openssl pkcs12 -in c:\certs\yourcert.pfx -out c:\certs\cag.pem
```
--------------------------------
### Implement Custom Signature Algorithm
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Create a custom signature algorithm by providing a getSignature method for signing the SignedInfo and a getAlgorithmName method. This is used for custom signing processes.
```javascript
function MySignatureAlgorithm() {
/*sign the given SignedInfo using the key. return base64 signature value*/
this.getSignature = function (signedInfo, privateKey) {
return "signature of signedInfo as base64...";
};
this.getAlgorithmName = function () {
return "http://mySigningAlgorithm";
};
}
```
--------------------------------
### Sign XML with Signature Prefix
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Compute a signature for an XML document and add a specified prefix to the signature element using the `prefix` option in `computeSignature`.
```javascript
var SignedXml = require("xml-crypto").SignedXml,
fs = require("fs");
var xml = "" + "" + "Harry Potter" + "" + "";
var sig = new SignedXml({ privateKey: fs.readFileSync("client.pem") });
sig.addReference({
xpath: "//*[local-name(.)='book']",
digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1",
transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"],
});
sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
sig.signatureAlgorithm = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
sig.computeSignature(xml, {
prefix: "ds",
});
```
--------------------------------
### Implement Custom Transformation Algorithm
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Define a custom transformation algorithm by implementing the process and getAlgorithmName methods. The process method should return the canonical representation of a node after transformation.
```javascript
function MyTransformation() {
/*given a node (from the xmldom module) return its canonical representation (as string)*/
this.process = function (node) {
//you should apply your transformation before returning
return node.toString();
};
this.getAlgorithmName = function () {
return "http://myTransformation";
};
}
```
--------------------------------
### Implement Custom Asynchronous Signature Algorithm
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Create a custom asynchronous signature algorithm for signing documents with external services or HSMs. The `getSignature` method should perform asynchronous operations and call back with the result.
```javascript
function AsyncSignatureAlgorithm() {
this.getSignature = function (signedInfo, privateKey, callback) {
var signer = crypto.createSign("RSA-SHA1");
signer.update(signedInfo);
var res = signer.sign(privateKey, "base64");
//Do some asynchronous things here
callback(null, res);
};
this.getAlgorithmName = function () {
return "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
};
}
var sig = new SignedXml({ signatureAlgorithm: "http://asyncSignatureAlgorithm" });
sig.SignatureAlgorithms["http://asyncSignatureAlgorithm"] = AsyncSignatureAlgorithm;
sig.signatureAlgorithm = "http://asyncSignatureAlgorithm";
sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
sig.computeSignature(xml, opts, function (err) {
var signedResponse = sig.getSignedXml();
});
```
--------------------------------
### Verifying XML Documents
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Methods for loading a signature and checking its validity against an XML document.
```APIDOC
## loadSignature
### Description
Loads the signature for verification.
### Method
`loadSignature(signatureXml)`
### Parameters
#### `signatureXml` (string or object)
- A string or node object (like an [xmldom](https://github.com/xmldom/xmldom) node) containing the XML representation of the signature.
```
```APIDOC
## checkSignature
### Description
Validates the given XML document against the loaded signature.
### Method
`checkSignature(xml)`
### Parameters
#### `xml` (string)
- A string containing the XML document to validate.
```
--------------------------------
### Implement Custom Digest Algorithm
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Define a custom digest algorithm by implementing the getHash and getAlgorithmName methods. Use this when a non-standard hashing method is required.
```javascript
function MyDigest() {
this.getHash = function (xml) {
return "the base64 hash representation of the given xml string";
};
this.getAlgorithmName = function () {
return "http://myDigestAlgorithm";
};
}
```
--------------------------------
### Register Custom Algorithms
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Register the custom transformation, canonicalization, digest, and signature algorithms with the SignedXml object to make them available for use.
```javascript
/*register all the custom algorithms*/
signedXml.CanonicalizationAlgorithms["http://MyTransformation"] = MyTransformation;
signedXml.CanonicalizationAlgorithms["http://MyCanonicalization"] = MyCanonicalization;
signedXml.HashAlgorithms["http://myDigestAlgorithm"] = MyDigest;
signedXml.SignatureAlgorithms["http://mySigningAlgorithm"] = MySignatureAlgorithm;
```
--------------------------------
### Signing XML Documents
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Methods for adding references and computing the signature of an XML document.
```APIDOC
## addReference
### Description
Adds a reference to an XML element for signing.
### Method
`addReference({ xpath, transforms, digestAlgorithm, id, type })`
### Parameters
#### Reference Object
- **xpath** (string) - Required - A XPath expression referencing a XML element.
- **transforms** (string[]) - Optional - An array of [transform algorithms](#canonicalization-and-transformation-algorithms).
- **digestAlgorithm** (string) - Required - One of the supported [hashing algorithms](#hashing-algorithms).
- **id** (string) - Optional - An `Id` attribute to add to the reference element.
- **type** (string) - Optional - The `Type` attribute to add to the reference element (represented as a URI).
```
```APIDOC
## computeSignature
### Description
Computes the signature of the given XML document.
### Method
`computeSignature(xml, [options])`
### Parameters
#### `xml` (string)
- A string containing a XML document.
#### `options` (object)
- **prefix** (string) - Optional - Adds this value as a prefix for the generated signature tags.
- **attrs** (object) - Optional - A hash of attributes and values to add to the signature root node.
- **location** (object) - Optional - Customize the location of the signature. Should contain `reference` (XPath expression) and `action` ('append', 'prepend', 'before', 'after').
- **existingPrefixes** (object) - Optional - A hash of prefixes and namespaces that already exist in the XML.
```
```APIDOC
## getSignedXml
### Description
Returns the original XML document with the signature included. Must be called after `computeSignature`.
### Method
`getSignedXml()`
```
```APIDOC
## getSignatureXml
### Description
Returns only the signature part of the XML. Must be called after `computeSignature`.
### Method
`getSignatureXml()`
```
```APIDOC
## getOriginalXmlWithIds
### Description
Returns the original XML with Id attributes added to relevant elements, required for validation. Must be called after `computeSignature`.
### Method
`getOriginalXmlWithIds()`
```
--------------------------------
### Specify Implicit Transforms for Verification
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
If signature verification fails, try specifying common implicit transforms in the `SignedXml` constructor options. This can help resolve issues caused by hidden transformations during the signing process.
```javascript
var options = {
implicitTransforms: ["http://www.w3.org/TR/2001/REC-xml-c14n-20010315"],
publicCert: fs.readFileSync("client_public.pem"),
};
var sig = new SignedXml(options);
sig.loadSignature(signature);
var res = sig.checkSignature(xml);
```
--------------------------------
### Specify Signature Location in XML
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Control the placement of the signature within the XML document by using the `location` option in `computeSignature`. Options include appending, prepending, or inserting before/after a specific node.
```javascript
const SignedXml = require("xml-crypto").SignedXml;
const fs = require("fs");
const xml = "" + "" + "Harry Potter" + "" + "";
const sig = new SignedXml({ privateKey: fs.readFileSync("client.pem") });
sig.addReference({
xpath: "//*[local-name(.)='book']",
digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1",
transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"],
});
sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
sig.signatureAlgorithm = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
sig.computeSignature(xml, {
location: { reference: "//*[local-name(.)='book']", action: "after" }, // This will place the signature after the book element
});
```
--------------------------------
### Extract Authenticated Data After Verification
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
After successful signature verification, use `getSignedReferences()` to obtain the data that was actually signed. Parse this data to ensure its integrity before use. Avoid using the `.getReferences()` API as it can be insecure.
```javascript
if (!res) {
throw "Invalid Signature";
}
// good: The XML Signature has been verified, meaning some subset of XML is verified.
var signedBytes = sig.getSignedReferences();
var authenticatedDoc = new dom().parseFromString(signedBytes[0]); // Take the first signed reference
// It is now safe to load SAML, obtain the assertion XML, or do whatever else is needed.
// Be sure to only use authenticated data.
let signedAssertionNode = extractAssertion(authenticatedDoc);
let parsedAssertion = parseAssertion(signedAssertionNode);
return parsedAssertion; // This the correctly verified signed Assertion
// BAD example: DO not use the .getReferences() API.
```
--------------------------------
### Add Custom Objects to XML Signature
Source: https://github.com/node-saml/xml-crypto/blob/master/README.md
Use the `objects` option when creating a SignedXml instance to include custom data within the signature. Ensure the object's ID is correctly referenced in the signature.
```javascript
const SignedXml = require("xml-crypto").SignedXml;
const fs = require("fs");
const xml = "" + "" + "Harry Potter" + "" + "";
const sig = new SignedXml({
privateKey: fs.readFileSync("client.pem"),
canonicalizationAlgorithm: "http://www.w3.org/2001/10/xml-exc-c14n#",
signatureAlgorithm: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
objects: [
{
content: "Test data in Object",
attributes: {
Id: "Object1",
MimeType: "text/xml",
},
},
],
});
// Add a reference to the Object element
sig.addReference({
xpath: "//*[@Id='Object1']",
digestAlgorithm: "http://www.w3.org/2001/04/xmlenc#sha256",
transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"],
});
sig.computeSignature(xml);
fs.writeFileSync("signed.xml", sig.getSignedXml());
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.