2013-09-26 2 views
1

В моей программе на C++ я создал пару открытых/закрытых ключей, используя CryptoAPI.Получить открытый ключ CryptoAPI через PKCS # 11

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, я не могу получить открытый ключ. Я также пробовал с другими атрибутами. Есть ли способ сделать это?

EDIT

Как owlstead предлагает, я попытался создать открытый ключ, начиная от модуля и общественного экспонента ключа, созданного в предыдущей сессии (в АЛО или, просто для этого теста, в 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, но меня интересует только открытый ключ. Я пропустил частный шаблон. Что вы здесь?

ответ

2

CKA_PRIVATE не указывает на закрытый ключ вообще.

Когда атрибут CKA_PRIVATE является TRUE, пользователь не может получить доступ к объекту, пока пользователь был идентифицирован в маркере

Вместо этого вы должны искать для атрибута, такого как CKA_CLASS со значением CKO_PUBLIC_KEY или CKO_PRIVATE_KEY, возможно, используя другие атрибуты для дальнейшего фильтрации ваших результатов.

Если вы не можете найти ни одного CKO_PUBLIC_KEY, то я предполагаю, что он был либо не сгенерирован в токене (ключ был импортирован, проверьте, установлен ли CKA_LOCAL). В качестве альтернативы он может быть создан только как объект сеанса. Наконец, возможно, он был удален.

Обратите внимание, что частные ключи RSA обычно содержат общедоступный экспонент, поэтому вы можете создать открытый ключ только из объекта закрытого ключа (конечно, с использованием модуля и открытого экспонента).

+0

ОК, благодарю вас за ответ !! Я сделал несколько тестов, и я обнаружил, что: закрытый ключ (т. Е. CKA_CLASS = CKO_PRIVATE_KEY) не является локальным - возможно потому, что он был создан через CAPI; не найдено ключей CKO_PUBLIC_KEY. Итак, по вашему мнению, для повторной сборки открытого ключа мы можем получить CKA_MODULUS и CKA_PUBLIC_EXPONENT из шаблона закрытого ключа. Я попробую! – andret8

+0

Если 'CKA_LOCAL' не установлен, вам может потребоваться дополнительная проверка безопасности вашей установки. Частный ключ наиболее безопасен, если он сгенерирован и оставлен защищенным в токене (кроме, возможно, зашифрованной резервной копии, если ваша схема управления ключами не позволяет генерировать новый ключ). –

+0

Если я создаю закрытый ключ через PKCS # 11, значение CKA_LOCAL равно true. Возможно, если он не установлен, это зависит от настройки CryptoAPI. Я проверю его. О публичном ключе, я редактирую свой вопрос с другими подробностями .. любые другие предложения? Большое спасибо – andret8

0

Удалить ссылочный символ в 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 
} 
0

Хотя это уже есть ответ для тех, кто хочет сделать это, мы создали WR PKCS # 11 на основе apper для CryptoAPI, вы можете найти его здесь:

https://github.com/PeculiarVentures/pvpkcs11

С этим вы можете получить доступ ключей, хранящихся в CryptoAPI, а также сертификатов с использованием нативного PKCS # 11 интерфейсов.