如何通过模板获取PKCS11公钥

How to get PKCS11 PublicKey via Template

我有一个 GO 应用程序,它通过软件令牌中的 opencryptoki (pkcs11) 将其证书存储到 HSM。但这不是一个 go 问题,我认为更像是一个一般的 pkcs11 问题。

我这样设置我的证书和私钥:

    certTemplate := []*pkcs11.Attribute{
        pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_CERTIFICATE),
        pkcs11.NewAttribute(pkcs11.CKA_CERTIFICATE_TYPE, pkcs11.CKC_X_509),
        pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
        pkcs11.NewAttribute(pkcs11.CKA_VALUE, certBytes),
        pkcs11.NewAttribute(pkcs11.CKA_SUBJECT, template.SubjectKeyId),
        pkcs11.NewAttribute(pkcs11.CKA_ID, pkcs11KeyID),
    }

    privateKeyTemplate := []*pkcs11.Attribute{
        pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY),
        pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_ECDSA),
        pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true), 
        pkcs11.NewAttribute(pkcs11.CKA_ID, pkcs11KeyID),
        pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, []byte{0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}),
        pkcs11.NewAttribute(pkcs11.CKA_VALUE, ecdsaPrivKeyD),
    }

ctx.CreateObject(session, certTemplate)
ctx.CreateObject(session, privateKeyTemplate)

这非常有效。我也可以通过

获得证书
findTemplate := []*pkcs11.Attribute{
    pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
    pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_CERTIFICATE),
    pkcs11.NewAttribute(pkcs11.CKA_CERTIFICATE_TYPE, pkcs11.CKC_X_509),
}

ctx.FindObjectsInit(session, findTemplate); 
objs, b, err := ctx.FindObjects(session, numSlots)

但是我没能拿到我的 public 钥匙,正如我所料

findTemplate := []*pkcs11.Attribute{
        pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
        pkcs11.NewAttribute(pkcs11.CKA_ID, pkcs11KeyID),
        pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
    }
ctx.FindObjectsInit(session, findTemplate); 
obj, _, err := ctx.FindObjects(session, 1)

没有错误,只是 hsm 存储中没有密钥。

正如您在问题中所写,您只有 created/imported 两个永久令牌对象 - 证书对象 (CKA_CLASS = CKO_CERTIFICATE) 和私钥对象 (CKA_CLASS = CKO_PRIVATE_KEY) - 很自然您只能通过调用 FindObjectsInitFindObjects.

找到这两个对象

如果您还想找到一个 public 关键对象 (CKA_CLASS = CKO_PUBLIC_KEY),那么您需要先 create/import 它。

尽管 public 密钥是证书的一部分,但 CKO_PUBLIC_KEY 对象可能无法单独使用,并且证书也没有 CKA_PUBLIC 属性。

要获取 public 密钥,您必须检索证书的 CKA_VALUE 并使用您最喜欢的 X.509v3 证书解析器对其进行解析。结果无疑 return 编码的 public 键值或 public 键作为您最喜欢的运行时中的结构。