25

在 Java 8 之前,SunPKCS11 提供程序的加载方式如下:

Provider provider = new sun.security.pkcs11.SunPKCS11 (new ByteArrayInputStream (configFile.getBytes ()));
Security.addProvider (provider);

configFile是一个带有配置参数的字符串。因此,如果应用程序需要使用多个连接的智能卡,它可以创建多个提供程序。要访问每个提供程序,使用的名称是“SunPKCS11-”,后跟我们在配置中指定的名称。

在 Java 8 中,sun.security.pkcs11.SunPKCS11JDK 中删除了该类。所以,我不得不通过反射来编程之前的调用。

Java 9 中 PKCS#11 提供程序的操作似乎非常不同:

  • 构造SunPKCS11函数已更改为空的。配置是通过“configure”方法加载的,所以它必须在磁盘上的文件中,我不能再通过流将它加载到字符串中。

  • 如果我们尝试使用反射,则会出现以下警告:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by PruebaTarjeta (file:/C:/temp/pkcs11java9/classes/) to constructor
sun.security.pkcs11.SunPKCS11()
WARNING: Please consider reporting this to the maintainers of PruebaTarjeta
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
  • 在 Java 9 中,会自动生成一个 SunPKCS11 提供程序,并在加密提供程序列表中。可以从列表中获取并配置。问题是您只能在列表中加载一个 PKCS#11 提供程序。Java 9 文档表明我们可以使用“SunPKCS11-”后跟我们在配置中指定的名称来获取 PKCS#11 提供程序,但事实并非如此。如果我们查看提供者列表,唯一的一个是“SunPKCS11”,所以我不能每个智能卡都有一个提供者。

这是否也发生在其他人身上?有什么解决办法吗?

4

2 回答 2

23

我注意到查看 javadoc configure

将提供的配置参数应用于此提供程序实例并返回配置的提供程序。请注意,如果无法就地配置此提供程序,则会创建并返回一个新提供程序。因此,调用者应始终使用返回的提供者。

这向我表明这里使用了原型模式,并且用于创建多个提供者的新控制流将类似于:

Provider prototype = Security.getProvider("SunPKCS11");
Provider provider1 = prototype.configure(...);
Provider provider2 = prototype.configure(...);
...

至于直接使用参数而不是文件名,我对源代码进行了一些挖掘,并在以下位置找到了它sun.security.pkcs11.Config

Config(String fn) throws IOException {
    this.filename = fn;
    if (filename.startsWith("--")) {
        // inline config
        String config = filename.substring(2).replace("\\n", "\n");
        reader = new StringReader(config);

请注意带有 的行filename.startsWith("--"),此文件名直接来自 的参数configure。因此,您应该能够将配置参数作为字符串传递,只要您以字符串开头--,然后用 . 分隔您的key=value\n。(虽然我目前无法对此进行测试)。

但是,我在任何地方都找不到公开记录的这一事实,因此它可能会发生变化,并且它对不同的提供商的工作方式不同,即使用风险自负!.

于 2017-10-02T11:16:15.047 回答
3

问题是您只能在列表中加载一个 PKCS#11 提供程序。

您问题的解决方案似乎是在链接本身的文档中定义的。

要为每个实现使用多个插槽PKCS#11,或使用多个PKCS#11实现,只需使用适当的配置文件为每个插槽重复安装即可。这将为每个PKCS#11实现的每个插槽生成一个 Sun PKCS#11 提供程序实例。

遵循格式的示例配置attribute=value将是:

name = FooAccelerator
library = /opt/foo/lib/libpkcs11.so
slot = 1

您可以进一步利用同一链接中 PKCS#11 提供程序配置文件中的属性来配置多个具有不同插槽 Id 和 listIndex 以及不同属性的提供程序。

于 2017-10-02T11:28:42.347 回答