SkillAgentSearch skills...

Pkcs11js

A Node.js implementation of the PKCS#11 2.40 interface

Install / Use

/learn @PeculiarVentures/Pkcs11js
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

PKCS11js

license test Coverage Status npm version

NPM

PKCS11js is a package for direct interaction with the PKCS#11 API, the standard interface for interacting with hardware crypto devices such as Smart Cards and Hardware Security Modules (HSMs). It was developed to the PKCS#11 2.40 specification and has been tested with a variety of devices.

Versioning Note:

  • Version 1.x was implemented using the nan module, which allowed the package to be built for older versions of Node.js.
  • Starting from version 2.x, the module has been rewritten to use napi. As a result, the minimum required Node.js version is now v18.

For most use cases, we recommend our package Graphene, which provides a simplistic Object Oriented interface for interacting with PKCS#11 devices.

This was developed to the PKCS#11 2.40 specification. It should be easy enough to extend it for any new versions at a later date.

It has been tested with :

NOTE: For testing purposes it may be easier to work with SoftHSM2 which is a software implementation of PKCS#11 based on OpenSSL or Botan.

Installation

$ npm install pkcs11js

Documentation

https://peculiarventures.github.io/pkcs11js/

Install SoftHSM2

Examples

Example #1

var pkcs11js = require("pkcs11js");

var pkcs11 = new pkcs11js.PKCS11();
pkcs11.load("/usr/local/lib/softhsm/libsofthsm2.so");

pkcs11.C_Initialize();

try {
    // Getting info about PKCS11 Module
    var module_info = pkcs11.C_GetInfo();

    // Getting list of slots
    var slots = pkcs11.C_GetSlotList(true);
    var slot = slots[0];

    // Getting info about slot
    var slot_info = pkcs11.C_GetSlotInfo(slot);
    // Getting info about token
    var token_info = pkcs11.C_GetTokenInfo(slot);

    // Getting info about Mechanism
    var mechs = pkcs11.C_GetMechanismList(slot);
    var mech_info = pkcs11.C_GetMechanismInfo(slot, mechs[0]);

    var session = pkcs11.C_OpenSession(slot, pkcs11js.CKF_RW_SESSION | pkcs11js.CKF_SERIAL_SESSION);

    // Getting info about Session
    var info = pkcs11.C_GetSessionInfo(session);
    pkcs11.C_Login(session, 1, "password");

    /**
     * Your app code here
     */
    
    pkcs11.C_Logout(session);
    pkcs11.C_CloseSession(session);
}
catch(e){
    console.error(e);
}
finally {
    pkcs11.C_Finalize();
}

Example #2

Generating secret key using AES mechanism

var template = [
    { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_SECRET_KEY },
    { type: pkcs11js.CKA_TOKEN, value: false },
    { type: pkcs11js.CKA_LABEL, value: "My AES Key" },
    { type: pkcs11js.CKA_VALUE_LEN, value: 256 / 8 },
    { type: pkcs11js.CKA_ENCRYPT, value: true },
    { type: pkcs11js.CKA_DECRYPT, value: true },
];
var key = pkcs11.C_GenerateKey(session, { mechanism: pkcs11js.CKM_AES_KEY_GEN }, template);

Example #3

Generating key pair using RSA-PKCS1 mechanism

var publicKeyTemplate = [
    { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PUBLIC_KEY },
    { type: pkcs11js.CKA_TOKEN, value: false },
    { type: pkcs11js.CKA_LABEL, value: "My RSA Public Key" },
    { type: pkcs11js.CKA_PUBLIC_EXPONENT, value: new Buffer([1, 0, 1]) },
    { type: pkcs11js.CKA_MODULUS_BITS, value: 2048 },
    { type: pkcs11js.CKA_VERIFY, value: true }
];
var privateKeyTemplate = [
    { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PRIVATE_KEY },
    { type: pkcs11js.CKA_TOKEN, value: false },
    { type: pkcs11js.CKA_LABEL, value: "My RSA Private Key" },
    { type: pkcs11js.CKA_SIGN, value: true },
];
var keys = pkcs11.C_GenerateKeyPair(session, { mechanism: pkcs11js.CKM_RSA_PKCS_KEY_PAIR_GEN }, publicKeyTemplate, privateKeyTemplate);

Example #4

Generating key pair using ECDSA mechanism

var publicKeyTemplate = [
    { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PUBLIC_KEY },
    { type: pkcs11js.CKA_TOKEN, value: false },
    { type: pkcs11js.CKA_LABEL, value: "My EC Public Key" },
    { type: pkcs11js.CKA_EC_PARAMS, value: new Buffer("06082A8648CE3D030107", "hex") }, // secp256r1
];
var privateKeyTemplate = [
    { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PRIVATE_KEY },
    { type: pkcs11js.CKA_TOKEN, value: false },
    { type: pkcs11js.CKA_LABEL, value: "My EC Private Key" },
    { type: pkcs11js.CKA_DERIVE, value: true },
];
var keys = pkcs11.C_GenerateKeyPair(session, { mechanism: pkcs11js.CKM_EC_KEY_PAIR_GEN }, publicKeyTemplate, privateKeyTemplate);

Example #4

Working with Object

var nObject = pkcs11.C_CreateObject(session, [
    { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_DATA },
    { type: pkcs11js.CKA_TOKEN, value: false },
    { type: pkcs11js.CKA_PRIVATE, value: false },
    { type: pkcs11js.CKA_LABEL, value: "My custom data" },
]);

// Updating label of Object
pkcs11.C_SetAttributeValue(session, nObject, [{ type: pkcs11js.CKA_LABEL, value: "My custom data!!!" }]);

// Getting attribute value
var label = pkcs11.C_GetAttributeValue(session, nObject, [
    { type: pkcs11js.CKA_LABEL },
    { type: pkcs11js.CKA_TOKEN }
]);
console.log(label[0].value.toString()); // My custom data!!!
console.log(!!label[1].value[0]); // false

// Copying Object
var cObject = pkcs11.C_CopyObject(session, nObject, [
    { type: pkcs11js.CKA_CLASS},
    { type: pkcs11js.CKA_TOKEN},
    { type: pkcs11js.CKA_PRIVATE},
    { type: pkcs11js.CKA_LABEL},
]);

// Removing Object
pkcs11.C_DestroyObject(session, cObject);

Example #4

Searching objects

NOTE: If template is not set for C_FindObjectsInit, then C_FindObjects returns all objects from slot

pkcs11.C_FindObjectsInit(session, [{ type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_DATA }]);
var hObject = pkcs11.C_FindObjects(session);
while (hObject) {
    var attrs = pkcs11.C_GetAttributeValue(session, hObject, [
        { type: pkcs11js.CKA_CLASS },
        { type: pkcs11js.CKA_TOKEN },
        { type: pkcs11js.CKA_LABEL }
    ]);
    // Output info for objects from token only
    if (attrs[1].value[0]){
        console.log(`Object #${hObject}: ${attrs[2].value.toString()}`);
    }
    hObject = pkcs11.C_FindObjects(session);
}
pkcs11.C_FindObjectsFinal(session);

Example #5

Generating random values

var random = pkcs11.C_GenerateRandom(session, new Buffer(20));
console.log(random.toString("hex"));

or

var random = new Buffer(20);
pkcs11.C_GenerateRandom(session, random);
console.log(random.toString("hex"));

Example #6

Digest

pkcs11.C_DigestInit(_session, { mechanism: pkcs11js.CKM_SHA256 });

pkcs11.C_DigestUpdate(session, new Buffer("Incoming message 1"));
pkcs11.C_DigestUpdate(session, new Buffer("Incoming message N"));

var digest = pkcs11.C_DigestFinal(_session, Buffer(256 / 8));

console.log(digest.toString("hex"));

Example #7

Signing data

pkcs11.C_SignInit(session, { mechanism: pkcs11js.CKM_SHA256_RSA_PKCS }, keys.privateKey);

pkcs11.C_SignUpdate(session, new Buffer("Incoming message 1"));
pkcs11.C_SignUpdate(session, new Buffer("Incoming message N"));

var signature = pkcs11.C_SignFinal(session, Buffer(256));

Verifying data

pkcs11.C_VerifyInit(session, { mechanism: pkcs11js.CKM_SHA256_RSA_PKCS }, keys.publicKey);

pkcs11.C_VerifyUpdate(session, new Buffer("Incoming message 1"));
pkcs11.C_VerifyUpdate(session, new Buffer("Incoming message N"));

var verify = pkcs11.C_VerifyFinal(session, signature);

Example #8

Encrypting data with AES-CBC mechanism

var cbc_param = pkcs11.C_GenerateRandom(new Buffer(16));

pkcs11.C_EncryptInit(
    session,
    {
        mechanism: pkcs11js.CKM_AES_CBC,
        parameter: cbc_param
    },
    secretKey
);

var enc = new Buffer(0);
enc = Buffer.concat([enc, pkcs11.C_EncryptUpdate(session, new Buffer("Incoming data 1"), new Buffer(16))]);
enc = Buffer.concat([enc, pkcs11.C_EncryptUpdate(session, new Buffer("Incoming data N"), new Buffer(16))]);
enc = Buffer.concat([enc, pkcs11.C_EncryptFinal(session, new Buffer(16))]);

console.log(enc.toString("hex"));

Decrypting data with AES-CBC mechanism

pkcs11.C_DecryptInit(
    session,
    {
        mechanism: pkcs11js.CKM_AES_CBC,
        parameter: cbc_param
    },
    secretKey
);

var dec = new Buffer(0);
dec = Buffer.concat([dec, pkcs11.C_DecryptUpdate(session, enc, new Buffer(32))]);
dec = Buffer.concat([dec, pkcs11.C_DecryptFinal(session, new Buffer(16))]);

console.log(dec.toString());

Example #9

Deriving key with ECDH mechanism

// Receive public data from EC public key
var attrs = pkcs11.C_GetAttributeValue(session, publicKeyEC, [{ type: pkcs11js.CKA_EC_POINT }])
var ec = attrs[0].value;

var derivedKey = pkcs11.C_DeriveK

Related Skills

View on GitHub
GitHub Stars121
CategoryDevelopment
Updated1mo ago
Forks33

Languages

C++

Security Score

100/100

Audited on Feb 9, 2026

No findings