Java 9 中的 SunPKCS11 提供程序

2022-09-01 17:40:08

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

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

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

在Java 8中,该类在JDK中被删除。因此,我必须通过反思对上一个调用进行编程。sun.security.pkcs11.SunPKCS11

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

  • 构造函数已更改为空构造函数。配置由“configure”方法加载,因此它必须位于磁盘上的文件中,并且我无法再通过流将其加载到字符串中。SunPKCS11

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

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”,所以我不能为每个智能卡有一个提供商。

这种情况也会发生在其他人身上吗?任何解决方案?


答案 1

我注意到正在查看用于配置的javadoc:

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

这向我表明,这里使用的是原型模式,并且用于创建多个提供程序的新控制流将如下所示:

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);

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

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


答案 2

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

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

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

格式属性 = 值后面的示例配置将是:

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

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


推荐