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"
}