【问题标题】:applet with SunMSCapi not working in linux带有 SunMSCapi 的小程序在 linux 中不起作用
【发布时间】:2014-07-15 03:37:11
【问题描述】:

我们为我们的网站创建了一个新站点,让用户可以使用我们设计的小程序签署 pdf 文档。问题是这个小程序只能在 Windows 操作系统中正常工作,我们希望将其扩展到 linux 操作系统。

当我们在 linux 中运行小程序时,我们会收到以下错误消息:

[opensc-pkcs11] 阅读器-pcsc.c:896:pcsc_detect_readers: SCardListReaders 失败:0x8010002e [opensc-pkcs11] reader-pcsc.c:1015:pcsc_detect_readers:返回:没有读者 找到 [opensc-pkcs11] reader-pcsc.c:896:pcsc_detect_readers: SCardListReaders 失败:0x8010002e [opensc-pkcs11] reader-pcsc.c:1015:pcsc_detect_readers:返回:没有读者 发现 java.security.NoSuchProviderException:没有这样的提供者: SunMSCAPI 在 sun.security.jca.GetInstance.getService(未知来源) 在 sun.security.jca.GetInstance.getInstance(Unknown Source)

我认为当我们尝试通过代码中的此调用读取存储在 Windows 操作系统中的证书时出现问题:

 KeyStore keystore = KeyStore.getInstance("Windows-MY", "SunMSCAPI"); 
            keystore.load(null, null); 
            return keystore;

这是我们用来获取证书列表的函数。

public KeyStore  obtenerCertificados() throws Exception {

            String osNombre = System.getProperty("os.name");
            String osArquitectura = System.getProperty("os.arch");
            String providerConfig = null;
            String configuracionPKCS11 = null;

            // LINUX
            if(osNombre.contains(new StringBuffer("Linux")))
                providerConfig = "name = OpenSC\nlibrary = /usr/lib/opensc-pkcs11.so\n";
            // WINDOWS
            else if(osNombre.contains(new StringBuffer("Windows")))
                if(!osArquitectura.toLowerCase().contains("x86")){
                    System.out.println("Estamos en toLowerCase().contains x86");
                    providerConfig = "name = NSS"+"\n"+
                    "nssLibraryDirectory = "+"C:/Archivos de programa/Mozilla Firefox"+"\n"+
                    "nssSecmodDirectory = "+"C:/Users/SM/AppData/Local/Mozilla/Firefox/Profiles/plmk3eh9.default"+"\n"+
                    "nssDbMode = readOnly" + "\n" +
                    "nssModule = keystore" + "\n" + 
                    "\r";

                }
                else{
                    System.out.println("Estamos en NO toLowerCase().contains x86");
                    providerConfig = "name = NSS"+"\n"+
                    "nssLibraryDirectory = "+"C:/Program Files (x86)/Mozilla Firefox"+"\n"+
                    "nssLibrary = "+"C:/Program Files (x86)/Mozilla Firefox/softokn3.dll"+"\n"+
                    "nssSecmodDirectory = "+"C:/Users/SM/AppData/Roaming/Mozilla/Firefox/Profiles/plmk3eh9.default"+"\n"+
                    "nssDbMode = readOnly" + "\n" +
                    "nssModule = keystore" + "\n" + 
                    "\r";

                }
            // MAC OS
            else {providerConfig = "name = OpenSC\nlibrary = /Library/OpenSC/lib/opensc-pkcs11.so\n";}

            ByteArrayInputStream localByteArrayInputStream = new ByteArrayInputStream(providerConfig.getBytes());
            SunPKCS11 _pk11provider = null;
            try {
            _pk11provider = new SunPKCS11(localByteArrayInputStream);
            Security.addProvider(_pk11provider); 
//          _pk11provider.login(new Subject(), new DialogCallbackHandler());
            }catch(Throwable e){
            System.out.println(e.getMessage());
            }
            KeyStore keystore = KeyStore.getInstance("Windows-MY", "SunMSCAPI"); 
            keystore.load(null, null); 
            return keystore;


            }

关于如何将此用途扩展到 linux 和 MAC 的任何想法?

非常感谢您的帮助!!

【问题讨论】:

    标签: java certificate keystore pkcs#11


    【解决方案1】:

    您不能在 Linux 或 MAC OS X 中使用 SunMSCAPI 提供程序,此提供程序是 Windows 特定的,它处理 Windows 密钥库。如果您想通过SunPKCS11 提供程序在 Linux 或 MAC OS X 中使用智能卡或 Firefox 密钥库,您必须获得一个 java.security.KeyStore 的实例,将 SunPKCS11 作为提供程序传递,就像您使用 SunMSCAPI 所做的那样,即:

            ByteArrayInputStream confStream = ...// your configuration
            SunPKCS11 pkcs11 = new SunPKCS11(confStream);
            Security.addProvider(pkcs11);
            KeyStore ks = KeyStore.getInstance("PKCS11", pkcs11);
            ks.load(null, "your_pin".toCharArray());
    

    使用此代码,您可以将配置的 PKCS11 中的密钥加载到 Keystore ks

    如果您希望稍后由第三方引入您的 PKCS11 引脚,还有另一种方法。为此,您可以使用java.security.KeyStore.CallbackHandlerProtection 参数初始化您的密钥库,如下所示:

            ByteArrayInputStream confStream = ...// your configuration
            SunPKCS11 pkcs11 = new SunPKCS11(confStream);
            Security.addProvider(pkcs11);
            KeyStore.CallbackHandlerProtection cbhp = new KeyStore.CallbackHandlerProtection(new PinInputHandler(msg));
            KeyStore.Builder builder = KeyStore.Builder.newInstance("PKCS11", pkcs11, cbhp);
            builder.getKeyStore();
    

    请注意,第二个示例中的 PinInputHandler 必须实现:javax.security.auth.callback.CallbackHandler

    此外,在您的代码中,您似乎永远不会通过 SunPKCS11 提供程序加载 PKCS11 密钥(即使在 Windows 情况下),因为您没有使用 SunPKCS11 实例化密钥库,您只是使用 Security.addProvider 方法将其添加为提供程序并且您始终只使用SunMSCAPI 实例化一个密钥库,但可能在 Windows 中您会获得一些智能卡密钥,因为如果您为智能卡安装 Windows 驱动程序,您可以通过 Windows 密钥库获取它们的密钥。

    希望这会有所帮助,

    【讨论】:

      猜你喜欢
      • 2019-01-17
      • 2021-12-16
      • 1970-01-01
      • 1970-01-01
      • 2012-12-06
      • 2016-05-25
      • 2011-08-30
      • 1970-01-01
      相关资源
      最近更新 更多