Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

graphene-pk11

Package Overview
Dependencies
Maintainers
1
Versions
62
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

graphene-pk11

A simple layer for interacting with PKCS #11 / PKCS11 / CryptoKI libraries in NodeJS

  • 1.0.0
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
369
decreased by-44.34%
Maintainers
1
Weekly downloads
 
Created
Source

Graphene

A simple layer for interacting with PKCS #11 / CryptoKI libraries in NodeJS

PKCS #11 (also known as CryptoKI or PKCS11) is the standard interface for interacting with hardware crypto devices such as Smart Cards and Hardware Security Modules (HSMs). It wraps the library closely, but uses attempts to look like 'node.crypto' where it makes sense.

It has been tested with :

  • SoftHSM
  • Safenet Luna HSMs
  • RuToken

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

SoftHSM

  • Install SoftHSM

    apt-get install softhsm

  • Specify where your configuration file is

    export SOFTHSM2_CONF=/etc/softhsm/softhsm.conf

  • Fix the configuation file to specify correct path to it's db

    %s:/lib\/lib/lib

  • Initialize the first slot

    softhsm2-util --init-token --slot 0 --label "My token 1"

  • The pkcs11 module you can now use can be found here:

    /usr/lib/softhsm/libsofthsm.so

Examples

Listing capabilities

var pkcs11 = require('pkcs11');
var Module = pkcs11.Module;
var Enums = pkcs11.Enums;

var lib = "/usr/local/lib/softhsm/libsofthsm2.so";

var mod = Module.load(lib, "SoftHSM");
mod.initialize();

//get slots
var slots = mod.getSlots(true);
if (slots.length > 0) {
	var slots = mod.getSlots(true);
	for (var i in slots) {
		var slot = slots[i];
		console.log("Slot #" + (+i + 1));
		console.log("\tDescription:", slot.description);
		console.log("\tSerial:", slot.serial);
		console.log("\tNeed login:", slot.needLogin);
		console.log("\tPassword(min/max): %d/%d", slot.minPassword, slot.maxPassword);
		console.log("\tIs hardware:", slot.isHardware());
		console.log("\tIs removable:", slot.isRemovable());
		console.log("\tIs initialized:", slot.isInitialized());

		console.log("\n\nMechanisms:");
		console.log("Name                       h/s/v/e/d/w/u");
		console.log("========================================");
		function b(v) {
			return v ? '+' : '-';
		};
		function s(v) {
			v = v.toString();
			for (var i = v.length; i < 27; i++) {
				v += ' ';
			}
			return v;
		};
		var mechs = slot.mechanismList;
		for (var j in mechs) {
			var mech = mechs[j];
			console.log(
				s(mech.name) +
				b(mech.isDigest()) + '/' +
				b(mech.isSign()) + '/' +
				b(mech.isVerify()) + '/' +
				b(mech.isEncrypt()) + '/' +
				b(mech.isDecrypt()) + '/' +
				b(mech.isWrap()) + '/' +
				b(mech.isUnwrap())
				);
		}
	}
}

mod.finalize();

####Output

Slot #1
        Description: Luna UHD Slot
        Serial: 486884
        Need login: true
        Password(min/max): 7/255
        Is hardware: true
        Is removable: false
        Is initialized: true


Mechanisms:
Name                       h/s/v/e/d/w/u
=========================================
RSA_PKCS_KEY_PAIR_GEN      -/-/-/-/-/-/-
RSA_PKCS                   -/+/+/+/+/+/+
SHA1_RSA_PKCS              -/+/+/-/-/-/-
RSA_PKCS_OAEP              -/-/-/+/+/+/+
RSA_X9_31_KEY_PAIR_GEN     -/-/-/-/-/-/-
SHA1_RSA_X9_31             -/+/+/-/-/-/-
RSA_PKCS_PSS               -/+/+/-/-/-/-
SHA1_RSA_PKCS_PSS          -/+/+/-/-/-/-
DSA_KEY_PAIR_GEN           -/-/-/-/-/-/-
DSA                        -/+/+/-/-/-/-
SHA224_RSA_PKCS            -/+/+/-/-/-/-

Hashing

var pkcs11 = require('pkcs11');
var Module = pkcs11.Module;

var lib = "/usr/local/lib/softhsm/libsofthsm2.so";
	
var mod = Module.load(lib, "SoftHSM");
mod.initialize();
	
//get slots
var slots = mod.getSlots(true);
if (slots.length > 0) {
	var slot = slots[0]; //get first slot;
	if (slot.isInitialized()){
		var session = slot.session;
		session.start();
	
		var digest = session.createDigest("sha1");
		digest.update("simple text 1");
		digest.update("simple text 2");
		var hash = digest.final();
		console.log("Hash SHA1:", hash.toString("hex")); //Hash SHA1: e1dc1e52e9779cd69679b3e0af87d2e288190d34 
	
		session.stop();
	}
	else{
		console.error('Slot is not initialized');
	}
}

mod.finalize();

Generating keys

AES
var pkcs11 = require('pkcs11');
var Module = pkcs11.Module;
var Enums = pkcs11.Enums;

var lib = "/usr/local/lib/softhsm/libsofthsm2.so";

var mod = Module.load(lib, "SoftHSM");
mod.initialize();

//get slots
var slots = mod.getSlots(true);
if (slots.length > 0) {
	var slot = slots[1];
	if (slot.isInitialized()) {
		var session = slot.session;
		session.start(2|4); //start session in RW mode

		session.login("1234");
		
		var k = session.generateKey("AES_KEY_GEN", {
			"class": Enums.ObjectClass.SecretKey,
			"token": true,
			"sensitive": true,
			"valueLen": 32,
			"keyType": Enums.KeyType.AES,
			"label": "My AES secret key",
			"private": true
		})
		console.log("Key.handle:", k.handle);
		console.log("Key.type:", k.getType());

		session.logout();
		session.stop();
	}
	else {
		console.error('Slot is not initialized');
	}
}

mod.finalize();
ECC
var pkcs11 = require('pkcs11');
var Module = pkcs11.Module;
var Enums = pkcs11.Enums;

var lib = "/usr/local/lib/softhsm/libsofthsm2.so";

var mod = Module.load(lib, "SoftHSM");
mod.initialize();

//get slots
var slots = mod.getSlots(true);
if (slots.length > 0) {
	var slot = slots[1];
	if (slot.isInitialized()) {
		var session = slot.session;
		session.start(2 | 4); //start session in RW mode

		session.login("1234");

		var keyPair = session.generateKeyPair(
			"EC_KEY_PAIR_GEN",
			{
				"token": true,
				"private": true,
				"verify": true,
				"wrap": false,
				"encrypt": false,
				"paramsEC": new Buffer("06082A8648CE3D030101", "hex")
			},
			{
				"token": true,
				"private": true,
				"sensitive": true,
				"decrypt": false,
				"sign": true,
				"unwrap": false,

			})
		var pubKey = keyPair.public;
		console.log("Key.handle:", pubKey.handle);
		console.log("Key.type:", Enums.KeyType.getText(pubKey.getType()));
		
		var prvKey = keyPair.private;
		console.log("Key.handle:", prvKey.handle);
		console.log("Key.type:", Enums.KeyType.getText(prvKey.getType()));

		session.logout();
		session.stop();
	}
	else {
		console.error('Slot is not initialized');
	}
}

mod.finalize();

Signing

var pkcs11 = require('pkcs11');
var Module = pkcs11.Module;
var Enums = pkcs11.Enums;

var lib = "/usr/local/lib/softhsm/libsofthsm2.so";

var mod = Module.load(lib, "SoftHSM");
mod.initialize();

//get slots
var slots = mod.getSlots(true);
if (slots.length > 0) {
	var slot = slots[1];
	if (slot.isInitialized()){
		var session = slot.session;
		session.start();
		
		session.login("1234");
		
		var objects = session.findObjects();
		
		var key = null;
		//Get first PrivateKey
		for (var i in objects){
			var object = objects[i];
			if (object.getClass() == Enums.ObjectClass.PrivateKey){
				key = object.toType(Enums.ObjectClass.PrivateKey);
				break;
			}
		}
		
		console.log("PK lable:", key.getLabel()); 			//PK lable: My key
		console.log("PK type:", Enums.KeyType.getText(key.getType()));	//PK type: RSA
		console.log("PK is Sign:", key.isSign());			//PK is Sign: true
	
		var sign = session.createSign("SHA1_RSA_PKCS", key);
		sign.update("simple text 1");
		sign.update("simple text 2");
		var signature = sign.final();
		console.log("Signature RSA-SHA1:", signature.toString("hex"));	//Signature RSA-SHA1: 6102a66dc0d97fadb5...
		
		session.logout();
		session.stop();
	}
	else{
		console.error('Slot is not initialized');
	}
}

mod.finalize();

Verifying

var pkcs11 = require('pkcs11');
var Module = pkcs11.Module;
var Enums = pkcs11.Enums;

var lib = "/usr/local/lib/softhsm/libsofthsm2.so";

var mod = Module.load(lib, "SoftHSM");
mod.initialize();

//get slots
var slots = mod.getSlots(true);
if (slots.length > 0) {
	var slot = slots[1];
	if (slot.isInitialized()){
		var session = slot.session;
		session.start();
		
		session.login("1234");
		
		var objects = session.findObjects();
		
		var key = null;
		//Get first PublicKey
		for (var i in objects){
			var object = objects[i];
			if (object.getClass() == Enums.ObjectClass.PublicKey){
				key = object.toType(Enums.ObjectClass.PublicKey);
				break;
			}
		}
		
		console.log("PubK lable:", key.getLabel()); 				//PK lable: My key
		console.log("PubK type:", Enums.KeyType.getText(key.getType()));	//PK type: RSA
		console.log("PubK is Verify:", key.isVerify());				//PK is Sign: true
	
		var verify = session.createVerify("SHA1_RSA_PKCS", key);
		verify.update("simple text 1");
		verify.update("simple text 2");
		var signature = new Buffer("6102a66dc0d97fadb53bda109b726714e0206b5a...","hex");
		var res = verify.final(signature);
		console.log("Verify RSA-SHA1:", res);					//Verify RSA-SHA1: true
		
		session.logout();
		session.stop();
	}
	else{
		console.error('Slot is not initialized');
	}
}

mod.finalize();

Encrypting

var pkcs11 = require('pkcs11');
var Module = pkcs11.Module;
var Enums = pkcs11.Enums;

var lib = "/usr/local/lib/softhsm/libsofthsm2.so";

var mod = Module.load(lib, "SoftHSM");
mod.initialize();

//get slots
var slots = mod.getSlots(true);
if (slots.length > 0) {
	var slot = slots[0]; //get slot by index
	if (slot.isInitialized()) {
		var session = slot.session;
		session.start();

		session.login("1234");

		var objects = session.findObjects();

		var key = null;
		//Get AES key
		for (var i in objects) {
			var object = objects[i];
			if (object.getClass() == Enums.ObjectClass.SecretKey) {
				var _key = object.toType(); //converts object to SecretKey 
				if (_key.getType() == Enums.KeyType.AES) {
					key = object.toType(Enums.ObjectClass.PublicKey);
					break;
				}
			}
		}

		console.log("Key lable:", key.getLabel()); 						//Key lable: test key AES
		console.log("Key type:", Enums.KeyType.getText(key.getType()));	//Key type: AES
		console.log("Key is Encrypt:", key.isEncrypt());				//Key is Encrypt: true

		var encrypt = session.createEncrypt({
			name: "AES_CBC_PAD",
			params: new Buffer([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
		}, key);
		var encMsg = new Buffer(0);
		encMsg = Buffer.concat([encMsg, encrypt.update("simple text 1")]);
		encMsg = Buffer.concat([encMsg, encrypt.update("simple text 2")]);
		encMsg = Buffer.concat([encMsg, encrypt.final()]);
		console.log("Encrypted AES_CBC_PAD:", encMsg.toString('base64'));	
		//Encrypted AES_CBC_PAD: ByPGGo2xIcGsyRZBncjmI2nLiSAOSnmKG4U1p7LJIRM=
	
		session.logout();
		session.stop();
	}
	else {
		console.error('Slot is not initialized');
	}
}

mod.finalize();

Decrypting

var pkcs11 = require('pkcs11');
var Module = pkcs11.Module;
var Enums = pkcs11.Enums;

var lib = "/usr/local/lib/softhsm/libsofthsm2.so";

var mod = Module.load(lib, "SoftHSM");
mod.initialize();

//get slots
var slots = mod.getSlots(true);
if (slots.length > 0) {
	var slot = slots[0]; //get slot by index
	if (slot.isInitialized()) {
		var session = slot.session;
		session.start();

		session.login("1234");

		var objects = session.findObjects();

		var key = null;
		//Get AES key
		for (var i in objects) {
			var object = objects[i];
			if (object.getClass() == Enums.ObjectClass.SecretKey) {
				var _key = object.toType(); //converts object to SecretKey 
				if (_key.getType() == Enums.KeyType.AES) {
					key = object.toType(Enums.ObjectClass.PublicKey);
					break;
				}
			}
		}

		console.log("Key lable:", key.getLabel()); 						//Key lable: test key AES
		console.log("Key type:", Enums.KeyType.getText(key.getType()));	//Key type: AES
		console.log("Key is Encrypt:", key.isEncrypt());				//Key is Encrypt: true

		var decrypt = session.createDecrypt({
			name: "AES_CBC_PAD",
			params: new Buffer([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
		}, key);
		var msg = new Buffer(0);
		msg = Buffer.concat([msg, decrypt.update(
			new Buffer("ByPGGo2xIcGsyRZBncjmI2nLiSAOSnmKG4U1p7LJIRM=", "base64")
			)]);
		msg = Buffer.concat([msg, decrypt.final()]);
		console.log("Decrypted AES_CBC_PAD:", msg.toString());	
		//Decrypted AES_CBC_PAD: simple text 1simple text 2

		session.logout();
		session.stop();
	}
	else {
		console.error('Slot is not initialized');
	}
}

mod.finalize();

Suitability

At this time this solution should be considered suitable for research and experimentation, further code and security review is needed before utilization in a production application.

Bug Reporting

Please report bugs either as pull requests or as issues in the issue tracker. Graphene has a full disclosure vulnerability policy. Please do NOT attempt to report any security vulnerability in this code privately to anybody.

TODO

  • Add tests to the library
  • Add additional capabilities to CLI (device initialization, file signing, file encrption, etc)

Keywords

FAQs

Package last updated on 18 Nov 2015

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc