通过PKCS#11获取CryptoAPI公钥

时间:2013-09-26 09:45:49

标签: c++ cryptography cryptoapi pkcs#11

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

3 个答案:

答案 0 :(得分:2)

CKA_PRIVATE根本不表示私钥。

  

当CKA_PRIVATE属性为TRUE时,用户可能无法访问该对象,直到该用户为止   已经对令牌

进行了身份验证

相反,您应该使用值CKA_CLASSCKO_PUBLIC_KEY来查找CKO_PRIVATE_KEY等属性,可能还会使用其他属性来进一步过滤结果。

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

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

答案 1 :(得分: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 
}

答案 2 :(得分:0)

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

https://github.com/PeculiarVentures/pvpkcs11

通过这种方式,您可以使用本机PKCS#11接口访问存储在CryptoAPI中的密钥以及证书。