【问题标题】:PKCS11, OBJECT PINPKCS11,对象引脚
【发布时间】:2016-04-05 11:18:39
【问题描述】:

我正在为网络应用程序制作 pkcs11 模块。它是证书的远程存储,并提供用于签名数据的 API。用于签名的 API 如下所示: sign(int CertificateId, char* Password, void* data, int lenght)

在 pkcs11 模块中,整个存储由一个令牌表示。在 C_Initialize 部分,我对服务器进行身份验证。我找到了另一个 API 调用的对象,一切都很好。问题是,当我调用 C_SignInit 或 C_Sign 函数时,我不知道如何为我的对象获取二级密码。 谁能帮帮我?

【问题讨论】:

    标签: c pkcs#11


    【解决方案1】:

    在 PKCS#11 中,所有对象都使用用户 PIN 进行保护。他们没有自己的 PIN。因此,没有标准方法可以为特定对象请求不同的 PIN。

    【讨论】:

    • 那么如果我有n个不同的私钥,我必须制作n个令牌?
    • @OndřejPřikryl 不,您可以在令牌上拥有多个密钥,但它们需要使用同一个 PIN 进行保护,并在 C_Login 函数中传递。
    【解决方案2】:

    PKCS#11 的想法是使用 1 个密码 (PIN) 来保护整个令牌。位于同一令牌上的密钥的二级身份验证已完全排除在协议之外。如 2.01 规范所述:

    使用受二级身份验证保护的私钥使用与使用仅受登录 PIN 保护的私钥相同的过程和调用顺序。事实上,为 Cryptoki 版本 2.01 编写的应用程序将使用二次认证,无需修改。

    这意味着:“二级身份验证不是我们的问题。这些机制必须在我们的协议之外实现”。

    但是,他们描述了一种技巧,当密钥实际上位于同一个令牌上时会暴露多个 PIN here

    2.11 规范链接:here

    【讨论】:

      【解决方案3】:

      如果您将保护 .pfx 或 .pvk 文件中的私钥的密码称为“辅助密码”,那您就错了。这些密码用于保护那些文件(.pfx 或 .pvk)中的私钥,而不是 HSM 文件。没有其他密码可以保护 HSM 中的密钥。如果你想调用 api 函数,你必须使用用户或管理员 PIN 登录。

      【讨论】:

      • 那么如果我有n个不同的私钥,我必须制作n个令牌?
      • 不,您可以创建具有不同名称的不同密钥。您可以使用带有对象 ID 的键。您可以通过搜索它们的名称找到键的对象 ID。
      • 我不认为你说得对。我不想创建密钥,我希望用户给我 PIN,我可以从用户那里获取 PIN 的唯一功能是 C_Login,还是我错了?
      【解决方案4】:

      正如 Eugene Mayevski writes 在 PKCS#11 中没有“对象 PIN”这样的概念。

      您可以实现以下架构的一些变体以获得类似的访问控制模型:

      注册密钥对:

      1. 通过C_GenerateKeyPair 生成密钥对,并确保将私钥生成为仅会话对象(即使用CKA_TOKEN==FALSE)。另一种方法是以某种方式导入密钥对(此处不讨论)。

      2. 生成一个强密码(或使用用户提供的密码)并通过一些KDF 运行它以获得“解锁密钥”。将此“解锁密钥”保存在您的应用程序内存中。

      3. 生成一个新的持久对称“派生密钥”,它只允许密钥派生(即CKA_TOKEN==TRUECKA_DERIVE==TRUE)使用例如CKM_AES_KEY_GEN

      4. 派生一个新的“包装密钥”会话专用密钥对象,例如使用CKM_AES_CBC_ENCRYPT_DATA 使用“解锁密钥”字节作为输入多样化数据并使用“派生密钥”作为主密钥。新密钥应该是一个仅限会话的对象,并且应该只允许密钥包装(即CKA_TOKEN==FALSECKA_WRAP==TRUE)。

      5. 使用“wrap key”将步骤 1 中的私钥对象包装到“key blob”中。

      6. 存储“key blob”(在令牌内部或外部)。

      7. 从步骤 1 中删除私钥和“包装密钥”。 Nuke 密码和“解锁密钥”。 (即使前面的某些步骤失败,也要执行此步骤)

      8. 不知道密码就不能访问私钥。

      使用密钥对:

      1. 通过同一个KDF运行输入密码,得到“解锁密钥”。

      2. 以与密钥注册期间相同的方式派生“包装密钥”,但这次仅用于解包(即CKA_TOKEN==FALSECKA_UNWRAP==TRUE)。

      3. 将“密钥 blob”解包到新的仅限会话的私钥对象中。

      4. 删除“包装密钥”。 Nuke 密码和“解锁密钥”。 (即使前面的某些步骤失败,也要执行此步骤)

      5. 随意使用密钥对。

      6. 删除私钥。 (即使前面的某些步骤失败,也要执行此步骤)

      擦除密钥对:

      1. 删除关联的“派生密钥”和“密钥 blob”。

      一些额外的(随机的)注释:

      • 使用的 AES 机制只是示例。如果使用CKM_AES_CBC_ENCRYPT_DATA,则必须将使用过的 IV 与“key blob”一起存储。

      • 非常注意所有对象属性值(即,拒绝所有不需要的东西)。如果您的设备支持某些供应商定义的扩展来控制对象的使用,请务必使用它们(例如,强制执行允许的包装/解包/派生机制)。

      • 记得从内存/会话中擦除/删除密码和临时密钥。

      • 使用供应商特定的包装机制,因为它们可能提供更好的保护(如果可能的话)。

      • 删除会话对象的便捷方法是关闭会话。

      • 如果包装机制未提供“密钥 blob”,您可能希望保护它的完整性。

      祝你好运!

      免责声明:我不是加密专家,所以请验证我的想法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-07
        • 1970-01-01
        • 1970-01-01
        • 2010-11-26
        相关资源
        最近更新 更多