使用PKCS11令牌(智能卡)进行客户端身份验证

时间:2011-02-15 16:50:51

标签: java authentication ssl smartcard pkcs#11

我必须在服务器上调用脚本(php,jsp - 什么都有)。但是此服务器受客户端身份验证保护。现在我可以使用P12-Keystore来完成它。代码:

    private void installSSLContextP12() throws Exception {
    KeyStore tks = KeyStore.getInstance(KeyStore.getDefaultType());
    tks.load(new FileInputStream("/home/dan/Dokumente/Zertifikate/store"), "xxx".toCharArray());                   // load truststore

    KeyStore iks = KeyStore.getInstance("PKCS12");
    iks.load(new FileInputStream("/home/dan/Dokumente/Zertifikate/danmocz_zert.p12"), "yyy".toCharArray());     // load private keystore

    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());            // init truststore
    tmf.init(tks);

    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    kmf.init(iks, "yyy".toCharArray());                                                                                    // load priv. key's pw
    KeyManager[] kms = kmf.getKeyManagers();


    SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);                                                          // trust/keystore
    SSLContext.setDefault(ctx);  //That is enough to authenticate at the server
}

这很好用。

但现在我有一张智能卡(PKCS11),我需要对此进行身份验证。我使用opensc-cryptocard提供程序来读取卡片。这里的示例代码(请参阅行注释!):

private void installSSLContextPKCS11() throws Exception {
    PKCS11Provider provider = new PKCS11Provider("/usr/lib/opensc-pkcs11.so.BAK");
    Security.addProvider(provider);

    System.out.println("loading truststore");
    KeyStore tks = KeyStore.getInstance(KeyStore.getDefaultType());
    tks.load(new FileInputStream("/home/dan/Dokumente/Zertifikate/store"), "xxx".toCharArray());                   // load truststore

    System.out.println("loading keystore");
    KeyStore iks = KeyStore.getInstance("PKCS11", provider);  //works fine. he asks for a right pin - cancels when pin is wrong
    iks.load(null, "zzz".toCharArray());                                                                                                         // load private keystore

    System.out.println("init truststore");
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());            // init truststore
    tmf.init(tks);

    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");  // here is the problem. It seems that the pin is ignored. and if i overgive the provider (like KeyStore.getInstance-Method)i get an NoSuchAlgorithmException (for stacktrace see below)
    kmf.init(null, "834950".toCharArray());  //The debugger shows in kmf.getKeyManagers()-Array no priv. Key or anything. It contains nothing but an empty hashmap (or something like this) with p12 it contains the priv. key and the certificate from the smart card

    System.out.println("setting sslcontext");
    SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
    SSLContext.setDefault(ctx);

    System.out.println("doing handshake");
    final SSLSocketFactory factory = ctx.getSocketFactory();
    final SSLSocket socket = (SSLSocket) factory.createSocket("download.uv.ruhr-uni-bochum.de", 443);
    socket.setUseClientMode(true);
    socket.startHandshake();   // here i try to do the handshake. it works with a p12-keystore... like ahead. with pkcs11 i get an SSLHandshakeException (Received fatal alert: handshake_failure)
    System.out.println("done");
}

NoSuchAlgorythmException:

Exception in thread "main" java.security.NoSuchAlgorithmException: no such algorithm: SunX509 for provider OpenSC-PKCS11
    at sun.security.jca.GetInstance.getService(GetInstance.java:100)
    at sun.security.jca.GetInstance.getInstance(GetInstance.java:218)
    at javax.net.ssl.KeyManagerFactory.getInstance(KeyManagerFactory.java:217)
    at clientauthtest.Main.installSSLContextPKCS11(Main.java:130)
    at clientauthtest.Main.main(Main.java:54)

希望你看到问题所在。 提前谢谢...丹尼尔

2 个答案:

答案 0 :(得分:1)

Builder builder = Builder.newInstance("PKCS11", provider, new KeyStore.CallbackHandlerProtection(/*PIN callback handler instance*/));
KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
kmf.init(new KeyStoreBuilderParameters(builder));

这应该可以正常工作。

答案 1 :(得分:0)

PHP 有一个 PKCS11 扩展,可用于对您的数据进行签名、验证、加密或解密。请参阅:https://github.com/gamringer/php-pkcs11

测试/文件夹中提供了一些示例。例如见:https://github.com/gamringer/php-pkcs11/blob/master/tests/0340-oasis_C_Encrypt.phpt

它对您的 jsp 没有帮助,但正如您所说,您也可以使用 php,您应该尝试一下。

相关问题