2013-09-26 28 views
1

在我的C++程序中,我使用CryptoAPI创建了公钥/私钥对。通过PKCS获取CryptoAPI公钥#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,我不能让公共密钥。我也尝试过其他属性。 有没有办法做到这一点?

编辑

由于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,但我只对公钥感兴趣。我省略了私人模板。 这里有什么问题?

回答

2

CKA_PRIVATE根本不表示私钥。

当CKA_PRIVATE属性为真,用户可能无法访问对象,直到用户 已被认证令牌

相反,你应该寻找为CKA_CLASS这样的属性与价值CKO_PUBLIC_KEYCKO_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_BYTE数组的指针时,删除CK_ATTRIBUTE中的引用符号 - 在你的情况下模数

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)} 

我没有测试你的代码,但我可以通过设置下面的模板,使以C_GetAttributeValue呼叫成功获得CK_OBJECT_HANDLE模量(私钥/公钥):

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

虽然这已经回答了别人谁想要做到这一点,我们已经创建了一个基于PKCS#11 WR冲击片雷管的CryptoAPI的,你可以在这里找到:

https://github.com/PeculiarVentures/pvpkcs11

有了这个,你可以使用本地PKCS#11接口访问存储在CryptoAPI的以及证书的密钥。