Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.
Introduction
The PKCS #11 standard defines a platform-independent API to cryptographic tokens, such as hardware security modules (HSM), smart cards, and names the API itself "Cryptoki" (from "cryptographic token interface" and pronounced as "crypto-key" - but "PKCS #11" is often used to refer to the API as well as the standard that defines it).
The API defines most commonly used cryptographic object types (RSAX.509 keys, DES/Triple DES Certificates/keys, etc.) and all the functions needed to use, create/generate, modify and delete those objects.
This container relies on a PKCS#11 a library which handles the communication with the token/card. This can be a vendor specific library or an opensource one, please select the correct one depending on the type of token/card you are using.
Interface Summary
The Abstract PKCS #11 smartcard interface is summarised in the following snippet:
Copy export interface AbstractPkcs11 {
certificates(slotId: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: Pkcs11ObjectCertificatesResponse) => void): Promise<Pkcs11ObjectCertificatesResponse>;
signData(data: Pkcs11SignData, callback?: (error: T1CLibException, data: Pkcs11ObjectSignResponse) => void): Promise<Pkcs11ObjectSignResponse>;
slots(callback?: (error: T1CLibException, data: Pkcs11ObjectSlotsResponse) => void): Promise<Pkcs11ObjectSlotsResponse>;
slotsWithTokenPresent(callback?: (error: T1CLibException, data: Pkcs11ObjectSlotsResponse) => void): Promise<Pkcs11ObjectSlotsResponse>;
token(slotId: string, callback?: (error: T1CLibException, data: Pkcs11ObjectTokenResponse) => void): Promise<Pkcs11ObjectTokenResponse>;
}
Pkcs11 object models
Copy export class Pkcs11ObjectInfoResponse extends DataObjectResponse {
constructor(public data: Pkcs11Info, public success: boolean) {
super(data, success);
}
}
export class Pkcs11ObjectSign {
constructor(public data: string) {
}
}
export class Pkcs11ObjectSignResponse {
constructor(public data: Pkcs11ObjectSign, public success: boolean) {
}
}
export class Pkcs11ObjectSlots {
constructor(public slots: Pkcs11Slot[]) {
}
}
export class Pkcs11ObjectSlotsResponse {
constructor(public data: Pkcs11ObjectSlots, public success: boolean) {
}
}
export class Pkcs11ObjectCertificates {
constructor(public certificates: Pkcs11ObjectCertificate[]) {}
}
export class Pkcs11ObjectCertificate {
constructor(public id: string, public certificate: string, public parsed?: Certificate) {}
}
export class Pkcs11ObjectCertificatesResponse {
constructor(public data: Pkcs11ObjectCertificates, public success: boolean) {
}
}
export class Pkcs11SignData {
constructor(public slotId: string,
public certificateId: string,
public algorithm: string,
public data: string,
public pin?: string,
public osDialog?: boolean) {}
}
export class Pkcs11ObjectTokenResponse {
constructor(public data: Pkcs11TokenInfo, public success: boolean) {
}
}
export class Pkcs11SetConfigResponse {
constructor(public data: string, public success: boolean) {
}
}
export class Pkcs11Slots {
constructor(public slots: Pkcs11Slot[]) {
}
}
export class Pkcs11Slot {
constructor(public slot: number,
public description: string) {
}
}
export class Pkcs11TokenInfo {
constructor(public slot: string,
public label: string,
public manufacturerId: string,
public model: string,
public serialNumber: string,
public flags: string,
public ulMaxSessionCount: number,
public ulSessionCount: number,
public ulMaxRwSessionCount: number,
public ulMaxPinLen: number,
public ulMinPinLen: number,
public ulTotalPublicMemory: number,
public ulFreePublicMemory: number,
public ulTotalPrivateMemory: number,
public ulFreePrivateMemory: number,
public hardwareVersion: string,
public firmwareVersion: string) {
}
}
Get the PKCS #11 container object
For more information on how to configure the JS client library see Configuration .
Copy const winLocation = "C:\\Windows\\System32\\eTPKCS11.dll"
const macLocation = "/usr/local/lib/libeTPkcs11.dylib";
T1CSdk.T1CClient.initialize(config).then(res => {
client = res;
console.log("Client config: ", client.localConfig)
core = client.core();
// Depending on the OS select the appropriate location of the library
const pkcs11 = client.pkcs11(winLocation);
}, err => {});
Depending on the OS you need to provide a valid location to the desired PKCS11 library to be used.
Call a function for the PKCS #11 container:
Copy const slotId = 0;
pkcs11.certificates(slotId, true).then(res => {
console.log(JSON.stringify(data, null, ' '));
}, err => {
console.log("Error:",JSON.stringify(err, null, ' '));
});
Reading data
Slots
This methods returns the available slots on the system.
An example response:
Copy {
"data":
[
{
"slot": 0,
"description": "eToken 5100",
},
{
"slot": 1,
"description": "",
}
]
"success": true
}
Slots with tokens present
This method is similar the the slots endpoint but only returns a list of slots where a token is present.
Copy pkcs11.slotsWithTokenPresent(callback);
An example response:
Copy {
"data":
[
{
"slot": 0,
"description": "eToken 5100"
}
]
"success": true
}
Token
This methods returns the token information for a slot.
Copy pkcs11.token(slot_id, callback);
An example response:
Copy {
"data":
{
"slot": 1,
"label": "Token Label",
"manufacturerId": "Gemalto",
"model": "Safenet Token e5100",
"serialNumber": "1234567890",
"flags": 7,
"maxSessionCount": 10,
"sessionCount": 1,
"maxRwSessionCount": 5,
"rwSessionCount": 1,
"maxPinLength": 20,
"minPinLength": 8,
"totalPublicMemory": 10000,
"freePublicMemory": 5000,
"totalPrivateMemory": 1000,
"freePrivateMemory": 50,
"hardwareVersion": "1",
"firmwareVersion": "1"
},
"success": true
}
Certificates
This methods allows you to retrieve the certificates from the PKCS #11 token.
Copy // retrieve certificates for token in slot_id 0
pkcs11.certificates(0, false);
Response:
Copy {
"data": [
{
"certificate": "MIIFjjCCA3agAwI...rTBDdrlEWVaLrY+M+xeIctrC0WnP7u4xg==",
"id": "E8CE05618E79A79825722AE067EC0029851D860D"
},
{
"certificate": "MIIFjjCCA3agAwI...rTBDdrlEWVaLrY+M+xeIctrC0WnP7u4xg==",
"id": "9F8F1CD68867526B1DF919832219B217282D2B0B"
}
],
"success": true
}
Signing data
To successfully sign data, we need the following parameters:
Slot ID of the token to use
Certificate ID of the signing certificate
The slot id can be found using either a call to slots
, slotsWithTokenPresent
. Once the slot id is found, the certificates can be retrieved with a call to certificates
. This then returns the certificate id . Now we can combine this with the PIN code and hashed data + hashing algorithm (SHA1, SHA256, SHA384, SHA512) to create the final signData call:
signData call
Returns signed data for provided input data.
Copy var signDataPayload = {
slotId: 1,
certificateId: "9F8F1CD68867526B1DF919832219B217282D2B0B",
pin: "thepincodeforthetoken",
data: "hashed data"
algorithm: "sha256"
}
pkcs11.signData(signDataPayload, callback);
An example response:
Copy {
"data": "L3BWs7lvoajPg5tC9GEmlSMdXMcDkNDUVVvt+KFqbJbXkJdI3DGoM3IOeXLaeTCxKmJ33/QQApL1nEAMuHY38V41czyswfSdpnqeex3EisXKkiYHeNzt9AXeoxDtsWbGkejKqru6X4xzAy/1SnccjZ2BQB/uUwyfyyweFjbZAGCLfTzWraCxG0ud2c8itsjmsBgXSuGjLqxKIJXbtuX22gd0nc4LeZLA91sxaoNFBCEVlOgJ/oJncFylf6T/Tz9R4VOA9kSf6NB1tAMsFEsihgjZafu/rzlrOfzZw4YY/T32LKY4Y2zNnDhJAucqflZjopGadDvkkSmTvxxEJuE+Bw==",
"success": true
}
Error Handling
Error Object
The functions specified are asynchronous and always need a callback function.
The callback function will reply with a data object in case of success, or with an error object in case of an error. An example callback:
Copy function callback(err,data) {
if(err){
console.log("Error:",JSON.stringify(err, null, ' '));
}
else {
console.log(JSON.stringify(data, null, ' '));
}
}
The error object returned:
Copy {
success: false,
description: "some error description",
code: "some error code"
}