将 C_Sign 调用与 C_Generate 分开
Separate C_Sign call from C_Generate
我正在用 C 代码实现 pkcs11,并尝试实现一个简单的生成、签名、验证工作流程。当我为所有内容调用我的 pkcs11 驱动程序时,该流程有效。但是,我正在尝试分离这些调用,以便我可以生成一个密钥,在稍后阶段将其用于单独的 c_sign 或 c_verify 调用。
我的主要问题是 c_sign 调用需要私钥句柄的 CK_OBJECT_HANDLE 参数,但我不知道稍后如何检索它。它在单个 "generate -> sign -> verify" 流上工作的原因是句柄仍然在生成调用的内存中,使其在后续调用中很容易访问。
我的生成调用如下所示:
C_GenerateKeyPair(hSession, &mechanism,
publicKeyTemplate,
sizeof(publicKeyTemplate)/sizeof(CK_ATTRIBUTE),
privateKeyTemplate,
sizeof(privateKeyTemplate)/sizeof(CK_ATTRIBUTE),
phPublicKey, phPrivateKey);
其中 phPublicKey
和 phPrivateKey
是存储句柄的位置...
随后的签名函数需要一个 hPrivateKey
参数,用于我要签名的 privKey。
一个句柄绑定到一个会话。在新会话中,句柄不再有效。要维护对键的引用,您需要给它一些唯一的名称。有两种方法可以做到这一点:
- 任何 object in storage 都可以有一个
CKA_LABEL
属性,其值为可打印字符串。
- 任何 key object 都可以有一个
CKA_ID
属性,其值为字节数组。
为您的密钥指定唯一 ID 或标签。稍后要打开它,您需要搜索它。这是唯一的方法:PKCS#11 没有办法通过名称直接打开密钥!您需要搜索具有正确 id/label 的对象,如果该属性是唯一的,您就知道找到的第一个就是正确的。 public 密钥和匹配密钥对中的私钥相同 id/label 是可以的(而且确实更方便);在搜索时通过 class 属性指定您想要的。
创作:
CK_BYTE id[] = {0x01, 0x02, 0x03, 0x04};
int generate_key(CK_SESSION_HANDLE hSession, …)
{
CK_BBOOL ck_true = CK_TRUE;
CK_ATTRIBUTE publicKeyTemplate[] = {
{CKA_TOKEN, &ck_true, sizeof(ck_true)},
{CKA_ID, id, sizeof(id)},
…
};
CK_ATTRIBUTE privateKeyTemplate[] = {
{CKA_TOKEN, &ck_true, sizeof(ck_true)},
{CKA_ID, id, sizeof(id)},
…
};
CK_MECHANISM mechanism = …;
CK_OBJECT_HANDLE hPublicKey = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE hPrivateKey = CK_INVALID_HANDLE;
C_GenerateKeyPair(hSession, &mechanism,
publicKeyTemplate,
sizeof(publicKeyTemplate)/sizeof(CK_ATTRIBUTE),
privateKeyTemplate,
sizeof(privateKeyTemplate)/sizeof(CK_ATTRIBUTE),
&hPublicKey, &hPrivateKey);
}
使用(省略大部分错误检查):
CK_BYTE id[] = {0x01, 0x02, 0x03, 0x04}; // same as when creating the key
int sign_stuff(CK_SESSION_HANDLE hSession, ) {
CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY;
CK_ATTRIBUTE privateKeyTemplate[] = {
{CKA_ID, id, sizeof(id)},
{CKA_CLASS, cko_private_key, sizeof(cko_private_key)},
};
C_FindObjectsInit(hSession,
privateKeyTemplate, sizeof(privateKeyTemplate)/sizeof(*privateKeyTemplate));
CK_OBJECT_HANDLE hPrivateKey = CK_INVALID_HANDLE;
CK_ULONG count = 0;
C_FindObjects(hSession, &hPrivateKey, 1, &count);
C_FindObjectsFinal(hSession);
if (count == 0)
return ERROR_KEY_NOT_FOUND;
CK_MECHANISM mechanism = …;
C_SignInit(hSession, &mechanism, hPrivateKey);
…
}
我正在用 C 代码实现 pkcs11,并尝试实现一个简单的生成、签名、验证工作流程。当我为所有内容调用我的 pkcs11 驱动程序时,该流程有效。但是,我正在尝试分离这些调用,以便我可以生成一个密钥,在稍后阶段将其用于单独的 c_sign 或 c_verify 调用。
我的主要问题是 c_sign 调用需要私钥句柄的 CK_OBJECT_HANDLE 参数,但我不知道稍后如何检索它。它在单个 "generate -> sign -> verify" 流上工作的原因是句柄仍然在生成调用的内存中,使其在后续调用中很容易访问。
我的生成调用如下所示:
C_GenerateKeyPair(hSession, &mechanism,
publicKeyTemplate,
sizeof(publicKeyTemplate)/sizeof(CK_ATTRIBUTE),
privateKeyTemplate,
sizeof(privateKeyTemplate)/sizeof(CK_ATTRIBUTE),
phPublicKey, phPrivateKey);
其中 phPublicKey
和 phPrivateKey
是存储句柄的位置...
随后的签名函数需要一个 hPrivateKey
参数,用于我要签名的 privKey。
一个句柄绑定到一个会话。在新会话中,句柄不再有效。要维护对键的引用,您需要给它一些唯一的名称。有两种方法可以做到这一点:
- 任何 object in storage 都可以有一个
CKA_LABEL
属性,其值为可打印字符串。 - 任何 key object 都可以有一个
CKA_ID
属性,其值为字节数组。
为您的密钥指定唯一 ID 或标签。稍后要打开它,您需要搜索它。这是唯一的方法:PKCS#11 没有办法通过名称直接打开密钥!您需要搜索具有正确 id/label 的对象,如果该属性是唯一的,您就知道找到的第一个就是正确的。 public 密钥和匹配密钥对中的私钥相同 id/label 是可以的(而且确实更方便);在搜索时通过 class 属性指定您想要的。
创作:
CK_BYTE id[] = {0x01, 0x02, 0x03, 0x04};
int generate_key(CK_SESSION_HANDLE hSession, …)
{
CK_BBOOL ck_true = CK_TRUE;
CK_ATTRIBUTE publicKeyTemplate[] = {
{CKA_TOKEN, &ck_true, sizeof(ck_true)},
{CKA_ID, id, sizeof(id)},
…
};
CK_ATTRIBUTE privateKeyTemplate[] = {
{CKA_TOKEN, &ck_true, sizeof(ck_true)},
{CKA_ID, id, sizeof(id)},
…
};
CK_MECHANISM mechanism = …;
CK_OBJECT_HANDLE hPublicKey = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE hPrivateKey = CK_INVALID_HANDLE;
C_GenerateKeyPair(hSession, &mechanism,
publicKeyTemplate,
sizeof(publicKeyTemplate)/sizeof(CK_ATTRIBUTE),
privateKeyTemplate,
sizeof(privateKeyTemplate)/sizeof(CK_ATTRIBUTE),
&hPublicKey, &hPrivateKey);
}
使用(省略大部分错误检查):
CK_BYTE id[] = {0x01, 0x02, 0x03, 0x04}; // same as when creating the key
int sign_stuff(CK_SESSION_HANDLE hSession, ) {
CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY;
CK_ATTRIBUTE privateKeyTemplate[] = {
{CKA_ID, id, sizeof(id)},
{CKA_CLASS, cko_private_key, sizeof(cko_private_key)},
};
C_FindObjectsInit(hSession,
privateKeyTemplate, sizeof(privateKeyTemplate)/sizeof(*privateKeyTemplate));
CK_OBJECT_HANDLE hPrivateKey = CK_INVALID_HANDLE;
CK_ULONG count = 0;
C_FindObjects(hSession, &hPrivateKey, 1, &count);
C_FindObjectsFinal(hSession);
if (count == 0)
return ERROR_KEY_NOT_FOUND;
CK_MECHANISM mechanism = …;
C_SignInit(hSession, &mechanism, hPrivateKey);
…
}