如何使用带有python的智能卡发出TLS请求?



我尝试使用python库"请求"与受智能卡保护的网站进行通信。这意味着SSL中的强身份验证:您必须提供客户端证书(证书和私钥(。

由于我使用的是智能卡,因此无法读取作为正常保护的私钥(仅读取模数(。我可以使用python库PyKCS11读取智能卡:一旦给定密码,所有证书,公钥和私钥模数。

如何混合请求和 PyKCS11 ?
如何在智能卡中使用客户端证书发出SSL请求?

编辑 2017/08/04

在我的 Mac 上:

  • brew install openssl
  • brew install opensc
  • brew install engine_pkcs11
  • 开放SSL课程 engine dynamic -pre SO_PATH:/usr/local/Cellar/engine_pkcs11/0.1.8/lib/engines/engine_pkcs11.so -pre ID:pkcs11 -pre LIST_ADD:1 -pre
    • LOAD -pre MODULE_PATH:/usr/local/lib/(my specific pkcs11 lib(.dylib 加载: (pkcs11
      • ( pkcs11 引擎
    • s_client -引擎 PKCS11 -键"(插槽(:(id(" -键窗体引擎 -证书"PEM.cer" -连接(主机(:443 -状态 -调试
      • SSL 握手正常

我现在的问题是 pyOpenSSl 在 API 中没有选择引擎的函数(如 pkcs11(。所以我被阻止了。我不能使用python。

我遇到了类似的问题,除了我在 Windows 上并且需要使用"capi"引擎来处理智能卡客户端证书。我有一个使用 cffi 的工作代码和使用 pyopenssl 的请求,我希望将其更改为支持 pkcs11 应该不会太困难。

import os
import ssl
import sys
import cffi
import requests
pyopenssl = requests.packages.urllib3.contrib.pyopenssl
pyopenssl.inject_into_urllib3()
# I use anaconda and these paths are valid for me, change as required
libcryptopath = os.path.join(sys.prefix, "Library", "bin", "libcrypto-1_1-x64.dll")
libsslpath = os.path.join(sys.prefix, "Library", "bin", "libssl-1_1-x64.dll")
capipath = os.path.join(sys.prefix, "Library", "lib", "engines-1_1", "capi.dll")
ffi = cffi.FFI()
ffi.cdef(
"void *ENGINE_by_id(const char *id);"
"int ENGINE_ctrl_cmd_string(void *e, const char *cmd_name, const char *arg, int cmd_optional);"
"int ENGINE_init(void *e);"
"int SSL_CTX_set_client_cert_engine(void *ctx, void *e);"
)
try:
libcrypto, libssl, engine
except NameError:
libcrypto = ffi.dlopen(libcryptopath)
libssl = ffi.dlopen(libsslpath)
engine = libcrypto.ENGINE_by_id(b"dynamic")
libcrypto.ENGINE_ctrl_cmd_string(engine, b"SO_PATH", capipath.encode(), 0)
libcrypto.ENGINE_ctrl_cmd_string(engine, b"LOAD", ffi.NULL, 0)
libcrypto.ENGINE_init(engine)

class PyOpenSSLContextCAPI(pyopenssl.PyOpenSSLContext):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
libssl.SSL_CTX_set_client_cert_engine(self._ctx._context, engine)

# https://lukasa.co.uk/2017/02/Configuring_TLS_With_Requests/
class HTTPAdapterCAPI(requests.adapters.HTTPAdapter):
def init_poolmanager(self, *args, **kwargs):
context = PyOpenSSLContextCAPI(ssl.PROTOCOL_TLS)
kwargs['ssl_context'] = context
return super().init_poolmanager(*args, **kwargs)

class SessionCAPI(requests.Session):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.mount("https://", HTTPAdapterCAPI())

if __name__ == '__main__':
s = SessionCAPI()
r = s.get("https://example.com")
print(r.text)

我会尝试使用:

  • OpenSSL with PKCS#11(可能使用 pkcs11 引擎 https://github.com/OpenSC/libp11(
  • pyOpenSSL

它适用于M2Crypto:

def InitPKCS11Engine(id, dllPath):
Engine.load_dynamic()
e = Engine.Engine('dynamic')
e.ctrl_cmd_string('SO_PATH', dllPath)
e.ctrl_cmd_string('ID', id)
e.ctrl_cmd_string('LIST_ADD', '1')
e.ctrl_cmd_string('LOAD', None)
return e

之后,您可以添加特定的 pkcs11 库并添加引脚。

最新更新