2

从单个 python 线程中,如下所示,我收到错误“请在任何插槽中插入令牌”,它似乎看不到我的令牌。我将代码更改为不在多处理线程内部运行,它可以工作。为了将 PyKCS11 库排除在等式之外,我还通过使用 ctypes 并包装了在 opensc 中实现的标准 pkcs11 函数进行了测试,除了从 python 线程运行时,我仍然遇到相同的问题。什么会导致这个?

从 python 线程内部使用 pkcs11 失败:

from PyKCS11 import LowLevel
import sys
from multiprocessing import Thread


class MyThread(Thread):
    def run(self):
        lib = "/usr/local/lib/opensc-pkcs11.so" # place here your PKCS#11 library
        pin = "12345678" # place here the pin of your token

        a = LowLevel.CPKCS11Lib()
        info = LowLevel.CK_INFO()
        slotList = LowLevel.ckintlist()

        loadRes = a.Load(lib, 1)
        print "Load of library '%s' : %s " % (lib, str(loadRes) )
        if not loadRes: 
            sys.exit(1)
        print "C_GetInfo: rv=" , hex(a.C_GetInfo(info))
        print "Library manufacturerID: ", info.GetManufacturerID()
        # listing only slots with a token inside.
        rv = a.C_GetSlotList(1, slotList)
        if (rv != LowLevel.CKR_OK): 
            sys.exit(1)
        if len(slotList) == 0:
            print "Please insert a token in any slot"
            sys.exit(1)


mythread = MyThread()
mythread.start()
mythread.join()

在 Thread 之外使用 pkcs11 可以:

from PyKCS11 import LowLevel
import sys

def run(self):
        lib = "/usr/local/lib/opensc-pkcs11.so" # place here your PKCS#11 library
        pin = "12345678" # place here the pin of your token

        a = LowLevel.CPKCS11Lib()
        info = LowLevel.CK_INFO()
        slotList = LowLevel.ckintlist()

        loadRes = a.Load(lib, 1)
        print "Load of library '%s' : %s " % (lib, str(loadRes) )
        if not loadRes: 
            sys.exit(1)
        print "C_GetInfo: rv=" , hex(a.C_GetInfo(info))
        print "Library manufacturerID: ", info.GetManufacturerID()
        # listing only slots with a token inside.
        rv = a.C_GetSlotList(1, slotList)
        if (rv != LowLevel.CKR_OK): 
            sys.exit(1)
        if len(slotList) == 0:
            print "Please insert a token in any slot"
            sys.exit(1)

run()

测试环境:

操作系统:OSX 优胜美地

pkcs11 中间件:opensc

4

1 回答 1

0

有关多线程和 PKCS#11 库的更多信息可以在 PKCS#11 v2.20 规范的第 6.6.2 章中找到:

6.6.2 应用程序和线程

一些应用程序将以多线程方式访问 Cryptoki 库。Cryptoki 使应用程序能够向库提供信息,以便它们可以为多线程提供适当的支持。特别是,当应用程序通过调用 C_Initialize 来初始化 Cryptoki 库时,它可以为库指定四种可能的多线程行为之一:

  1. 应用程序可以指定它不会从多个线程同时访问该库,因此该库不必担心为了线程安全而执行任何类型的锁定。
  2. 应用程序可以指定它将从多个线程同时访问该库,并且该库必须能够使用本机操作系统同步原语以确保正确的线程安全行为。
  3. 应用程序可以指定它将从多个线程同时访问库,并且库必须使用一组应用程序提供的同步原语来确保正确的线程安全行为。
  4. 应用程序可以指定它将从多个线程同时访问该库,并且该库必须使用本机操作系统同步原语或一组应用程序提供的同步原语来确保正确的线程安全行为。

IMO 多线程应用程序中最常用的类型是第 2 类。要激活它,您需要将CKF_OS_LOCKING_OK标志传递给C_Initialize函数。以下代码显示了如何在 C# 中使用 Pkcs11Interop 库实现这一点:

Pkcs11 pkcs11 = new Pkcs11(libraryPath);

CK_C_INITIALIZE_ARGS initArgs = new CK_C_INITIALIZE_ARGS();
initArgs.Flags = CKF.CKF_OS_LOCKING_OK;

CKR rv = pkcs11.C_Initialize(initArgs);
if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED))
    throw new Pkcs11Exception("C_Initialize", rv);

我相信您需要在 Python 中使用类似的代码。只是在这里猜测,但也许您需要将一些参数传递给LowLevel.CPKCS11Lib()

于 2016-08-02T11:07:46.643 回答