【问题标题】:How to suppress PIN Error Dialog from Keystore.load when Keystore is a USB cryptotoken当 Keystore 是 USB 加密令牌时,如何从 Keystore.load 抑制 PIN 错误对话框
【发布时间】:2016-05-03 05:30:44
【问题描述】:

您好,我正在使用 SUN PKCS11 实现使用 USB 加密令牌中的 PKI 证书执行操作

我为特定的 USB 令牌创建了一个提供程序对象,然后调用

Keystore ks =  KeyStore.getInstance(PKCS11_KEYSTORE_TYPE,prov);

然后我用

加载它
keyStore.load(null, PIN.toCharArray())

PIN 是用户为特定证书输入的 PIN

现在,当由于错误的 PIN 码导致加载失败时,不同的加密令牌的行为会有所不同。 Keystore::load 但是当 PIN 错误时抛出 IOException,

例如。

  1. Watchdata USB 令牌首先抛出一个对话框,其中包含一条消息“PIN is 错误的。 X 尝试离开”然后抛出 IOException。
  2. Gemalto 和 Fietian 不抛出对话框,而只抛出一个 IO异常

我想为所有 USB 类型显示 PIN 错误消息,但如果我添加自己的对话框,那么在 WatchData 上我最终会收到 2 个对话框 (1 from Watchdata & 1 of my own).

有没有办法判断错误信息是否已经显示?或者有没有办法抑制显示自己的加密狗上的错误对话框?

【问题讨论】:

  • 你好@user93353。您使用的是供应商 PKCS#11 模块(如 Watchdata 的 libwdpkcs_icp.so)还是 opensc-pkcs11.so?
  • @SebB - 使用供应商 PKCS#。
  • WatchKey Token Tool* 安装日志中,我看到了有趣的模块:WDPKCS.dll, WDICP_P11_CCID_v34.dll,...。你在加载哪一个?
  • 尝试改用WDICP_P11_CCID_v34.dll。在WDPKCS.dll export-table 我看到了典型的 PKCS#11 函数 + 一些 Watchdata 的函数 (WD***)
  • 这个文件在使用WDPKCS.dll时也可能很有趣:C:\Windows\SysWOW64\WatchData\Watchdata ICP CSP v1.0\WatchSafe.ini。我看到RetryTimes=4,MinPinLen=5,P11Message=1,...

标签: java security usb pkcs#11


【解决方案1】:

该行为是特定于令牌的,因为标准没有指定驱动程序必须如何准确地表现。所以显示窗口是你无法控制的。您可以做的最好的事情是联系特定设备的供应商并寻求帮助。

【讨论】:

    【解决方案2】:

    编辑:

    Watchdata 似乎有 2 个 PKCS#11 模块:

    • WDICP_P11_CCID_v34.dll: Vanilla PKCS#11 impl
    • WDPKCS.dll: PKCS#11 + 自定义函数 (ICP CSP v1.0)。
      这里是 什么,显然似乎是配置文件: C:\Windows\SysWOW64\WatchData\Watchdata ICP CSP v1.0\WatchSafe.ini

    避免“PIN 错误对话框”的可能解决方案: WDPKCS.dll WDICP_P11_CCID_v34.dll

    参考资料: ProxKey User ManualWatchKey USB Token Tools


    您要抑制的错误对话框,它的外观如何?本国的?还是 Java/Swing 之类的?
    这个过程涉及到很多“层”。


    1. 让我们将流程分为 4 层:
      1-PKCS#11(native); 2-Wrappers[IAIK, SUN, Vendors]; 3-Providers[IAIK, SUN]; 4-JCA/JCE 因此,您的“错误对话框”来自这些层之一。
      从第 1 层开始:您的控制权较少,您可以联系供应商,就像 @Eugene 写的那样。
      从第 2 层到第 4 层,您的控制权会增加,因此如果您实施正确的回调,您可能会对此有所作为。
    2. 提供者和包装者
      Sun:
      -sun.security.pkcs11.SunPKCS11
      -sun.security.pkcs11.wrapper
      IAIK:
      -iaik.pkcs.pkcs11.provider
      -iaik.pkcs.pkcs11.wrapper
    3. 控制:
      使用java.security.AuthProvideriaik.pkcs.pkcs11.provider.DefaultLoginManager,您可能可以控制,如果它来自提供商的话。
      如果还不够,请尝试使用包装器或两者兼而有之。
    4. 代码测试:
      使用 java.security.AuthProvider,我仍然可以从设备中看到 CKR_PIN_INCORRECT,但现在我可以从登录中捕获 LoginException

      public static void main(String[] args) {
          /*
              Properties config = new Properties();
              config.put("library", "/path/someVendor_pkcs11.dll");
              config.put("name", "Token1");
          */      
          try {
      
              SunPKCS11 result = new SunPKCS11("res/pkcs11.cfg");
              if (result.getService("KeyStore", "PKCS11") == null) {
                  throw new RuntimeException("No PKCS#11 Service available. Probably Security Token (Smartcard) not inserted");
              }
      
              // Register the Provider 
              if (Security.getProvider(result.getName()) != null) {
                  Security.removeProvider(result.getName());
              }
      
              Security.addProvider(result);
              //throw new RuntimeException("Failed to install SUN PKCS#11 Provider",e);
      
              AuthProvider pkcs11Prov = result; 
              //Provider pkcs11Prov = result; //no possibility of explicit login
              pkcs11Prov.login(new Subject(), new SwingPasswordCallbackHandler()); //explicit login
      
              CallbackHandlerProtection pwCallbackProt = new CallbackHandlerProtection( new SwingPasswordCallbackHandler() );         
              KeyStore.Builder builder = KeyStore.Builder.newInstance("PKCS11", pkcs11Prov, pwCallbackProt);
              KeyStore ks = builder.getKeyStore();        
      
              for(Enumeration<String> aliases = ks.aliases(); aliases.hasMoreElements(); ) {
                  String alias = aliases.nextElement();
                  System.out.println(alias);
      
                  // print certifcate
                  Certificate cert = ks.getCertificate(alias);
                  if (cert != null) {
                      System.out.print(" Certificate found. type="+cert.getType());
      
                      if (cert instanceof X509Certificate){
                          System.out.print(" SubjectDN="+((X509Certificate)cert).getSubjectDN());
                      }
                      System.out.println();
                  }
      
                  // private key is accessed without password 
                  Key pk = ks.getKey(alias, null);
                  if (pk != null) {
                      System.out.println(" Private key found. algorithm="+pk.getAlgorithm());
                  }
      
                  System.out.println();
              }
      
          } catch (KeyStoreException e) {
              throw new RuntimeException("Failed to load PKCS#11 Keystore",e);            
          } catch (LoginException e) {
              System.out.println("LoginException: Here, you can SWING!!!");
              e.printStackTrace();
          } catch (UnrecoverableKeyException e) {
              e.printStackTrace();
          } catch (NoSuchAlgorithmException e) {
              e.printStackTrace();
          }
      }
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-20
      • 2011-02-02
      • 2012-10-21
      • 1970-01-01
      • 2021-10-14
      • 2014-05-03
      • 1970-01-01
      • 2013-05-03
      相关资源
      最近更新 更多