智能卡 PKCS11 AES 密钥生成失败
Smartcard PKCS11 AES Key Gen Failure
我正在尝试在 ACOS5-64 智能卡和 OMNIKEY 3121 卡上创建 AES 256 密钥 reader,使用 python 中的 PKCS11(使用 PyKCS11 库)。到目前为止,所有 "standard" 操作似乎都适用于非对称加密。我有 运行 大量代码示例和 pkcs11-tool 命令,用于初始化令牌、set/change 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,那么它会 "works"。当然,通过将其设置为 false,它使密钥成为会话对象而不是令牌对象(即在我注销后,密钥被擦除)。将 pkcs11-tool 与 --list-objects 一起使用,密钥不存在。我可以使用 ACSCMU(用于令牌管理的 GUI 工具),我可以在 "Secret Key Manager" 中创建一个 AES 密钥,它确实创建了一个持久密钥。但是我无法查看 ACSCMU 正在做什么以使其持久化(它可能根本没有使用 PKCS11)。
如果我不得不猜测问题,我猜它与会话有关。如果 CKA_TOKEN=True 无效,则令牌似乎实际上并未处于 RW 模式(如第 9 行中的 CKF_RW_SESSION 所建议)。到目前为止,我不确定还可以尝试什么或如何调试它。
IMO 你对此无能为力,只能联系 libacospkcs11.so
的制作人并寻求解释。您很可能会被定向到文档,该文档将声明对称密钥只能作为会话对象创建,并且使用此类密钥的所有操作都在软件中执行(而不是在卡中)——这是大多数商用卡和中间件套件。
顺便说一句,您还可以尝试为 CKM_AES_KEY_GEN
机制(以及您计划使用的其他 AES 机制)调用 C_GetMechanismInfo
并检查 CKF_HW
标志是否设置在回复。此标志表示该机制是由设备执行还是在软件中执行。
通过大量示例进行大量挖掘后,我自己弄清楚了:如果您要创建一个持久性 (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
我正在尝试在 ACOS5-64 智能卡和 OMNIKEY 3121 卡上创建 AES 256 密钥 reader,使用 python 中的 PKCS11(使用 PyKCS11 库)。到目前为止,所有 "standard" 操作似乎都适用于非对称加密。我有 运行 大量代码示例和 pkcs11-tool 命令,用于初始化令牌、set/change 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,那么它会 "works"。当然,通过将其设置为 false,它使密钥成为会话对象而不是令牌对象(即在我注销后,密钥被擦除)。将 pkcs11-tool 与 --list-objects 一起使用,密钥不存在。我可以使用 ACSCMU(用于令牌管理的 GUI 工具),我可以在 "Secret Key Manager" 中创建一个 AES 密钥,它确实创建了一个持久密钥。但是我无法查看 ACSCMU 正在做什么以使其持久化(它可能根本没有使用 PKCS11)。
如果我不得不猜测问题,我猜它与会话有关。如果 CKA_TOKEN=True 无效,则令牌似乎实际上并未处于 RW 模式(如第 9 行中的 CKF_RW_SESSION 所建议)。到目前为止,我不确定还可以尝试什么或如何调试它。
IMO 你对此无能为力,只能联系 libacospkcs11.so
的制作人并寻求解释。您很可能会被定向到文档,该文档将声明对称密钥只能作为会话对象创建,并且使用此类密钥的所有操作都在软件中执行(而不是在卡中)——这是大多数商用卡和中间件套件。
顺便说一句,您还可以尝试为 CKM_AES_KEY_GEN
机制(以及您计划使用的其他 AES 机制)调用 C_GetMechanismInfo
并检查 CKF_HW
标志是否设置在回复。此标志表示该机制是由设备执行还是在软件中执行。
通过大量示例进行大量挖掘后,我自己弄清楚了:如果您要创建一个持久性 (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