2.5.1 • Published 1 year ago

xmldsigjs v2.5.1

Weekly downloads
512
License
MIT
Repository
github
Last release
1 year ago

XMLDSIGjs

license CircleCI Coverage Status npm version

NPM

XMLDSIG is short for "XML Digital Signature". This library aims to provide an implementation of XMLDSIG in Typescript/Javascript that uses Web Crypto for cryptographic operations so it can be used both in browsers and in Node.js (when used with a polyfill like node-webcrypto-ossl or node-webcrypto-p11).

INSTALLING

npm install xmldsigjs

The npm module has build folder with the following files:

NameSizeDescription
index.js105 KbCJS module with external modules
index.es.js100 KbES module with external modules
xmldsig.js872 KbIIFE bundle module
xmldsig.min.js398 Kbminified IIFE bundled module

COMPATABILITY

CRYPTOGRAPHIC ALGORITHM SUPPORT

SHA1SHA2-256SHA2-384SHA2-512
RSASSA-PKCS1-v1_5XXXX
RSA-PSSXXXX
ECDSAXXXX
HMACXXXX

CANONICALIZATION ALGORITHM SUPPORT

  • XmlDsigC14NTransform
  • XmlDsigC14NWithCommentsTransform
  • XmlDsigExcC14NTransform
  • XmlDsigExcC14NWithCommentsTransform
  • XmlDsigEnvelopedSignatureTransform
  • XmlDsigBase64Transform

PLATFORM SUPPORT

XMLDSIGjs works with any browser that supports Web Crypto. Since node does not have Web Crypto you will need a polyfill on this platform, for this reason the npm package includes node-webcrypto-ossl; browsers do not need this dependency and in those cases though it will be installed it will be ignored.

If you need to use a Hardware Security Module we have also created a polyfill for Web Crypto that supports PKCS #11. Our polyfill for this is node-webcrypto-p11.

To use node-webcrypto-ossl you need to specify you want to use it, that looks like this:

var xmldsigjs = require("xmldsigjs");
var WebCrypto = require("node-webcrypto-ossl");

xmldsigjs.Application.setEngine("OpenSSL", new WebCrypto());

The node-webcrypto-p11 polyfill will work the same way. The only difference is that you have to specify the details about your PKCS#11 device when you instansiate it:

var xmldsigjs = require("xmldsigjs");
var WebCrypto = require("node-webcrypto-p11");

xmldsigjs.Application.setEngine("PKCS11", new WebCrypto({
    library: "/path/to/pkcs11.so",
	name: "Name of PKCS11 lib",
	slot: 0,
    sessionFlags: 4, // SERIAL_SESSION
	pin: "token pin"
}));

WARNING

Using XMLDSIG is a bit like running with scissors so use it cautiously. That said it is needed for interoperability with a number of systems, for this reason, we have done this implementation.

Usage

Sign

SignedXml.Sign(algorithm: Algorithm, key: CryptoKey, data: Document, options?: OptionsSign): PromiseLike<Signature>;

Parameters

NameDescription
algorithmSigning Algorithm
keySigning Key
dataXML document which must be signed
optionsAdditional options

Options

interface OptionsSign {
    /**
     * Id of Signature
     */
    id?: string 
    /**
     * Public key for KeyInfo block
     */
    keyValue?: CryptoKey;
    /**
     * List of X509 Certificates
     */
    x509?: string[];
    /**
     * List of Reference
     * Default is Reference with hash alg SHA-256 and exc-c14n transform  
     */
    references?: OptionsSignReference[];
}

interface OptionsSignReference {
    /**
     * Id of Reference
     */
    id?: string;
    uri?: string;
    /**
     * Hash algorithm
     */
    hash: AlgorithmIdentifier;
    /**
     * List of transforms
     */
    transforms?: OptionsSignTransform[];
}

type OptionsSignTransform = "enveloped" | "c14n" | "exc-c14n" | "c14n-com" | "exc-c14n-com" | "base64";

Verify

Verify(key?: CryptoKey): PromiseLike<boolean>;

Parameters

NameDescription
keyVerifying Key. Optional. If key not set it looks for keys in KeyInfo element of Signature.

EXAMPLES

For Sign/Verify operations you will need to use a Web Crypto CryptoKey. You can see examples for an example of how to do that.

Initiating in NodeJs

"use strict";

const WebCrypto = require("node-webcrypto-ossl");
const crypto = new WebCrypto();
const XmlDSigJs = require("xmldsigjs");

XmlDSigJs.Application.setEngine("OpenSSL", crypto);

Initiating in Browser

Get the latest version form unpkg.com/xmldsigjs

<script src="https://unpkg.com/xmldsigjs@<version>/build/xmldsig.js"></script>

Creating a XMLDSIG Signature

"use strict";

let signature = new XmlDSigJs.SignedXml();

signature.Sign(                                  // Signing document
    { name: "RSASSA-PKCS1-v1_5" },                        // algorithm 
    keys.privateKey,                                      // key 
    XmlDSigJs.Parse(xml),                                 // document
    {                                                     // options
        keyValue: keys.publicKey,
        references: [
            { hash: "SHA-512", transforms: ["enveloped", "c14n"] },
        ]
    })
    .then(() => {
        console.log(signature.toString());       // <xml> document with signature
    })
    .catch(e => console.log(e));

Checking a XMLDSIG Signature

let doc = XmlDSigJs.Parse(xml);
let signature = doc.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature");

let signedXml = new XmlDSigJs.SignedXml(doc);
signedXml.LoadXml(signature[0]);

signedXml.Verify()
    .then(res => {
        console.log("Signature status:", res);       // Signature status: true
    })
    .catch(e => console.log(e));

Browser Verify Example

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8"/>
    <title>XMLDSIGjs Verify Sample</title>
</head>

<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.7.0/polyfill.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/asmCrypto/2.3.2/asmcrypto.all.es5.min.js"></script>
    <script src="https://cdn.rawgit.com/indutny/elliptic/master/dist/elliptic.min.js"></script>
    <script src="https://unpkg.com/webcrypto-liner@1.1.2/build/webcrypto-liner.shim.min.js"></script>
    <script src="https://unpkg.com/xmldsigjs@2.0.27/build/xmldsig.js"></script>
    <script type="text/javascript">
        fetch("signature.xml")
        .then(function(response) {
            return response.text();
        }).then(function(body) {
            var xmlString = body;

            var signedDocument = XmlDSigJs.Parse(xmlString);
            var xmlSignature = signedDocument.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature");

            var signedXml = new XmlDSigJs.SignedXml(signedDocument);
            signedXml.LoadXml(xmlSignature[0]);
            signedXml.Verify()
            .then(function (res) {
                console.log((res ? "Valid" : "Invalid") + " signature");
            })
            .catch(function (e) {
                console.error(e);
            });
        })
    </script>
</body>
</html>

TESTING

In NodeJS:

npm test

In the browser

To run the browser test you need to run a test server, from the test directory run:

npm start

And the then browse to `http://localhost:3000'.

THANKS AND ACKNOWLEDGEMENT

This project takes inspiration (style, approach, design and code) from both the Mono System.Security.Cryptography.Xml implementation as well as xml-crypto.

RELATED

2.5.1

1 year ago

2.5.0

2 years ago

2.4.1

2 years ago

2.3.0

2 years ago

2.2.0

2 years ago

2.4.0

2 years ago

2.1.5

3 years ago

2.1.4

3 years ago

2.1.3

3 years ago

2.1.2

3 years ago

2.1.1

4 years ago

2.1.0

4 years ago

2.0.31

4 years ago

2.0.29

4 years ago

2.0.30

4 years ago

2.0.29-next.0

4 years ago

2.0.28

4 years ago

2.0.28-next.0

4 years ago

2.0.27

4 years ago

2.0.26

5 years ago

2.0.25

5 years ago

2.0.24

5 years ago

2.0.23

5 years ago

2.0.22

6 years ago

2.0.21

6 years ago

2.0.20

6 years ago

2.0.19

6 years ago

2.0.18

6 years ago

2.0.17

6 years ago

2.0.16

6 years ago

2.0.15

6 years ago

2.0.14

6 years ago

2.0.13

6 years ago

2.0.12

6 years ago

2.0.11

6 years ago

2.0.10

7 years ago

2.0.9

7 years ago

2.0.8

7 years ago

2.0.7

7 years ago

2.0.6

7 years ago

2.0.5

7 years ago

2.0.4

7 years ago

2.0.3

7 years ago

2.0.2

7 years ago

2.0.1

7 years ago