Skip to content


Subversion checkout URL

You can clone with
Download ZIP
PKCS #11/Ruby Interface
Ruby C Objective-C
Branch: master


Status Build Status

PKCS #11/Ruby Interface

This module allows Ruby programs to interface with “RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki)”. PKCS #11 is the de-facto standard to access cryptographic devices. You must have a PKCS #11 v2.x implementation library installed in order to use this module. Tested implementations of PKCS#11 librarys include:

This module works on Unix like operating systems and on Windows.


$ gem install pkcs11

This installs the PKCS#11 extension either by compiling (Unix) or by using the precompiled gem for Windows.


Cryptoki has a reputation to be complicated to implement and use. While this seems to be true for C, it shouldn't for Ruby.

  • {} opens a PKCS#11 Unix *.so file or Windows-DLL with a suitable PKCS #11 implementation and returns a {PKCS11::Library}.

  • {PKCS11::Library#slots} returns a list of {PKCS11::Slot} for all slots accessable by the library.

  • {PKCS11::Slot#open} opens a {PKCS11::Session} which is used for object handling and cryptographic operations.

  • {PKCS11::Object} represents a key, data or certificate object.

  • all constants defined in PKCS#11 v2.40 are available in the module {PKCS11} and contain the associated Integer value (CKA_KEY_TYPE, CKK_AES, CKM_SHA_1 etc.)

  • also all PKCS#11 v2.40 structs are available in the module {PKCS11} as proper ruby classes ({PKCS11::CK_VERSION}, {PKCS11::CK_OTP_PARAMS} etc.)


require "rubygems"
require "pkcs11"
include PKCS11

pkcs11 ="/path/to/")
p  # => #<PKCS11::CK_INFO cryptokiVersion=...> do |session|
  session.login(:USER, "1234")
  secret_key = session.generate_key(:DES2_KEY_GEN,
    :ENCRYPT=>true, :DECRYPT=>true, :SENSITIVE=>true, :TOKEN=>true, :LABEL=>'my key')
  cryptogram = session.encrypt( {:DES3_CBC_PAD=>"\0"*8}, secret_key, "some plaintext")

This opens a {PKCS11::Library PKCS#11 library} and prints it's {PKCS11::CK_INFO information block}. Then a {PKCS11::Session} to the first {PKCS11::Library#active_slots active slot} of the device is opened and a {PKCS11::Session#login login} is done on the user account. Now, a 112 bit DES3 {PKCS11::Object key object} is generated and some plaintext is {PKCS11::Session#encrypt encrypted} with it. A 8-byte zero IV is used. In many cases method parameters can be Integer (like PKCS11::CKA_LABEL) or, as in the sample, Symbol (:LABEL) which is internally converted.

Many more usage examples can be found in the unit tests of the test directory of the project or gem.

Detail information for the API specification is provided by the OASIS PKCS 11 Technical Committee. Please refer the URL:

Browsable HTML can be found at

Vendor extensions

Some vendors extend their libraries beyond the standard, in it's own way. This can be used by vendor specific packages:

  • Safenet ProtectServer: {file:pkcs11_protect_server/README_PROTECT_SERVER.rdoc}

  • Safenet Luna: {file:pkcs11_luna/README_LUNA.rdoc}


The pkcs11 binding fully supports native, background Ruby threads. This of course only applies to Rubinius and Ruby 1.9 or higher since earlier versions of Ruby do not support native threads.

According to the standard, calling the Cryptoki library from multiple threads simultaneously, requires to open it with flag PKCS11::CKF_OS_LOCKING_OK. Application-supplied synchronization primitives (CreateMutex, DestroyMutex, LockMutex, UnlockMutex) are not supported.

Compiling for Windows

The pkcs11 source gem can be built on Windows (with help of the RubyInstaller's DevKit ) . Use

$ gem install pkcs11 --platform=ruby

for installation. In addition precompiled binary Windows gems are provided for convenience. They are installed by default on Windows.

The binary Windows gems can be compiled per rake-compiler-dock :

$ rake gem:windows

If everything works, there should be some files kind of pkcs11-VERSION-ARCH-mingw32.gem in the pkg directory for installation.


  • encoding support for Ruby 1.9+

  • support for proprietary extensions of other vendors

  • full support for PKCS#11 v2.40

Development Status

Any operation that is possible with PKCS#11 in C, should be likewise possible in Ruby. Otherwise it is considered as a bug in the binding.

STATE   FUNCTION               NOTE
------  ---------------------  ----------------------------------------
DONE    C_Initialize
DONE    C_Finalize
DONE    C_GetInfo
DONE    C_GetFunctionList
DONE    C_GetSlotList
DONE    C_GetSlotInfo
DONE    C_GetTokenInfo
DONE    C_GetMechanismList
DONE    C_GetMechanismInfo
DONE    C_InitToken
DONE    C_OpenSession
DONE    C_CloseSession
DONE    C_CloseAllSessions
DONE    C_GetSessionInfo
DONE    C_GetOperationState
DONE    C_SetOperationState
DONE    C_Login
DONE    C_Logout
DONE    C_CreateObject
DONE    C_CopyObject
DONE    C_DestroyObject
DONE    C_GetObjectSize
DONE    C_GetAttributeValue
DONE    C_SetAttributeValue
DONE    C_FindObjectsInit
DONE    C_FindObjects
DONE    C_FindObjectsFinal
DONE    C_EncryptInit
DONE    C_Encrypt
DONE    C_EncryptUpdate
DONE    C_EncryptFinal
DONE    C_DecryptInit
DONE    C_Decrypt
DONE    C_DecryptUpdate
DONE    C_DecryptFinal
DONE    C_DigestInit
DONE    C_Digest
DONE    C_DigestUpdate
DONE    C_DigestKey
DONE    C_DigestFinal
DONE    C_SignInit
DONE    C_Sign
DONE    C_SignUpdate
DONE    C_SignFinal
DONE    C_SignRecoverInit
DONE    C_SignRecover
DONE    C_VerifyInit
DONE    C_Verify
DONE    C_VerifyUpdate
DONE    C_VerifyFinal
DONE    C_VerifyRecoverInit
DONE    C_VerifyRecover
DONE    C_DigestEncryptUpdate
DONE    C_DecryptDigestUpdate
DONE    C_SignEncryptUpdate
DONE    C_DecryptVerifyUpdate
DONE    C_GenerateKey
DONE    C_GenerateKeyPair
DONE    C_WrapKey
DONE    C_UnwrapKey
DONE    C_DeriveKey
DONE    C_SeedRandom
DONE    C_GenerateRandom
N/A     C_GetFunctionStatus    legacy function
N/A     C_CancelFunction       legacy function
DONE    C_WaitForSlotEvent


  • Ryosuke Kutsuna <>

  • GOTOU Yuuzou <>

  • Lars Kanis <>

  • Jonathan Patchell <>


See MIT-LICENSE included in the package.

Something went wrong with that request. Please try again.