用于 Firefox 的 MacOS 中的 SunPKCS11 提供程序

SunPKCS11 provider in MacOS for Firefox

我设法让 SunPKCS11 在 Windows 下与 Firefox ESR 52.0 一起工作,但我无法在 MacOS 中加载它。我已经尝试了几种不同的配置并通过 PKCS11 直接加载它但没有任何效果,谁能给我一些指导?

pkcs11.cfg配置如下:

name = FirefoxKeyStore
library = "/Applications/Firefox.app/Contents/MacOS/fixed-for-java-runtime/libsoftokn3.dylib"
attributes = compatibility
nssArgs = "configdir='/Users/helloworld/Library/Application Support/Firefox/Profiles/wasdwasd.default-1453211557245' certPrefix='' keyPrefix='' secmod='secmod.db' flags='readOnly' "
slot = 2

然后在 Java 中,我试过这样加载它:

FileInputStream fis = new FileInputStream("pkcs11.cfg");
Provider provider = new SunPKCS11(fis);
Security.addProvider(provider);

但是这立即给我以下错误:

sunpkcs11: Initializing PKCS#11 library /Applications/Firefox.app/Contents/MacOS/fixed-for-java-runtime/libsoftokn3.dylib
sunpkcs11: Multi-threaded initialization failed: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_DEVICE_ERROR
Exception in thread "main" java.security.ProviderException: Initialization failed
at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:376)
at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:107)

你可能会问我为什么要从奇怪的文件夹中加载.dylib,那是因为我在MacOS中使用install_name_tool@executable_path更改为@loader_path顺序让库依赖工作(因为我试图 运行 在 Eclipse 中而不是从 Firefox 本身)。

我也尝试使用此处建议的解决方案: 但也不行...我遇到了同样的错误。

以及尝试此处提到的各种不同的配置设置:https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/PKCS11/Module_Specs#Softoken_Specific_Parameters

EDIT1

我尝试了@FaithReaper 提到的方法,但它仍然抛出相同的错误。我尝试将插槽值更改为 01-1,结果相同。加载底层 PKCS11 对象似乎有问题。

Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_DEVICE_ERROR
at sun.security.pkcs11.wrapper.PKCS11.C_Initialize(Native Method)
at sun.security.pkcs11.wrapper.PKCS11$SynchronizedPKCS11.C_Initialize(PKCS11.java:1545)
at sun.security.pkcs11.wrapper.PKCS11.getInstance(PKCS11.java:157)
at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:330)

我不知道这是否有帮助,但我 运行 FireFox 配置文件中的 modutil 并正在转储此信息:

modutil -dbdir "/Users/eto/Library/Application Support/Firefox/Profiles/ew2g332o.default-1453211557245" -rawlist

library= name="NSS Internal PKCS #11 Module" 
parameters="configdir=/Users/eto/Library/Application Support/Firefox/Profiles/ew2g332o.default-1453211557245 certPrefix= keyPrefix= secmod=secmod.db flags=readOnly " 
NSS="Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30})"

Listing of PKCS #11 Modules

  1. NSS Internal PKCS #11 Module uri: pkcs11:library-manufacturer=Mozilla%20Foundation;library-description=NSS%20Internal%20Crypto%20Services;library-version=3.33 slots: 2 slots attached status: loaded

    slot: NSS Internal Cryptographic Services token: NSS Generic Crypto Services uri: pkcs11:token=NSS%20Generic%20Crypto%20Services;manufacturer=Mozilla%20Foundation;serial=0000000000000000;model=NSS%203

    slot: NSS User Private Key and Certificate Services token: NSS Certificate DB uri: pkcs11:token=NSS%20Certificate%20DB;manufacturer=Mozilla%20Foundation;serial=0000000000000000;model=NSS%203

首先,我注意到您 insert/add Provider 与我的不同方式。您可以尝试以这种方式添加 Provider 吗? (可能无关紧要)

Provider p = new SunPKCS11(new ByteArrayInputStream(config.getBytes()));
Security.insertProviderAt(p, 1);
KeyStore.Builder builder = null;
builder = KeyStore.Builder.newInstance("PKCS11", p, 
    new KeyStore.CallbackHandlerProtection(new UtilTarjetas().new CustomCallbackHandler()));
cardKeyStore = builder.getKeyStore();

那么,也许你可以试试这里的方法:

https://github.com/avocado-framework/avocado/issues/1112

即:

apahim commented on 7 Apr 2016

@will-Do, nss folks were able to track this issue down and seems like they are going to consider a change in NSS_InitContext(), which should include a SECMOD_RestartModules(PR_FALSE) after a fork(). Anyway, they also provided a better workaround than the one I provided you. If you set the environment variable NSS_STRICT_NOFORK to DISABLED then the code is expected to work. It worked for me and I'd like to check if it works for you as well. Looking forward to see your results.

此外,一些消息来源表明这可能是令牌或插槽问题。您可以尝试将插槽索引更改为 0,或 -1

如果在 FireFox 之外执行,Mac OS X 中 Firefox 提供的库实际上可能会完全损坏或无法运行。

在尝试了许多不同的配置和方式组合后,我终于通过不使用 Firefox 的库...

使它工作

以下是让它发挥作用的分步方法:

  1. 在您的 Mac
  2. 中安装自制软件
  3. 运行 brew install nss
  4. 运行 brew install nspr
  5. 您可能需要使用 brew link nssbrew link nspr
  6. 手动 link 它们
  7. 在配置文件中,你需要将它指向你的自制软件libsoftokn3.dylib,像这样library = /usr/local/opt/nss/lib/libsoftokn3.dylib

那么你的 Java 代码应该能够在 Mac OS X 下加载 Firefox 密钥库...我已经提交了一个错误 here. The ticket contains a working sample code 关于如何实例化 PKCS11,加载 Firefox 密钥库并列出存储中的别名。

这绝对是使用 Firefox 的噩梦......但至少我让它工作了......谁会想到他们提供的库不起作用(但它在 Windows 中工作! )? :P

为了完整起见,我也将示例代码直接包含在此 post 中:

import java.io.ByteArrayInputStream;
import java.security.KeyStore;
import java.security.Provider;
import java.security.Security;
import java.util.Collections;

public class Sample {

    private KeyStore load(String lib, String profile) throws Exception
    {
        String config = "library = " + lib + "\n" + 
                "name = FirefoxKeyStore\n" + 
                "attributes = compatibility\n" + 
                "nssArgs = \"configDir='" + profile + "' certPrefix='' keyPrefix='' secmod='secmod.db' flags='readOnly,forceOpen,optimizeSpace' \"\n" + 
                "slot = 2\n";

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

        return KeyStore.getInstance("PKCS11");
    }

    public static void main(String[] args) throws Exception {

        Sample s = new Sample();

        String profile = "/Users/blah/Library/Application Support/Firefox/Profiles/yougottachangethis";
        String[] libs = { 
            //"/Applications/Firefox.app/Contents/MacOS/libsoftokn3.dylib",
            "/usr/local/opt/nss/lib/libsoftokn3.dylib"
        };

        for (String lib : libs) {
            System.out.println("TRYING >>> " + lib);
            try {
                KeyStore ks1 = s.load(lib, profile);

                ks1.load(null, null);
                for (String alias : Collections.list(ks1.aliases())) {
                    System.out.println(alias);  
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

这是来自 Mac 的 otool 的输出(包含在 FaithReaper 的评论中):

otool -L libsoftokn3.dylib
libsoftokn3.dylib:
/usr/local/opt/nss/lib/libsoftokn3.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libsqlite3.dylib (compatibility version 9.0.0, current version 253.0.0)
/usr/local/Cellar/nss/3.34/lib/libnssutil3.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/local/opt/nspr/lib/libplc4.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/local/opt/nspr/lib/libplds4.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/local/opt/nspr/lib/libnspr4.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.0.0)