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.20 implementation library installed in order to use this module. Tested implementations of PKCS#11 librarys include:

This module works on the Unix like operating systems and win32.

Installation

  gem install pkcs11

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

Usage

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

Example

  require "rubygems"
  require "pkcs11"
  include PKCS11

  pkcs11 = PKCS11.open("/path/to/pkcs11.so")
  p pkcs11.info
  session = pkcs11.active_slots.first.open
  session.(: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")
  session.logout
  session.close

This opens a PKCS#11 library and prints it’s information block. Then a PKCS11::Session to the first active slot of the device is opened and a login is done on the user account. Now, a 112 bit DES3 key is generated and some plaintext is 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 RSA Security Inc. Please refer the URL: www.rsa.com/rsalabs/node.asp?id=2133. Browsable HTML can be found at www.cryptsoft.com/pkcs11doc.

Vendor extensions

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

Threading

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

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.

Cross compiling for Windows

Using rake-compiler a cross compiled pkcs11-gem can be build on a linux host for the win32 platform. There are no runtime dependencies to any but the standard Windows DLLs.

Install mingw32. On a debian based system this should work:

  apt-get install mingw32

On MacOS X, if you have MacPorts installed:

  port install i386-mingw32-gcc

Install the rake-compiler:

  gem install rake-compiler

Download and cross compile ruby for win32:

  rake-compiler cross-ruby VERSION=1.8.7-p352
  rake-compiler cross-ruby VERSION=1.9.2-p290

Download and cross compile pkcs11 for win32 (MRI 1.8+1.9 fat gem):

  rake cross native gem RUBY_CC_VERSION=1.8.7:1.9.2

If everything works, there should be pkcs11-VERSION-x86-mingw32.gem in the pkg directory.

ToDo

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_InitPIN
  DONE    C_SetPIN
  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

Authors

Copying

See MIT-LICENSE included in the package.