我试图在Python智能卡上创建一个AES 256密钥,并使用Python中的子文件夹(使用库)创建一个3121卡读卡器。到目前为止,所有的“标准”操作似乎都适用于非对称加密。我已经运行了大量的代码示例和PKCS11工具命令,以初始化令牌、设置/更改PIN、创建RSA密钥对等。因此,驱动程序都是功能性的(PCSCD、CCID、PKCS11中间件)。
以下代码导致问题:

from PyKCS11 import *
import getpass
libacospkcs = '/usr/lib/libacospkcs11.so'

def createTokenAES256(lbl):
   pkcs11 = PyKCS11Lib()
   pkcs11.load(libacospkcs)
   theOnlySlot = pkcs11.getSlotList()[0]
   session = pkcs11.openSession(theOnlySlot, CKF_SERIAL_SESSION | CKF_RW_SESSION)
   PIN = getpass.getpass('Enter User PIN to login:')
   session.login(PIN)

   t = pkcs11.getTokenInfo(theOnlySlot)
   print t.label
   print t.model
   print t.serialNumber

   template = (
      (CKA_CLASS, CKO_SECRET_KEY),
      (CKA_KEY_TYPE, CKK_AES),
      (CKA_VALUE_LEN, 32),
      (CKA_LABEL, "A"),
      (CKA_PRIVATE, True),
      (CKA_SENSITIVE, True),
      (CKA_ENCRYPT, True),
      (CKA_DECRYPT, True),
      (CKA_TOKEN, True),
      (CKA_WRAP, True),
      (CKA_UNWRAP, True),
      (CKA_EXTRACTABLE, False))
   ckattr = session._template2ckattrlist(template)
   m = LowLevel.CK_MECHANISM()
   m.mechanism = LowLevel.CKM_AES_KEY_GEN

   key = LowLevel.CK_OBJECT_HANDLE()
   returnValue = pkcs11.lib.C_GenerateKey( session.session, m, ckattr, key)

   if returnValue != CKR_OK:
      raise PyKCS11Error(returnValue)

# Now run the method to create the key
createTokenAES256('TestAESKey')

但是,运行时出现错误:
~/projects/smartcard $ python testpkcs11again.py
Enter User PIN to login:
Token #A
ACOS5-64
30A740C8704A
Traceback (most recent call last):
  File "testcreateaes.py", line 43, in <module>
    createTokenAES256('TestAESKey')
  File "testcreateaes.py", line 40, in createTokenAES256
    raise PyKCS11Error(returnValue)
PyKCS11.PyKCS11Error: CKR_ATTRIBUTE_VALUE_INVALID (0x00000013)

问题是,如果我将cka_标记行切换为false,那么它“工作”。当然,通过将其设置为false,它使密钥成为会话对象,而不是令牌对象(即,在注销后,密钥将被擦除)。使用带有--list对象的pkcs11工具时,键不在那里。我可以使用acscmu(令牌管理的gui工具),我可以在“密钥管理器”中创建aes密钥,它确实创建了一个持久密钥。但是我无法看到acscmu正在做什么来使其持久化(它可能根本没有使用pkcs11)。
如果我必须猜出问题,我想这和会议有关。如果cka_token=true无效,则该令牌似乎实际上没有处于rw模式(如第9行的ckf_rw_会话所建议的)。到目前为止,我还不确定该尝试什么或如何调试。

最佳答案

通过大量的示例,我自己解决了这个问题:如果要创建持久化(cka_token=true)对象,cka_id是必需的属性。不知道我是怎么知道的(从来没有在任何文档中看到过),但是在我添加了它之后,它确实工作得很好。
如果驱动程序设置正确,则此代码应该可以工作:

from PyKCS11 import *
import getpass
libacospkcs = '/usr/lib/libacospkcs11.so'

def createTokenAES256(label):
   pkcs11 = PyKCS11Lib()
   pkcs11.load(libacospkcs)
   theOnlySlot = pkcs11.getSlotList()[0]
   session = pkcs11.openSession(theOnlySlot, CKF_SERIAL_SESSION | CKF_RW_SESSION)
   PIN = getpass.getpass('Enter User PIN to login:')
   session.login(PIN)

   print pkcs11.getTokenInfo(theOnlySlot)

   template = (
      (CKA_CLASS, CKO_SECRET_KEY),
      (CKA_KEY_TYPE, CKK_AES),
      (CKA_VALUE_LEN, 32),
      (CKA_LABEL, label),
      (CKA_ID, "1244"),
      (CKA_PRIVATE, True),
      (CKA_SENSITIVE, True),
      (CKA_ENCRYPT, True),
      (CKA_DECRYPT, True),
      (CKA_TOKEN, True),
      (CKA_WRAP, True),
      (CKA_UNWRAP, True),
      (CKA_EXTRACTABLE, False))
   ckattr = session._template2ckattrlist(template)
   m = LowLevel.CK_MECHANISM()
   m.mechanism = LowLevel.CKM_AES_KEY_GEN

   key = LowLevel.CK_OBJECT_HANDLE()
   returnValue = pkcs11.lib.C_GenerateKey( session.session, m, ckattr, key)

   if returnValue != CKR_OK:
      raise PyKCS11Error(returnValue)

# Now execute the above to create AES256 key
createTokenAES256('TestKey')

之后,我可以注销卡并使用pkcs11工具查看新对象:
$ pkcs11-tool --module=/usr/lib/libacospkcs11.so --list-objects
Using slot 0 with a present token (0x0)
Secret Key Object; unknown key algorithm 31
  label:      TestKey
  ID:         31323434
  Usage:      encrypt, decrypt, wrap, unwrap, derive

10-04 12:31