В моей программе на C ++ я создал пару открытый / закрытый ключ, используя CryptoAPI.
CryptGenKey(eTokenProv,ENCRYPT_ALGORITHM,CRYPT_EXPORTABLE,&k1)
Ключи хранятся в eToken.
Можно ли получить открытый ключ, используя PKCS # 11? Ранее созданный закрытый ключ находится после поиска по следующему шаблону поиска:
CK_ATTRIBUTE private_search[] = {
{CKA_PRIVATE, CK_TRUE, sizeof(CK_BBOOL)}
};
Если я установлю CKA_PRIVATE
в CK_FALSE, я не могу получить открытый ключ. Я также пробовал с другими атрибутами.
Есть ли способ сделать это?
РЕДАКТИРОВАТЬ
Как owlstead предполагает, что я попытался создать открытый ключ, начиная с модуля и экспоненты открытого ключа, созданного в предыдущем сеансе (в CAPI или, только для этого теста, в PKCS11). Я получил модуль и открытый показатель из закрытого ключа в этих буферах:
CK_BYTE modulus[128]; //if 1024bit
CK_BYTE publicExponent[4]; //4 Byte, according to public key blob
Но когда я пытаюсь создать новый публичный ключ с помощью следующих инструкций:
CK_ATTRIBUTE publicKeyTemplate[] = {
{CKA_TOKEN, &yes, sizeof(true)},
{CKA_WRAP, &yes, sizeof(true)},
{CKA_ENCRYPT, &yes, sizeof(true)},
{CKA_MODULUS_BITS, &modulusBits, sizeof(modulusBits)},
{CKA_MODULUS, &modulus, sizeof(modulus)},
{CKA_PUBLIC_EXPONENT, &publicExponent, sizeof(publicExponent)}
CK_MECHANISM mechanism = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
rv = (*functions->C_GenerateKeyPair) (session, &mechanism, publicKeyTemplate, 6, privateKeyTemplate, 6, &hPublicKey, &hPrivateKey);
Я получаю ошибку «Неверный шаблон». Проблема в модуле, потому что без него я могу создать пару ключей. Я использую функцию C_GenerateKeyPair
, но меня интересует только открытый ключ. Я опустил закрытый шаблон.
Что здесь не так?
CKA_PRIVATE
не указывает закрытый ключ вообще.
Когда атрибут CKA_PRIVATE равен TRUE, пользователь не может получить доступ к объекту, пока пользователь
был аутентифицирован в токене
Вместо этого вы должны искать такой атрибут, как CKA_CLASS
со значением CKO_PUBLIC_KEY
или же CKO_PRIVATE_KEY
, возможно, используя другие атрибуты для дальнейшей фильтрации ваших результатов.
Если вы не можете найти какие-либо CKO_PUBLIC_KEY
затем я предполагаю, что он не был сгенерирован в токене (ключ был импортирован, проверьте, CKA_LOCAL
установлено). В качестве альтернативы, он может быть создан только как объект сеанса. Наконец это могло быть удалено.
Обратите внимание, что закрытые ключи RSA обычно содержат открытый показатель, поэтому вы все равно можете создать открытый ключ только из объекта закрытого ключа (конечно, используя модуль и открытый показатель).
Удалите символ ссылки в CK_ATTRIBUTE при установке указателя на массив CK_BYTE — в вашем случае модуль.
CK_ATTRIBUTE publicKeyTemplate[] = {
{CKA_TOKEN, &yes, sizeof(true)},
{CKA_WRAP, &yes, sizeof(true)},
{CKA_ENCRYPT, &yes, sizeof(true)},
{CKA_MODULUS_BITS, &modulusBits, sizeof(modulusBits)},
{CKA_MODULUS, modulus, sizeof(modulus)},
{CKA_PUBLIC_EXPONENT, &publicExponent, sizeof(publicExponent)}
Я не проверял ваш код, но я могу успешно получить модуль CK_OBJECT_HANDLE (закрытый ключ / открытый ключ), установив следующий шаблон и сделав вызов C_GetAttributeValue:
CK_BYTE modulus[128];
CK_ATTRIBUTE Modulus = { CKA_MODULUS, modulus, sizeof(modulus) };
if ((rv = (*p11FunctionList->C_GetAttributeValue)(hSession, hPrivKey /*hPubKey*/, &Modulus, 1)) == CKR_OK)
{
// do something with obtained modulus
}
Сгенерированная пара закрытый-открытый ключ была сгенерирована следующим образом:
CK_OBJECT_HANDLE hPrivKey, hPubKey;
CK_BBOOL bTrue = TRUE;
CK_ULONG mod_bits = 1024;
CK_MECHANISM GenMechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
CK_ATTRIBUTE GenPubTemplate[] = {
{ CKA_MODULUS_BITS, &mod_bits, sizeof(CK_ULONG) },
{ CKA_PUBLIC_EXPONENT, "\x01\x00\x01", 3 },
{ CKA_TOKEN, &bTrue, sizeof(CK_BBOOL) },
{ CKA_ID, (CK_CHAR_PTR)szKeyID, strlen(szKeyID) } }; // szKeyID is a const char *
CK_ATTRIBUTE GenPrivTemplate[] = {
{ CKA_TOKEN, &bTrue, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &bTrue, sizeof(CK_BBOOL) },
{ CKA_SENSITIVE, &bTrue, sizeof(CK_BBOOL) },
{ CKA_ID, (CK_CHAR_PTR)szKeyID, strlen(szKeyID) } }; // szKeyID is a const char *
// hSession is a CK_SESSION_HANDLE of an opened & logged in session
if ((rv = (*p11FunctionList->C_GenerateKeyPair)(hSession, &GenMechanism, GenPubTemplate, 4, GenPrivTemplate, 4, &hPubKey, &hPrivKey)) == CKR_OK)
{
// Now get the modulus of a the private / public key as described above
}
Хотя это уже было дано ответом для тех, кто хочет это сделать, мы создали оболочку на основе PKCS # 11 для CryptoAPI, вы можете найти ее здесь:
https://github.com/PeculiarVentures/pvpkcs11
При этом вы можете получить доступ к ключам, хранящимся в CryptoAPI, а также к сертификатам, используя собственные интерфейсы PKCS # 11.