【问题标题】:Get CryptoAPI public key via PKCS#11通过 PKCS#11 获取 CryptoAPI 公钥
【发布时间】:2013-09-26 09:45:49
【问题描述】:

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

【问题讨论】:

  • 如果你想创建一个你不应该使用C_GenerateKeyPair的公钥,你应该使用C_CreateObject创建一个公钥对象。当然,如果您尝试创建具有预设模数的 new 密钥对,它会失败。请注意,EDIT 包含一个与原始问题相当不同的问题。哦,是的,我是“owlstead”——我已经停止使用我以前的昵称了 :)

标签: c++ cryptography cryptoapi pkcs#11


【解决方案1】:

CKA_PRIVATE 根本不表示私钥。

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

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

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

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

【讨论】:

  • 好的,谢谢你的回答!!我做了一些测试,发现:私钥(即 CKA_CLASS = CKO_PRIVATE_KEY)不是本地的——可能是因为它是通过 CAPI 创建的;没有找到 CKO_PUBLIC_KEY 密钥。因此,正如您所建议的,要重新构建公钥,我们可以从私钥模板中获取 CKA_MODULUS 和 CKA_PUBLIC_EXPONENT。我试试看!
  • 如果CKA_LOCAL 未设置,那么您可能需要额外查看设置的安全性。如果私钥在令牌中生成并受到保护,则它是最安全的(如果您的密钥管理方案不允许生成新密钥,则可能需要加密备份)。
  • 如果我通过 PKCS#11 创建私钥,CKA_LOCAL 设置为 true。也许,如果未设置,则取决于 CryptoAPI 设置。我会检查它。关于公钥,我用其他细节编辑我的问题..还有其他建议吗?非常感谢
  • @andret8 为什么需要将公钥放在 PKCS#11 令牌中?公钥是公开的,因此您不需要使用加密令牌来保护它。只需在软件中重新创建公钥并直接使用即可。
【解决方案2】:

在设置指向 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 
}

【讨论】:

    【解决方案3】:

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

    https://github.com/PeculiarVentures/pvpkcs11

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

    【讨论】:

      猜你喜欢
      • 2018-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多