首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >pkcs11engine不会在引擎清理()之后退出

pkcs11engine不会在引擎清理()之后退出
EN

Stack Overflow用户
提问于 2013-01-09 06:05:33
回答 1查看 362关注 0票数 0

我想做以下几点:

  1. 在安全令牌上生成密钥对(我使用阿拉丁令牌) (PyKCS11)
  2. 生成PKCS#10请求(我对其使用M2Crypto + engine_pkcs11 )并将其发送到CA。
  3. 从CA接收签名的X.509证书,并将其写入安全令牌。

请求生成如下所示:

代码语言:javascript
运行
复制
    def generate_request(
        self, uid, cn=None, user_pin=None, keyid=TOKEN_TEMP_KEY_ID):
    """Generate PKCS#10 certificate request
    @param keyid: ID of key to use for certificate request generation
    @type keyid: str
    @param uid: UID to put in request subject distinguished name
    @type uid: str
    @param cn: Common name (if any) of subject to use for certificate
    request generation
    @type cn: str
    @param user_pin: user PIN code. User privileges are required for
    signing of certificate request
    @type user_pin: str
    @return PKCS10 request in PEM format signed by token's private key
    """
    Engine.load_dynamic()
    e = Engine.Engine('dynamic')
    e.ctrl_cmd_string('SO_PATH', PKCS11_ENGINE_PATH)
    e.ctrl_cmd_string('LIST_ADD', '1')
    e.ctrl_cmd_string('LOAD', None)
    e.ctrl_cmd_string('MODULE_PATH', PKCS11_LIBRARY_PATH)
    a = Engine.Engine('pkcs11')
    a.init()
    # Hex-encoded key id should be provided to that function
    k = a.load_private_key(hexlify(keyid), pin=user_pin)
    req = X509.Request()
    subject_name = PKCS10_DN_PREFIX + (('UID', MBSTRING_ASC, uid, -1, -1, 0),)
    if cn:
        subject_name = subject_name + (('CN', MBSTRING_ASC, cn, -1, -1, -1),)
    name = X509.X509_Name()
    for entry in subject_name:
        name.add_entry_by_txt(*entry)
    req.set_subject(name)
    req.set_pubkey(k)
    req.sign(k, 'sha1')
    reqpem = req.as_pem()
    Engine.cleanup()
    return reqpem

下面是将证书写入安全令牌的代码:

代码语言:javascript
运行
复制
def write_certificate(self, cert_pem, so_pin):
    """Write certificate to token
    @param cert_pem: certificate in pem format
    @type cert_pem: str
    @param so_pin: PIN code of security officer
    @type so_pin: str
    """
    cert = X509.load_cert_string(cert_pem)
    if cert.check_ca(): # What label to use?
        label = TOKEN_CA_CERT_LABEL
    else:
        label = TOKEN_USER_CERT_LABEL
    tCert = (
        (PyKCS11.LowLevel.CKA_CLASS, PyKCS11.LowLevel.CKO_CERTIFICATE),
        (PyKCS11.LowLevel.CKA_CERTIFICATE_TYPE, PyKCS11.LowLevel.CKC_X_509),
        (PyKCS11.LowLevel.CKA_TOKEN, True),
        (PyKCS11.LowLevel.CKA_PRIVATE, False),
        (PyKCS11.LowLevel.CKA_LABEL, label),
        (PyKCS11.LowLevel.CKA_ID, make_key_id(cert.get_pubkey())),
        (PyKCS11.LowLevel.CKA_SUBJECT, cert.get_subject().as_der()),
        (PyKCS11.LowLevel.CKA_ISSUER, cert.get_issuer().as_der()),
        (PyKCS11.LowLevel.CKA_SERIAL_NUMBER, cert.get_serial_number()),
        (PyKCS11.LowLevel.CKA_VALUE, cert.as_der()))
    s = self.lib.openSession(self.slot, PyKCS11.CKF_RW_SESSION)
    s.login(so_pin, PyKCS11.LowLevel.CKU_SO)
    s.createObject(tCert)
    s.logout()
    s.closeSession()

问题是,在请求生成之后,我得到了CKR_USER_ANOTHER_ALREADY_LOGGED_IN错误。我查看了engine_pkcs11源代码,在engine_pkcs11.c (pkcs11.c)文件中有一个名为static EVP_PKEY *pkcs11_load_key的函数。它很长,所以这里是它的一部分:

代码语言:javascript
运行
复制
    /* Now login in with the (possibly NULL) pin */
    if (PKCS11_login(slot, 0, pin)) {
        /* Login failed, so free the PIN if present */
        if (pin != NULL) {
            OPENSSL_cleanse(pin, pin_length);
            free(pin);
            pin = NULL;
            pin_length = 0;
        }
        fail("Login failed\n");
    }

因此,正如我所理解的,登录是在使用密钥时执行的(PKCS#10请求生成需要密钥)。如果执行登录,我相信也应该执行相应的注销,但我找不到。下面是ENGINE_finish()函数的来源:

代码语言:javascript
运行
复制
int pkcs11_finish(ENGINE * engine)
{
    if (ctx) {
    PKCS11_CTX_unload(ctx);
    PKCS11_CTX_free(ctx);
    ctx = NULL;
}
if (pin != NULL) {
    OPENSSL_cleanse(pin, pin_length);
    free(pin);
    pin = NULL;
    pin_length = 0;
}
return 1;
}

是否有可能在第2步以某种方式(可能隐式)从安全令牌进行注销)?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-01-09 18:06:09

最后,我可以这样做:

在加载引擎之前,我打开新会话并在完成工作后登录到其中,然后关闭会话(仅使用closeSession()是不够的)

所以请求生成就是这样完成的。

代码语言:javascript
运行
复制
    s = self.lib.openSession(self.slot, PyKCS11.CKF_RW_SESSION)
    s.login(user_pin)
    Engine.load_dynamic()

..。我在清理引擎后加上了

代码语言:javascript
运行
复制
    a.finish()
    Engine.cleanup()        
    s.logout()
    s.closeAllSessions()

我还必须对PyKCS11源代码中的会话类进行一些修补,因为存在一个错误(closeAllSession而不是closeAllSessions):

代码语言:javascript
运行
复制
def closeAllSessions(self):
    """
    C_CloseAllSessions
    """
    rv = self.lib.C_CloseAllSessions(self.slot)
    if rv != CKR_OK:
        raise PyKCS11Error(rv)

希望这能帮上忙

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14229187

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档