{"id":18601596,"url":"https://github.com/peculiarventures/pkcs11js","last_synced_at":"2025-04-04T10:07:52.176Z","repository":{"id":9988875,"uuid":"64019786","full_name":"PeculiarVentures/pkcs11js","owner":"PeculiarVentures","description":"A Node.js implementation of the PKCS#11 2.40 interface","archived":false,"fork":false,"pushed_at":"2024-02-01T00:59:37.000Z","size":1612,"stargazers_count":103,"open_issues_count":17,"forks_count":33,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-04-14T09:58:18.437Z","etag":null,"topics":["cryptography","hsms","pkcs","pkcs11","softhsm2"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PeculiarVentures.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"PeculiarVentures","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2016-07-23T14:26:56.000Z","updated_at":"2024-05-22T13:53:27.703Z","dependencies_parsed_at":"2024-01-15T22:33:54.910Z","dependency_job_id":"34d6d2d4-9210-48b4-8ef6-47ab0da0da21","html_url":"https://github.com/PeculiarVentures/pkcs11js","commit_stats":{"total_commits":305,"total_committers":15,"mean_commits":"20.333333333333332","dds":"0.39344262295081966","last_synced_commit":"e30a91fcc53661c8d93a7a55a0a472ba261b1b63"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeculiarVentures%2Fpkcs11js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeculiarVentures%2Fpkcs11js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeculiarVentures%2Fpkcs11js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeculiarVentures%2Fpkcs11js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PeculiarVentures","download_url":"https://codeload.github.com/PeculiarVentures/pkcs11js/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247157282,"owners_count":20893220,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptography","hsms","pkcs","pkcs11","softhsm2"],"created_at":"2024-11-07T02:08:50.430Z","updated_at":"2025-04-04T10:07:52.151Z","avatar_url":"https://github.com/PeculiarVentures.png","language":"C++","funding_links":["https://github.com/sponsors/PeculiarVentures"],"categories":[],"sub_categories":[],"readme":"# PKCS11js\n\n[![license](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://raw.githubusercontent.com/PeculiarVentures/graphene/master/LICENSE)\n![test](https://github.com/PeculiarVentures/pkcs11js/workflows/test/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/PeculiarVentures/pkcs11js/badge.svg?branch=master)](https://coveralls.io/github/PeculiarVentures/pkcs11js?branch=master)\n[![npm version](https://badge.fury.io/js/pkcs11js.svg)](https://badge.fury.io/js/pkcs11js)\n\n[![NPM](https://nodei.co/npm/pkcs11js.png)](https://nodei.co/npm/pkcs11js/)\n\nPKCS11js 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.\n\n**Versioning Note:** \n- Version 1.x was implemented using the `nan` module, which allowed the package to be built for older versions of Node.js.\n- 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.\n\nFor most use cases, we recommend our package [Graphene](https://github.com/PeculiarVentures/graphene), which provides a simplistic Object Oriented interface for interacting with PKCS#11 devices.\n\nThis 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.\n\nIt has been tested with :\n- [SoftHSM2](https://www.opendnssec.org/softhsm/)\n- [Thales NShield](https://www.thales-esecurity.com/products-and-services/products-and-services/hardware-security-modules/general-purpose-hsms/nshield-solo)\n- [Safenet Luna HSMs](http://www.safenet-inc.com/)\n- [RuToken](http://www.rutoken.ru/)\n\n**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.\n\n## Installation\n\n```\n$ npm install pkcs11js\n```\n\n## Documentation\n\n[https://peculiarventures.github.io/pkcs11js/](https://peculiarventures.github.io/pkcs11js/)\n\n### Install SoftHSM2\n\n- For OSX see the [instructions here](https://github.com/opendnssec/SoftHSMv2/blob/develop/OSX-NOTES.md)\n- For linux [instructions here](https://github.com/opendnssec/SoftHSMv2/blob/develop/README.md)\n- For Windows [instructions here](https://github.com/disig/SoftHSM2-for-Windows#softhsm2-installer-for-ms-windows)\n\n## Examples\n\n### Example #1\n\n```javascript\nvar pkcs11js = require(\"pkcs11js\");\n\nvar pkcs11 = new pkcs11js.PKCS11();\npkcs11.load(\"/usr/local/lib/softhsm/libsofthsm2.so\");\n\npkcs11.C_Initialize();\n\ntry {\n    // Getting info about PKCS11 Module\n    var module_info = pkcs11.C_GetInfo();\n\n    // Getting list of slots\n    var slots = pkcs11.C_GetSlotList(true);\n    var slot = slots[0];\n\n    // Getting info about slot\n    var slot_info = pkcs11.C_GetSlotInfo(slot);\n    // Getting info about token\n    var token_info = pkcs11.C_GetTokenInfo(slot);\n\n    // Getting info about Mechanism\n    var mechs = pkcs11.C_GetMechanismList(slot);\n    var mech_info = pkcs11.C_GetMechanismInfo(slot, mechs[0]);\n\n    var session = pkcs11.C_OpenSession(slot, pkcs11js.CKF_RW_SESSION | pkcs11js.CKF_SERIAL_SESSION);\n\n    // Getting info about Session\n    var info = pkcs11.C_GetSessionInfo(session);\n    pkcs11.C_Login(session, 1, \"password\");\n\n    /**\n     * Your app code here\n     */\n    \n    pkcs11.C_Logout(session);\n    pkcs11.C_CloseSession(session);\n}\ncatch(e){\n    console.error(e);\n}\nfinally {\n    pkcs11.C_Finalize();\n}\n```\n\n### Example #2\n\nGenerating secret key using AES mechanism\n\n```javascript\nvar template = [\n    { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_SECRET_KEY },\n    { type: pkcs11js.CKA_TOKEN, value: false },\n    { type: pkcs11js.CKA_LABEL, value: \"My AES Key\" },\n    { type: pkcs11js.CKA_VALUE_LEN, value: 256 / 8 },\n    { type: pkcs11js.CKA_ENCRYPT, value: true },\n    { type: pkcs11js.CKA_DECRYPT, value: true },\n];\nvar key = pkcs11.C_GenerateKey(session, { mechanism: pkcs11js.CKM_AES_KEY_GEN }, template);\n```\n\n### Example #3\n\nGenerating key pair using RSA-PKCS1 mechanism\n\n```javascript\nvar publicKeyTemplate = [\n    { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PUBLIC_KEY },\n    { type: pkcs11js.CKA_TOKEN, value: false },\n    { type: pkcs11js.CKA_LABEL, value: \"My RSA Public Key\" },\n    { type: pkcs11js.CKA_PUBLIC_EXPONENT, value: new Buffer([1, 0, 1]) },\n    { type: pkcs11js.CKA_MODULUS_BITS, value: 2048 },\n    { type: pkcs11js.CKA_VERIFY, value: true }\n];\nvar privateKeyTemplate = [\n    { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PRIVATE_KEY },\n    { type: pkcs11js.CKA_TOKEN, value: false },\n    { type: pkcs11js.CKA_LABEL, value: \"My RSA Private Key\" },\n    { type: pkcs11js.CKA_SIGN, value: true },\n];\nvar keys = pkcs11.C_GenerateKeyPair(session, { mechanism: pkcs11js.CKM_RSA_PKCS_KEY_PAIR_GEN }, publicKeyTemplate, privateKeyTemplate);\n```\n\n### Example #4\n\nGenerating key pair using ECDSA mechanism\n\n```javascript\nvar publicKeyTemplate = [\n    { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PUBLIC_KEY },\n    { type: pkcs11js.CKA_TOKEN, value: false },\n    { type: pkcs11js.CKA_LABEL, value: \"My EC Public Key\" },\n    { type: pkcs11js.CKA_EC_PARAMS, value: new Buffer(\"06082A8648CE3D030107\", \"hex\") }, // secp256r1\n];\nvar privateKeyTemplate = [\n    { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_PRIVATE_KEY },\n    { type: pkcs11js.CKA_TOKEN, value: false },\n    { type: pkcs11js.CKA_LABEL, value: \"My EC Private Key\" },\n    { type: pkcs11js.CKA_DERIVE, value: true },\n];\nvar keys = pkcs11.C_GenerateKeyPair(session, { mechanism: pkcs11js.CKM_EC_KEY_PAIR_GEN }, publicKeyTemplate, privateKeyTemplate);\n```\n\n### Example #4\n\nWorking with Object\n\n```javascript\nvar nObject = pkcs11.C_CreateObject(session, [\n    { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_DATA },\n    { type: pkcs11js.CKA_TOKEN, value: false },\n    { type: pkcs11js.CKA_PRIVATE, value: false },\n    { type: pkcs11js.CKA_LABEL, value: \"My custom data\" },\n]);\n\n// Updating label of Object\npkcs11.C_SetAttributeValue(session, nObject, [{ type: pkcs11js.CKA_LABEL, value: \"My custom data!!!\" }]);\n\n// Getting attribute value\nvar label = pkcs11.C_GetAttributeValue(session, nObject, [\n    { type: pkcs11js.CKA_LABEL },\n    { type: pkcs11js.CKA_TOKEN }\n]);\nconsole.log(label[0].value.toString()); // My custom data!!!\nconsole.log(!!label[1].value[0]); // false\n\n// Copying Object\nvar cObject = pkcs11.C_CopyObject(session, nObject, [\n    { type: pkcs11js.CKA_CLASS},\n    { type: pkcs11js.CKA_TOKEN},\n    { type: pkcs11js.CKA_PRIVATE},\n    { type: pkcs11js.CKA_LABEL},\n]);\n\n// Removing Object\npkcs11.C_DestroyObject(session, cObject);\n```\n\n### Example #4\n\nSearching objects\n\n**NOTE:** If template is not set for C_FindObjectsInit, then C_FindObjects returns all objects from slot  \n\n```javascript\npkcs11.C_FindObjectsInit(session, [{ type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_DATA }]);\nvar hObject = pkcs11.C_FindObjects(session);\nwhile (hObject) {\n    var attrs = pkcs11.C_GetAttributeValue(session, hObject, [\n        { type: pkcs11js.CKA_CLASS },\n        { type: pkcs11js.CKA_TOKEN },\n        { type: pkcs11js.CKA_LABEL }\n    ]);\n    // Output info for objects from token only\n    if (attrs[1].value[0]){\n        console.log(`Object #${hObject}: ${attrs[2].value.toString()}`);\n    }\n    hObject = pkcs11.C_FindObjects(session);\n}\npkcs11.C_FindObjectsFinal(session);\n```\n\n### Example #5\n\nGenerating random values\n\n```javascript\nvar random = pkcs11.C_GenerateRandom(session, new Buffer(20));\nconsole.log(random.toString(\"hex\"));\n```\n\nor\n\n```javascript\nvar random = new Buffer(20);\npkcs11.C_GenerateRandom(session, random);\nconsole.log(random.toString(\"hex\"));\n```\n\n### Example #6\n\nDigest\n\n```javascript\npkcs11.C_DigestInit(_session, { mechanism: pkcs11js.CKM_SHA256 });\n\npkcs11.C_DigestUpdate(session, new Buffer(\"Incoming message 1\"));\npkcs11.C_DigestUpdate(session, new Buffer(\"Incoming message N\"));\n\nvar digest = pkcs11.C_DigestFinal(_session, Buffer(256 / 8));\n\nconsole.log(digest.toString(\"hex\"));\n```\n\n### Example #7\n\nSigning data\n\n```javascript\npkcs11.C_SignInit(session, { mechanism: pkcs11js.CKM_SHA256_RSA_PKCS }, keys.privateKey);\n\npkcs11.C_SignUpdate(session, new Buffer(\"Incoming message 1\"));\npkcs11.C_SignUpdate(session, new Buffer(\"Incoming message N\"));\n\nvar signature = pkcs11.C_SignFinal(session, Buffer(256));\n```\n\nVerifying data\n\n```javascript\npkcs11.C_VerifyInit(session, { mechanism: pkcs11js.CKM_SHA256_RSA_PKCS }, keys.publicKey);\n\npkcs11.C_VerifyUpdate(session, new Buffer(\"Incoming message 1\"));\npkcs11.C_VerifyUpdate(session, new Buffer(\"Incoming message N\"));\n\nvar verify = pkcs11.C_VerifyFinal(session, signature);\n```\n\n### Example #8\n\nEncrypting data with AES-CBC mechanism\n\n```javascript\nvar cbc_param = pkcs11.C_GenerateRandom(new Buffer(16));\n\npkcs11.C_EncryptInit(\n    session,\n    {\n        mechanism: pkcs11js.CKM_AES_CBC,\n        parameter: cbc_param\n    },\n    secretKey\n);\n\nvar enc = new Buffer(0);\nenc = Buffer.concat([enc, pkcs11.C_EncryptUpdate(session, new Buffer(\"Incoming data 1\"), new Buffer(16))]);\nenc = Buffer.concat([enc, pkcs11.C_EncryptUpdate(session, new Buffer(\"Incoming data N\"), new Buffer(16))]);\nenc = Buffer.concat([enc, pkcs11.C_EncryptFinal(session, new Buffer(16))]);\n\nconsole.log(enc.toString(\"hex\"));\n```\n\nDecrypting data with AES-CBC mechanism\n\n```javascript\npkcs11.C_DecryptInit(\n    session,\n    {\n        mechanism: pkcs11js.CKM_AES_CBC,\n        parameter: cbc_param\n    },\n    secretKey\n);\n\nvar dec = new Buffer(0);\ndec = Buffer.concat([dec, pkcs11.C_DecryptUpdate(session, enc, new Buffer(32))]);\ndec = Buffer.concat([dec, pkcs11.C_DecryptFinal(session, new Buffer(16))]);\n\nconsole.log(dec.toString());\n```\n\n### Example #9\n\nDeriving key with ECDH mechanism\n\n```javascript\n// Receive public data from EC public key\nvar attrs = pkcs11.C_GetAttributeValue(session, publicKeyEC, [{ type: pkcs11js.CKA_EC_POINT }])\nvar ec = attrs[0].value;\n\nvar derivedKey = pkcs11.C_DeriveKey(\n    session,\n    {\n        mechanism: pkcs11js.CKM_ECDH1_DERIVE,\n        parameter: {\n            type: pkcs11js.CK_PARAMS_EC_DH,\n            kdf: 2,\n            publicData: ec\n        }\n    },\n    privateKeyEC,\n    [\n        { type: pkcs11js.CKA_CLASS, value: pkcs11js.CKO_SECRET_KEY },\n        { type: pkcs11js.CKA_TOKEN, value: false },\n        { type: pkcs11js.CKA_KEY_TYPE, value: pkcs11js.CKK_AES },\n        { type: pkcs11js.CKA_LABEL, value: \"Derived AES key\" },\n        { type: pkcs11js.CKA_ENCRYPT, value: true },\n        { type: pkcs11js.CKA_VALUE_LEN, value: 256 / 8 }\n    ]\n);\n```\n### Example #10\n\nInitializing NSS crypto library\n\nUse `options` parameter for `C_Initialize` function.\n\n__Type__\n```ts\ninterface InitializationOptions {\n    /**\n     * NSS library parameters\n     */\n    libraryParameters?: string;\n    /**\n     * bit flags specifying options for `C_Initialize`\n     * - CKF_LIBRARY_CANT_CREATE_OS_THREADS. True if application threads which are executing calls to the library\n     *   may not use native operating system calls to spawn new threads; false if they may\n     * - CKF_OS_LOCKING_OK. True if the library can use the native operation system threading model for locking;\n     *   false otherwise\n     */\n    flags?: number;\n}\n/**\n * Initializes the Cryptoki library\n * @param options Initialization options\n * Supports implementation of standard `CK_C_INITIALIZE_ARGS` and extended NSS format.\n * - if `options` is null or empty, it calls native `C_Initialize` with `NULL`\n * - if `options` doesn't have `libraryParameters`, it uses `CK_C_INITIALIZE_ARGS` structure\n * - if `options` has `libraryParameters`, it uses extended NSS structure\n */\nC_Initialize(options?: InitializationOptions): void;\n```\n\n__Code__\n```js\nconst mod = new pkcs11.PKCS11();\nmod.load(\"/usr/local/opt/nss/lib/libsoftokn3.dylib\");\n\nmod.C_Initialize({\n    libraryParameters: \"configdir='' certPrefix='' keyPrefix='' secmod='' flags=readOnly,noCertDB,noModDB,forceOpen,optimizeSpace\",\n});\n\n// Your code here\n\nmod.C_Finalize();\n```\n\n[More](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Reference/FC_Initialize) info about NSS params for `C_Initialize`\n\n### Example #11\n\nDetect a slot event\n\n```javascript\nvar pkcs11js = require(\"pkcs11js\");\nvar pkcs11 = new pkcs11js.PKCS11();\n// Need a compliant Cryptoki Version 2.01 or later\npkcs11.load(\"/usr/local/lib/softhsm/libsofthsm2.so\");\n\npkcs11.C_Initialize();\n\ntry {\n    const slotId = pkcs11.C_WaitForSlotEvent(pkcs11js.CKF_DONT_BLOCK);\n    if (slotId) {\n        console.log(`Slot ${slotId} has been inserted`);\n    } else {\n        console.log(`No slot event`);\n    }\n} catch (e) {\n    console.error(e);\n} finally {\n    pkcs11.C_Finalize();\n}\n```\n\n## Suitability\nAt 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.\n\n## Bug Reporting\nPlease 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.\n\n## Related\n- [PKCS #11 2.40 Specification](http://docs.oasis-open.org/pkcs11/pkcs11-curr/v2.40/pkcs11-curr-v2.40.html)\n- [Many PKCS #11 Specifications](http://www.cryptsoft.com/pkcs11doc/)\n- [Attacking and Fixing PKCS#11 Security Tokens](http://www.lsv.ens-cachan.fr/Publis/PAPERS/PDF/BCFS-ccs10.pdf)\n- [PERL PKCS #11 binding](https://github.com/dotse/p5-crypt-pkcs11)\n- [.NET PKCS #11 binding](https://github.com/jariq/Pkcs11Interop)\n- [Ruby PKCS #11 binding](https://github.com/larskanis/pkcs11)\n- [OCaml PKCS #11 binding](https://github.com/ANSSI-FR/caml-crush)\n- [OCaml PKCS #11 CLI](https://github.com/ANSSI-FR/opkcs11-tool)\n- [Go PKCS #11 binding](https://github.com/miekg/pkcs11) \n- [PKCS #11 Admin](http://www.pkcs11admin.net)\n- [Node.js Foreign Function Interface](https://github.com/node-ffi/node-ffi)\n- [GOST PKCS#11 constants](https://github.com/romanovskiy-k/pkcs11/blob/master/rtpkcs11t.h)\n- [PKCS#11 logging proxy module](https://github.com/jariq/pkcs11-logger)\n- [PKCS#11 Proxy](https://github.com/iksaif/pkcs11-proxy)\n- [PKCS#11 Tests](https://github.com/google/pkcs11test)\n- [OpenCryptoKi](http://sourceforge.net/projects/opencryptoki/)\n- [SoftHSM](https://www.opendnssec.org/softhsm/)\n- [SofHSM2 for Windows](https://github.com/disig/SoftHSM2-for-Windows/)\n- [node-pcsc](https://github.com/santigimeno/node-pcsclite)\n- [PKCS#11 URIs](https://tools.ietf.org/html/rfc7512)\n- [Key Length Recommendations](http://www.keylength.com/en/compare/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeculiarventures%2Fpkcs11js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpeculiarventures%2Fpkcs11js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeculiarventures%2Fpkcs11js/lists"}