Skip to main content

Using PKCS#11 from Python

This example shows how to use keys on a Securosys HSM from Python via the PKCS#11 provider.

Prerequisites

Install the python-pkcs11 library:

pip3 install python-pkcs11

The python-pkcs11 library provides a way to call the C-based PKCS#11 API from Python, in a way that is idiomatic to Python, and without the Python application having to deal with FFI. Under the hood, python-pkcs11 calls the Primus PKCS#11 provider, which in turn communicates with the HSM.

For more details, see the python-pkcs11 documentation.

Sample Code

The code snippet demonstrates AES encryption and decryption in Python:

import pkcs11
import os
from base64 import b64encode, b64decode
import uuid

lib_path = "C:\\Program Files\\Securosys\\Primus P11\\primusP11.dll"

slot_id = 0

slot_password = 'PRIMUSDEV' # update to correct HSM password

def encrypt_decrypt():
session = get_hsm_session()
keyName = str(uuid.uuid4())
generate_key(session, keyName)
payload = b'INPUT DATA'
ciphertext, iv = encrypt_payload(session, keyName, payload)
decrypt_payload(session, b64decode(ciphertext), b64decode(iv), keyName)
session.close()


def generate_key(session, keyName):
session.generate_key(pkcs11.KeyType.AES, key_length=256, label=keyName, store=True, template={pkcs11.Attribute.EXTRACTABLE: False, pkcs11.Attribute.SENSITIVE: True})
print("AES key generated with key_length 256 and name: ", keyName)
print("Encrypt key stored")
return keyName


def encrypt_payload(session, keyName, payload):
encrypt_key = load_key_from_keyName(keyName, session)

# Get an initialisation vector
iv = session.generate_random(128) # AES blocks are fixed at 128 bits
# Encrypt our data
ciphertext = encrypt_key.encrypt(payload, mechanism_param=iv)

print("Encrypt payload '" + str(payload) + "' with Key: " + keyName)
return b64encode(ciphertext), b64encode(iv)


def decrypt_payload(session, ciphertext, iv, keyName):
decrypt_key = load_key_from_keyName(keyName, session)

# Encrypt our data
print("Decrypt ciphertext with Key: " + keyName)
plaintext = decrypt_key.decrypt(ciphertext, mechanism_param=iv)
print("Plaintext: " + str(plaintext))


def load_key_from_keyName(keyName, session):
key = session.get_key(object_class=pkcs11.ObjectClass.SECRET_KEY, label=keyName)
return key


def get_hsm_session():
try:
lib = pkcs11.lib(lib_path)
slots = lib.get_slots(token_present=True)
actual_slot = None
actual_slot_id = slot_id
for each_slot in slots:
if actual_slot_id == each_slot.slot_id:
actual_slot = each_slot
break
token = actual_slot.get_token()
session = token.open(rw=True, user_pin=slot_password)
return session
except Exception as e:
print("Exception occurred while creating session")

encrypt_decrypt()

Usage

To use this script:

  1. Saves this code as sample.py.
  2. Replace the lib_path, slot_id, and slot_password with the values used in your installation.
  3. Execute it with python3 sample.py.