需要帮助使用M2Crypto.Engine访问USB令牌

2 投票
6 回答
7115 浏览
提问于 2025-04-15 18:51

我正在使用 M2Crypto-0.20.2。我想用 OpenSC 项目的 engine_pkcs11 和 Aladdin PKI 客户端来进行基于令牌的身份验证,并通过 SSL 进行 xmlrpc 调用。

from M2Crypto import Engine

Engine.load_dynamic()
dynamic = Engine.Engine('dynamic')
# Load the engine_pkcs from the OpenSC project
dynamic.ctrl_cmd_string("SO_PATH", "/usr/local/ssl/lib/engines/engine_pkcs11.so")
Engine.cleanup()

Engine.load_dynamic()
# Load the Aladdin PKI Client
aladdin = Engine.Engine('dynamic')
aladdin.ctrl_cmd_string("SO_PATH", "/usr/lib/libeTPkcs11.so")

key = aladdin.load_private_key("PIN","password")

这是我收到的错误信息:

key = pkcs.load_private_key("PIN","eT0ken")
File "/usr/local/lib/python2.4/site-packages/M2Crypto/Engine.py", line 70, in load_private_key
    return self._engine_load_key(m2.engine_load_private_key, name, pin)
File "/usr/local/lib/python2.4/site-packages/M2Crypto/Engine.py", line 60, in _engine_load_key
    raise EngineError(Err.get_error())
M2Crypto.Engine.EngineError: 23730:error:26096075:engine routines:ENGINE_load_private_key:not initialised:eng_pkey.c:112:

对于 load_private_key(),第一个参数应该传什么?M2Crypto 的文档没有解释这个。

我在加载引擎时没有遇到任何错误,但我不确定自己是否加载正确。看起来引擎 ID 必须是一个特定的名称,但我在任何地方都找不到这个列表。'dynamic' 对我来说是可以用的。

任何帮助都将不胜感激!

6 个回答

1

根据Becky提供的pastebin链接,我觉得在新的API中,它大概是这样的:

from M2Crypto import Engine, m2

dynamic = Engine.load_dynamic_engine("pkcs11", "/Users/martin/prefix/lib/engines/engine_pkcs11.so")

pkcs11 = Engine.Engine("pkcs11")

pkcs11.ctrl_cmd_string("MODULE_PATH", "/Library/OpenSC/lib/opensc-pkcs11.so")

r = pkcs11.ctrl_cmd_string("PIN", sys.argv[1])

key = pkcs11.load_private_key("id_01")

所以我猜,如果你把"/Users/martin/prefix/lib/engines/engine_pkcs11.so"换成"/usr/local/ssl/lib/engines/engine_pkcs11.so",再把"/Library/OpenSC/lib/opensc-pkcs11.so"换成"/usr/lib/libeTPkcs11.so",可能就能让它和Aladdin一起工作了。

2

我不太明白当前M2Crypto中的engine_init代码到底是干什么的,也不知道为什么要这样做。把ENGINE_init()改成engine_init2,并用下面的补丁更新M2Crypto,会有帮助:

Index: SWIG/_engine.i
===================================================================
--- SWIG/_engine.i  (revision 719)
+++ SWIG/_engine.i  (working copy)
@@ -44,6 +44,9 @@
 %rename(engine_free) ENGINE_free;
 extern int ENGINE_free(ENGINE *);

+%rename(engine_init2) ENGINE_init;
+extern int ENGINE_init(ENGINE *);
+
 /*
  * Engine id/name functions
  */

在这之后,下面的代码让我更进一步了(不过目前urllib还不能完全正常工作):

import sys, os, time, cgi, urllib, urlparse
from M2Crypto import m2urllib2 as urllib2
from M2Crypto import m2, SSL, Engine

# load dynamic engine
e = Engine.load_dynamic_engine("pkcs11", "/Users/martin/prefix/lib/engines/engine_pkcs11.so")
pk = Engine.Engine("pkcs11")
pk.ctrl_cmd_string("MODULE_PATH", "/Library/OpenSC/lib/opensc-pkcs11.so")

m2.engine_init2(m2.engine_by_id("pkcs11")) # This makes the trick

cert = e.load_certificate("slot_01-id_01")
key = e.load_private_key("slot_01-id_01", sys.argv[1])

ctx = SSL.Context("sslv23")
ctx.set_cipher_list("HIGH:!aNULL:!eNULL:@STRENGTH")
ctx.set_session_id_ctx("foobar")
m2.ssl_ctx_use_x509(ctx.ctx, cert.x509)
m2.ssl_ctx_use_pkey_privkey(ctx.ctx, key.pkey)

opener = urllib2.build_opener(ctx)
urllib2.install_opener(opener)
2

找到了!!!

没错,就是我之前来的地方。

其实,ENGINE_init()这个功能在M2Crypto.Engine里并没有实现。所以,只有一个解决办法:打补丁!!!(非常小的补丁……)我在Engine.py里创建了一个新的Engine方法。

def engine_initz(self):
        """Return engine name"""
        return m2.engine_initz(self._ptr)

为什么叫engine_initz?因为engine_init已经在SWIG/_engine.i里定义过了:

void engine_init(PyObject *engine_err) {
    Py_INCREF(engine_err);
    _engine_err = engine_err;
}

我其实不太清楚具体做了什么,所以我选择创建一个新的……我只是把以下内容添加到了SWIG/_engine.i里:

%rename(engine_initz) ENGINE_init;
extern int ENGINE_init(ENGINE *);

然后重新编译了__m2crypto.so,现在在启动私钥之前只需要加上“pkcs11.engine_initz()”,就可以正常工作了……

撰写回答