插入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的方法了嗎?