2

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

4

3 回答 3

4

CKA_PRIVATE根本不表示私钥。

当 CKA_PRIVATE 属性为 TRUE 时,用户可能无法访问对象,直到用户通过令牌的身份验证

相反,您应该寻找CKA_CLASS具有值CKO_PUBLIC_KEY或的CKO_PRIVATE_KEY属性,可能使用其他属性来进一步过滤您的结果。

如果您找不到任何CKO_PUBLIC_KEY东西,那么我认为它不是在令牌中生成的(密钥已导入,检查是否CKA_LOCAL已设置)。或者,它可能仅被创建为会话对象。最后它可能已被删除。

请注意,RSA 私钥通常确实包含公共指数,因此您仍然可以仅从私钥对象构造公钥(当然,使用模数和公共指数)。

于 2013-09-26T15:58:45.363 回答
1

在设置指向 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 
}
于 2017-01-22T00:23:49.430 回答
0

尽管其他想要这样做的人已经回答了这个问题,但我们已经为 CryptoAPI 创建了一个基于 PKCS#11 的包装器,你可以在这里找到它:

https://github.com/PeculiarVentures/pvpkcs11

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

于 2017-05-24T23:57:32.497 回答