智能卡PKCS11 AES密钥生成失败。

4
我正在尝试使用Python(使用PyKCS11库)在ACOS5-64智能卡和OMNIKEY 3121读卡器上创建AES 256密钥。到目前为止,关于非对称加密的所有“标准”操作似乎都可以正常工作。我运行了大量代码示例和pkcs11-tool命令,以初始化令牌,设置/更改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_TOKEN行切换为False,则它会“起作用”。当然,通过将其设置为false,它使密钥成为会话对象而不是令牌对象(即在注销后,密钥被清除)。使用带有--list-objects的pkcs11-tool,密钥不存在。我可以使用ACSCMU(用于令牌管理的GUI工具),我可以在“秘密密钥管理器”中创建AES密钥,并且它确实创建了一个持久密钥。但是我无法知道ACSCMU正在执行什么操作以使其持久化(它可能根本没有使用PKCS11)。
如果我必须猜测问题所在,我会猜测它与会话有关。如果CKA_TOKEN=True无效,则似乎令牌实际上并不处于RW模式(如第9行中的CKF_RW_SESSION所建议的那样)。到目前为止,我不确定尝试什么或如何调试此问题。
2个回答

6

在大量的示例中自己找到了答案:如果要创建一个持久化对象(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-tool查看新对象:

$ 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

@Alan,你是如何从PKCS11获取AES密钥的?我无法从ACOS64中获取,它返回null。我可以使用ACSCMU创建ADS,但无法获取并加密它。 - Ebru Yener

0

在我看来,你唯一能做的就是联系 libacospkcs11.so 的生产商并要求解释。你很可能会被引导到文档中,其中将说明对称密钥只能作为会话对象创建,并且所有使用这些密钥的操作都在软件中执行(而不是在卡片中)- 这是大多数商用卡和中间件套件的常见做法。

顺便说一句,你也可以尝试调用 C_GetMechanismInfo 来获取 CKM_AES_KEY_GEN 机制(以及其他你计划使用的 AES 机制)的信息,并检查响应中是否设置了 CKF_HW 标志。该标志指示该机制是由设备执行还是在软件中执行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接