java pkcs#11讀取證書加解密(初學-分享)


插入USB-KEY, 想通過HttpClient來向服務器發送https請求。

 

一、httpClient只能夠支持java證書文件,他提供的例子如下

        DefaultHttpClient httpclient = new DefaultHttpClient();

        KeyStore trustStore  = KeyStore.getInstance(KeyStore.getDefaultType());        
        FileInputStream instream = new FileInputStream(new File("my.keystore")); 
        try {
            trustStore.load(instream, "nopassword".toCharArray());
        } finally {
            instream.close();
        }
        SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
        Scheme sch = new Scheme("https", socketFactory,443);
        httpclient.getConnectionManager().getSchemeRegistry().register(sch);

  如果USB-KEY的驅動程序支持PKCS#11接口,則OpenSSL通過engine可以比較方便地訪問USB-KEY。

 1     public static void main(String[] args) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException {
 2 //        程序並為將私鑰提取出來,只是調用了私鑰的接口
 3         String pkcs11config="name=PKCS11/n" +
 4                             "library=C://WINDOWS//system32//GP_IFD.dll"; 
 5         byte[] pkcs11configbytes=pkcs11config.getBytes();
 6         ByteArrayInputStream configStream = new ByteArrayInputStream(pkcs11configbytes);
 7         
 8         Provider p = new sun.security.pkcs11.SunPKCS11(configStream);
 9         Security.addProvider(p);
10         char[] pin = "password".toCharArray();
11         KeyStore ks = KeyStore.getInstance("PKCS11");
12         ks.load(null, pin);
13         System.out.println( ks );
14         
15         KeyStore keyStore  = KeyStore.getInstance(KeyStore.getDefaultType());
16         
17         Enumeration enumeration = keyStore.aliases();
18         while (enumeration.hasMoreElements()) {
19             String alias = (String) enumeration.nextElement();
20             System.out.println("----alias---:"+alias);
21             X509Certificate certificate = (X509Certificate)keyStore.getCertificate(alias);
22             System.out.println("----certificate---:"+certificate);
23             PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, null);
24             System.out.println("----privateKey---:"+privateKey);
25         }
26 
27     }

不曉得哪些廠商實現了這個接口,既然涉及到安全大家都沒有那么友好了。我用下面這段代碼來訪問農行的KEY寶(廠商是華大),報錯:

Exception in thread "main" java.security.ProviderException: Initialization failed at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:186) at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:80) at cn.com.hd.test.pkcs11.main(pkcs11.java:65) Caused by: java.io.IOException: ???????¨????ò??

at sun.security.pkcs11.wrapper.PKCS11.connect(Native Method) at sun.security.pkcs11.wrapper.PKCS11.<init>(PKCS11.java:125) at sun.security.pkcs11.wrapper.PKCS11.getInstance(PKCS11.java:138) at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:128) ... 2 more

 

應該根本就不支持這個接口吧

 

二、聽說最新版本的OpenSSL 0.9.8i版本已經增WINDOWS CAPI的支持。有人進行測試:

進行對USB-KEY的試驗(特別說明,試驗用的USB-KEY是公安專用,所以第一次訪問USB-KEY時會要求輸入KEY的密碼,並在公安內網中進行試驗。)

1、用新編譯的軟件發起HTTPS頁面請求,軟件彈出公安KEY的密碼輸入窗口。(可以證明去訪問了CAPI,並成功訪問到該USB)。

2、輸入密碼后,返回的頁面中帶有USB-KEY主人的信息。(被證明USB-KEY支持成功)

3、撥出USB-KEY,再次請求該頁面。返回的頁面中不帶任何人員信息,直接跳轉到登錄窗口。

4、再次插入(測試軟件不重啟),再次請求HTTPS,又出現密碼輸入窗口,輸入密碼后,成功訪問頁面,頁面中並帶有USB-KEY主人的信息。

5、再次請求該頁面,沒有出現密碼輸入窗口,頁面返回正常,即同樣帶有USB-KEY主人的信息。

通過以上五步測試,證明新編譯的OPENSSL0.9.8i版本可以自動的向CAPI進行調用。這給需要在OPENSSL中支持CAPI接口的開發者來說是一種福音,至少對我來說是,不用自己寫代碼,還要測試等等,呵呵。

這個版本好像只支持WINDOWS下的CAPI接口,LINUX下的不清楚了。就說到這里,本着OPENSSL開源的原則,我把我的測試經過供大家參考。以后如果有類似需求的朋友可以嘗試一下。

 

通過調用OpenSSL 的BIO 庫來建立安全連接和非安全連接具體方式可以參考:

http://www.ibm.com/developerworks/cn/linux/l-openssl.html

 

不過這些都是C的方式,本來想用httpClient提交請求的,難道就沒有好java的方法了嗎?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM