PKCS11,对象引脚

PKCS11,对象引脚,c,pkcs#11,C,Pkcs#11,我正在为网络应用制作pkcs11模块。它是证书的远程存储,并提供用于签名数据的API。用于签名的API如下所示: 符号(整数证书ID、字符*密码、无效*数据、整数长度) 在pkcs11模块中,整个存储由一个令牌表示。在C_Initialize部分中,我向服务器进行身份验证。我通过另一个API调用找到对象,一切都很好。问题是,当我调用C_SignInit或C_Sign函数时,我不知道如何获取对象的辅助密码。 有人能帮我吗?在PKCS#11中,所有对象都受到用户PIN的保护。他们没有自己的别针。因此

我正在为网络应用制作pkcs11模块。它是证书的远程存储,并提供用于签名数据的API。用于签名的API如下所示: 符号(整数证书ID、字符*密码、无效*数据、整数长度)

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

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

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

作为Eugene Mayevski,PKCS#11中没有“对象PIN”这样的概念

您可以实现以下模式的某些变体,以获得类似的访问控制模型:

注册密钥对:

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

  • 生成一个强密码(或使用用户提供的密码),并在其中运行以获得“解锁密钥”。将此“解锁钥匙”保留在应用程序内存中

  • 生成一个新的持久对称“派生密钥”,该密钥仅允许密钥派生(即
    CKA\u令牌==TRUE
    CKA\u派生==TRUE
    ),例如使用
    CKM\u AES\u key\u GEN

  • 使用例如
    CKM_AES_CBC_ENCRYPT_DATA
    和“unblocking key”字节作为输入数据,并使用“派生密钥”作为主密钥,派生新的“wrap key”会话专用密钥对象。新密钥应该是仅会话的对象,并且应该只允许密钥包装(即
    CKA\u-TOKEN==FALSE
    CKA\u-WRAP==TRUE

  • 使用“Wrap key”将步骤1中的私钥对象包装到“key blob”中

  • 存储“key blob”(令牌内部或外部)

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

  • 在不知道密码的情况下,不应访问私钥

  • 使用密钥对:

  • 通过相同的KDF运行输入密码以获得“解锁密钥”

  • 以与密钥注册期间相同的方式导出“包裹密钥”,但这次仅用于展开(即
    CKA\u令牌==FALSE
    CKA\u UNWRAP==TRUE

  • 将“密钥blob”展开为新的仅会话私钥对象

  • 删除“换行键”。核弹密码和“解锁钥匙”。(即使前面的某些步骤失败,也要执行此步骤)

  • 随意使用这对钥匙

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

  • 擦除密钥对:

  • 删除关联的“派生密钥”和“密钥blob”
  • 一些附加(随机)注释:

    • 使用的AES机制只是示例。如果使用
      CKM\u AES\u CBC\u ENCRYPT\u数据
      ,则必须将使用过的IV与“key blob”一起存储

    • 注意所有对象属性值(即拒绝所有不需要的内容)。如果您的设备支持一些供应商定义的扩展来控制对象的使用,那么一定要使用它们(例如,强制使用允许的包装/展开/派生机制)

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

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

    • 删除会话对象的一种方便方法是关闭会话

    • 如果包装机制不提供“key blob”,则可能需要保护其完整性

    祝你好运

    Desclaimer:我不是密码专家,所以请验证我的想法。

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

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

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

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


    链接到2.11规范:

    因此,如果我有n个不同的私钥,我必须生成n个令牌?不,您可以使用不同的名称创建不同的密钥。你可以通过使用对象ID来使用键。你可以通过搜索键的名称来找到键的对象ID。我想你没有理解我的意思。我不想创建密钥,我希望用户给我PIN,我可以从用户那里获得PIN的唯一功能是CřLogin,或者我错了吗?因此,如果我有n个不同的私钥,我必须生成n个令牌?@OndřejPřikryl不,您可以在令牌上有多个密钥,但它们需要通过CřLogin函数传递的同一个PIN进行保护。