Skip to content
Node.js library for creating and consuming JSON, JCS, JSF and JEF
JavaScript
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
build
doc
lib
test
.gitattributes
.gitignore
.project
JS.xml
README.md
demo.js
democert.js
demohmac.js
demojson.js
index.js
package.json

README.md

JSF and JEF for "node.js"

JSF (JSON Signature Format) specification: https://cyberphone.github.io/doc/security/jsf.html
JEF (JSON Encryption Format) specification: https://cyberphone.github.io/doc/security/jef.html

CURRENTLY ONLY FOR INTERNAL USE!!!

Installation

There is no npm yet but you can test this code anyway by downloading the zip https://github.com/cyberphone/node-webpki.org/archive/master.zip to a free directory and then perform three steps:

C:\node-webpki.org-master>mkdir node_modules
C:\node-webpki.org-master>mkdir node_modules\webpki.org
C:\node-webpki.org-master>copy package.json node_modules\webpki.org

Then you should be able to run the supplied demo and test programs:

C:\node-webpki.org-master>node democert.js
{"statement":"Hello signed world!", etc etc etc}
Validation success=true

Create a signed object

'use strict';

const Fs = require('fs');

const Keys = require('webpki.org').Keys;
const Jsf = require('webpki.org').Jsf;
const JsonUtil = require('webpki.org').JsonUtil;

function readPrivateKey(path) {
  return Keys.createPrivateKeyFromPem(Fs.readFileSync(__dirname + '/test/' + path));
}

// Load a private key in PKCS #8/PEM format
const privateKey = readPrivateKey('p256privatekey.pem');

// Initiate the signer
var signer = new Jsf.Signer(privateKey);

// Create an object to sign
var jsonObject = {'statement':'Hello signed world!'};

// Perform signing
var signedObject = signer.sign(jsonObject);

// Print it on the console as "pretty" (but legal) JSON.
console.log(JsonUtil.prettyPrint(signedObject));

Resulting JSON string

{
  "statement": "Hello signed world!",
  "signature": {
    "algorithm": "ES256",
    "publicKey": {
      "kty": "EC",
      "crv": "P-256",
      "x": "censDzcMEkgiePz6DXB7cDuwFemshAFR90UNVQFCg8Q",
      "y": "xq8rze6ewG0-eVcSF72J77gKiD0IHnzpwHaU7t6nVeY"
    },
    "value": "9JV3WcUU5SmV0v3mVXZubOpRE5bgjOVaPFBnw6ZcRMN8A7bYHt8U7F9qYVd9ZDiSDZRPEhCDSGnDeB6VZ7wnVA"
  }
}

Validate a signature

// Now we could verify the signed object we just created

function readPublicKey(path) {
  return Keys.createPublicKeyFromPem(Fs.readFileSync(__dirname + '/test/' + path));
}

// Load a matching public key
const publicKey = readPublicKey('p256publickey.pem');

// Create a verifier object
var verifier = new Jsf.Verifier();

// Call decoding.  This will check that the signature is technically correct
var result = verifier.decodeSignature(signedObject);

// Now check if the anticipated key was used as well
result.verifyPublicKey(publicKey);

// If we got here all is good...
console.log('Validation successful!');

Using Certificates

Creating signatures with certificate paths is almost identical to signatures only using public keys. You simply need to add the path.

'use strict';

const Fs = require('fs');

const Keys     = require('webpki.org').Keys;
const Jsf      = require('webpki.org').Jsf;
const JsonUtil = require('webpki.org').JsonUtil;

// Load private key and certificate path
const keyData = Fs.readFileSync(__dirname + '/test/mybank-cert-and-key-p256.pem');
const privateKey = Keys.createPrivateKeyFromPem(keyData);
const certificatePath = Keys.createCertificatesFromPem(keyData);

// Initiate the signer
var signer = new Jsf.Signer(privateKey);

// Indicate that we want to include a certificate path
signer.setCertificatePath(certificatePath, true);

// Create an object to sign
var jsonObject = {'statement':'Hello signed world!'};

// Perform signing
var signedJavaScript = signer.sign(jsonObject);

// Print it on the console as "pretty" (but legal) JSON.
console.log(JsonUtil.prettyPrint(signedJavaScript));

This sample would generate the following JSON:

{
  "statement": "Hello signed world!",
  "signature": {
    "algorithm": "ES256",
    "signerCertificate": {
      "issuer": "CN=Payment Network Sub CA3,C=EU",
      "serialNumber": "1441094164079",
      "subject": "CN=mybank.com,2.5.4.5=#130434353031,C=FR"
    },
    "certificatePath": [
      "MIIBtTCCAVmgAwIBAgIGAU-H595vMAwGCCqGSM49BAMCBQAwLzELMAkGA1UEBhMCRVUxIDAeBgNVBAMTF1BheW1lbnQgTmV0d29yayBTdWIgQ0EzMB4XDTE0MDEwMTAwMDAwMFoXDTIwMDcxMDA5NTk1OVowMTELMAkGA1UEBhMCRlIxDTALBgNVBAUTBDQ1MDExEzARBgNVBAMTCm15YmFuay5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjhSNHJyRmQi5U-r7WkNns0D6b1n1gQybglCvyXgIA2RCSJXJKHZrw37giKmGqX-4cXU3x__zOQXN1U48VAwNvo10wWzAJBgNVHRMEAjAAMA4GA1UdDwEB_wQEAwIHgDAdBgNVHQ4EFgQUOdV3H3r6TufkQh-dqhcXMrjUY2kwHwYDVR0jBBgwFoAUy0fdXq1oJ6GFAJo10qx609KDARAwDAYIKoZIzj0EAwIFAANIADBFAiEAluqzuTTzVBG74AoALaWRsRn9QALg2N6C3sIlztm6sPoCID1ZnGnTrhz-CodxuGvg7fkOVfdffdSuEdyhQXemGtT4",
      "MIIDcjCCAVqgAwIBAgIBAzANBgkqhkiG9w0BAQ0FADAwMQswCQYDVQQGEwJVUzEhMB8GA1UEAxMYUGF5bWVudCBOZXR3b3JrIFJvb3QgQ0ExMB4XDTEyMDcxMDEwMDAwMFoXDTI1MDcxMDA5NTk1OVowLzELMAkGA1UEBhMCRVUxIDAeBgNVBAMTF1BheW1lbnQgTmV0d29yayBTdWIgQ0EzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEcX8CYrYFoQhPbTci93W5qyCx0i0H-FvmXIvH5XNBlnNLfPkRacqn0PRFNn4Z4o3BVxI3x5yob9C7FqpKslcCgKNjMGEwDwYDVR0TAQH_BAUwAwEB_zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMtH3V6taCehhQCaNdKsetPSgwEQMB8GA1UdIwQYMBaAFELvwS_Fk7IfHMWJeu-yhGdM-5EiMA0GCSqGSIb3DQEBDQUAA4ICAQBNQdIOSU2fB5JjCO9Q0mCfOxDXFihMKSiOanAJ_r2rxGN7Uprw32JPsJnQhuxbrwmniKgCmBVD6Jak4GtHSLVvJPjpf_Pe7pUbyMb6iNNeV3SmJvsHoE2m5WdSGxjIPxK4NOBv3Mm3Ib1_kxyVceegHEHRUk5IXyQUNV1sUsxIypELjC8bAIvnMj_J1FlP8nsfehbibT3XH04uvX9dgNGexpz8BDLa0fEpLzrKoyMtUbSwg88_WsdPnkvp1fhiwCF9GpIHwsXi3Nv-Wdgdyn-hKFQe6sP2FmsPDiI2qWqX7fEs0VN5Uo2oI5Q2T6673JiZnkycXYLNIRpc06KSTcs8B45u5NMAyvLx3l4S8My-HK4nfiqbF3TPVGJkq4aXAAZnhVcQTrO71tQ0BJMibKjz6sylBEnhlFQs3ICcesaGVXV3JVbwtf_OkAUUUduYWOmUZU5ng3vNJV0ofqfvoNcBlVsrWpFNqImy2-icUxiad_8--ortiq4WG594Ap52CqXt7K8UcZaMLDAj2COOmo1gy9iUjzgyzSqnYye2Gqr72ts5jd8B8wkM1rM0JDM6DvCyJgHVvc8VTNE7Mt2Mu9XsofQkdLdDgrPuo6AV88g1BGk7cY0FJMJFoBAlrj98A4KslbeGBV7AUGuzvS-w1VA6dRH6_5Fv2eSHXW6pzA_D8Q"
    ],
    "value": "dBnkOuspGDc63aSWkXnXFPsdd2w8EpKl-01FbhO2v-oqVZ4JHUtHWP76qX04DqUJJWKy8Kw47jmKpAwkET2O0w"
  }
}

Validation of Certificate Paths

Validation requires that you provide a collection of CA certificates.

// Now we could verify the signed object we just created

// Load trust store
const trustedCAs = Keys.createCertificatesFromPem(Fs.readFileSync(__dirname + '/test/payment-network-ca.pem'));

// Create a verifier object
var verifier = new Jsf.Verifier();

// Call decoding.  This will check that the signature is technically correct
var result = verifier.decodeSignature(signedJavaScript);

// Now check if the certificate path is trusted
console.log('Validation success=' + result.verifyTrust(trustedCAs));

HMAC Signatures

'use strict';

const Jsf      = require('webpki.org').Jsf;
const JsonUtil = require('webpki.org').JsonUtil;

// Define a suitable secret key
var secretKey = new Buffer('F4C74F3398C49CF46D93EC9818832661A40BAE4D204D75503614102074346909', 'hex');

// Initiate the signer with key and algorithm.  Finally, add an (optional) keyId
var signer = new Jsf.Signer(secretKey, 'HS256').setKeyId('mykey');

// Create an object to sign
var jsonObject = {'statement':'Hello signed world!'};

// Perform signing
var signedJavaScript = signer.sign(jsonObject);

// Print it on the console as "pretty" (but legal) JSON.
console.log(JsonUtil.prettyPrint(signedJavaScript));

// Now we could verify the signed object we just created

// Create a verifier object
var verifier = new Jsf.Verifier();

// Call decoding.  This will check that the signature is technically correct
var result = verifier.decodeSignature(signedJavaScript);

// Now check the result
console.log('Validation success=' + result.verifyHmac(secretKey));

And here is the expected result:

{
  "statement": "Hello signed world!",
  "signature": {
    "algorithm": "HS256",
    "keyId": "mykey",
    "value": "IcC43Ecr11NPF01n6pj540OYvpVeUp3-wyxJ_cY_Yf4"
  }
}
You can’t perform that action at this time.