logo资料库

JAVA调用U盾 UKEY(网上交易安全认证).doc

第1页 / 共22页
第2页 / 共22页
第3页 / 共22页
第4页 / 共22页
第5页 / 共22页
第6页 / 共22页
第7页 / 共22页
第8页 / 共22页
资料共22页,剩余部分请下载后查看
网上交易-使用 JAVA 调用 U 盾进行客户认证的 total solution 一、通过用户名和密码来进行认证的弊病 我们有一个网站,为了保证用户在线交易传输数据的安全性,我们会启用一个 HTTPS/SSL: 但是,对于一些网上银行或者是网购来说,黑客特别喜欢攻击这样的网站, 有一种攻击手 法叫 MIMAT(中间者攻击), 伪造 SSL 证书,让客户端的 HTTP 流,流到他那边去, 然 后再进一步用暴力破解,来破解你 HTTP 传输时的密码。
一、改进的交易流程 我们假设密码已经被 MIM 拿到了,拿到就拿到呗,大家知道工商银行网上转贴划款时除了 输入用户名和密码外,还会在点”下一步”时,跳出一个页面,让你插上你的 U 盾,然后再送一下 交易密码的过程吧? 这个就是”电子签名认证” 二、先来回顾一下什么叫电子签名: 公钥加密,私钥解密 私钥签名,公钥认证 A 用自己的私钥,对 abcdefg 进行 sign,sign()函数返回一个 byte[],这就是电子签名。 举例: 1. 2. 把 A 的公钥和签名送到公行后台 3. 工行先看 A 的密码输的对不对,做一个数据库校验 工行用 A 的公钥对 A 的签名做 verify 运算,也得到一个 byte[] 4. 工行把工发过来的签名 byte[]和用 A 的公钥做 verify()后的 byte[], 两个 byte[]进行 booleanverified = sig.verify(dcByPriv); 5. 如果 verified 为 true,代表 A 一定是客户 A 本人且是工行的客户(当然,A 如果被人 杀了,并且 A 的私钥被杀他的人获得了这个不能算工行的责任) 三、用 JAVA 实现签名过程 于是, 根据上述过程先做一个 POC, 用 JAVA 来做电子签名认证,代码如下:
import java.security.*; public class SimpleSignature { private static void digitalSign(String text)throws Exception{ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(1024); KeyPair keyPair = kpg.generateKeyPair(); byte[] data = text.getBytes("UTF8"); Signature sig = Signature.getInstance("MD5WithRSA"); sig.initSign(keyPair.getPrivate()); sig.update(data); byte[] signatureBytes=sig.sign(); System.out.println("Signature:\n"+Base64.encode(signatureBytes)); sig.initVerify(keyPair.getPublic()); sig.update(data); boolean verified = false; try{ verified = sig.verify(signatureBytes); }catch(SignatureException se){ se.printStackTrace(); verified = false; } if(verified){ System.out.println("Signature verified."); System.out.println("Signature did not match."); }else{ } } public static void main(String[] args){ try{ String text="abc";
digitalSign(text); }catch(Exception e){ e.printStackTrace(); } } } 四、运用证书解决公钥,私钥传输的问题 1. 生成自签名 CA 根证书 openssl genrsa -des3 -out ca.key 1024 openssl rsa -in server.key -out ca.key openssl req -new -x509 -keyout ca.key -out ca.crt 2. 生成 Web 服务器证书 openssl genrsa -des3 -out shnlap93.key 1024 openssl rsa -in shnlap93.key -out shnlap93.key openssl req -new -key shnlap93.key -out shnlap93.csr openssl ca -in shnlap93.csr -out shnlap93.crt -cert ca.crt -keyfileca.key 3. 生成客户端证书 openssl genrsa -des3 -out client.key 1024 openssl rsa -in shnlap93.key -out client.key openssl req -new -key client.key -out client.csr openssl ca -in client.csr -out client.crt -cert ca.crt -keyfile ca.key 4. 把 shnlap93.crt 装在服务器上 客户端的 IE 导入 client.crt(此处必须把 crt 再转成 p12 格式)导入:
openssl pkcs12 -export -inkey client.key -in client.crt -out client.p12 1. 大家看到第 4 步中的那个 key 了吧,这个 key 就是客户端的私钥 大家看到第 4 步中的那个 crt 文件了吧?那个文件里存着客户端的公钥(不是那个.key 文件 啊) 2. 写一个 servlet,客户端访问这个 servlet 时,该 servlet 自动从客户端的 IE 获取 client.p12,然后把里面的公钥抽出来(由于是公钥,公开的,所以这个不存在安全不安全 的因素) 3. 服务器拿着该客户的私钥(此处我们先用这种方法来做),下面会讲更高级的 U 盾存 客户端私钥的做法) 一、然后套用(用 JAVA 实现签名过程)中的算法,就可以实现使用证书来进行客户端和服 务器的认证啦 需要解决的问题: Servlet 如何读客户端的认证 1. 很多网上的朋友都说 “我用 X509Certificate[]certs = (X509Certificate[]) request 09Certificate"); .getAttribute("javax.servlet.request.X5
得到的证书是个 null” 几乎没有答案,这边给出解决方案 a. 客户端访问这个 servlet,客户端和放这个 servlet 的 j2eeapp 必须实现“双向认证” b. J2ee app 端(假设我们这边用 TOMCAT 实现),在实现双向认证后,其实还不够, 需要加一个参数,很多人可能没注意到这个参数,下面给出方案: 看到上面那个标红的地方了吧?就是这个参数没加,因此很多人就算启用了双向认证,你的 servlet 在拿 ie 端的证书时还是会得到 null 值 2. 好,现在客户端的公钥拿到了,怎么拿私钥? 前面说了,我们先做一个简单的,写死的,就是把客户端的私钥放在我们的网站的某个目录 下,然后用程序去读出来。 Servlet 先读放在网站某个目录下的该客户的私钥,loadPrivateKey 后用私钥对客户提 因此我们的过程如下: a. 客户端通过 IE 输入他的交易密码 b. 然后点“提交”按钮,POST 到我们的这个 servlet c. 交的 form 里的密码进行签名。 d. verify, 得到 true 代表认签成功,false 认签失败,下面是我们的 servlet 此处需要注意的是我们用 openssl 签出的 private key 是不能直接被 java 所访问的,因为 它含用: Servlet 获得客户端 IE 里的证书,把公钥拿出来,然后用公钥对签完名的 byte[]进行 #begin certificate … #end certificate 这样的东西,而 JAVA 只认#begin…#end 当中的那块东西,怎么办: 使用下面这条使用把 openssl 签出的 key 转成我们 java 可以认的 rsa 的 KEY opensslpkcs8 -topk8 -inform PEM -outform DER -in shnlap93.key -out pkcs8_der.key –nocrypt
下面是我们的 servlet 的核心片段, 拿客户端 IE 的公钥,拿网站某个目录摆放的私钥,然 后调用标准的 JAVA 电子签名 private PublicKey getPubKeyFromIE(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("...security receive done..." + request.getScheme()); String issue, after, before, subject; String serialno, signalg; int version; String cipherSuite = ""; PublicKey pk = null; try { cipherSuite = (String) request .getAttribute("javax.servlet.request.cipher_suite"); System.out.println("cipherSuite=====" + cipherSuite); // response.setContentType("text/plain"); // FileInputStream fis = new FileInputStream("d://paramita.cer "); PrintWriter out = response.getWriter(); if (cipherSuite != null) { X509Certificate[] certs = (X509Certificate[]) request .getAttribute("javax.servlet.request.X509Certificate"); /* ibm http server us followings */ // X509Certificate[] certs = (X509Certificate[]) request // .getAttribute("javax.net.ssl.peer_certificates"); if (certs != null) { if (certs.length > 0) { X509Certificate t = certs[0]; pk = t.getPublicKey(); } } else { if ("https".equals(request.getScheme())) { out.println("This was an HTTPS request, " + "but no client certificate is available"); } else { out.println("This was not an HTTPS request, "
+ "so no client certificate is available"); } } } return pk; } catch (Exception e) { throw new ServletException(e); } } 二、私钥放在 U 内形成 U 盾 看到这边,大家已经蛋疼了吧? 要不要喝口水? 只有平时多蛋疼,真的碰到问题时才不会疼,这就叫“老乱”。 1. 去买个支持安装 RSA,加密,解密的证书的 U 盘吧,不贵,几十块钱,随盘一起赠送 一套软件,用这套软件把(pkcs8_der.key)经过 OPENSSL 转换过后的私钥 write 进去吧 (通过随盘自带的工具吧,这个不说了,因为每个人买的 U 盘所带的工具都不一样。 2. 写个 applet,这个 applet 就一个输入框,用于让客户输入密码使用 3. 然后使用 javascript 调用 applet,读客户本地的 U 盘,把私钥读出来,然后该 APPLET 用读出的私钥和客户输入的密码进行签名,把签完名后的 byte[]转成 base64,加上客户端 输入的密码一起 post 到我们刚才写的那个 servlet 中去。 4. 客户端安装由网站颁放的证书(P12 格式导入 IE 的“个人信任域中”) 5. 我们的那个 servlet 从客户端的 IE 得到证书,导出公钥,拿公钥+签名后的 byte[]再做 一个 verify(), true 代表认签,false 代表失败(不管失败原因),反正这个客户认签失败。 6. 以上这一步其实已经认证通过了,这时可以把客户输入的用户名和密码进行一次基于 数据库或者是 LDAP 的 authentication,这样就可以保证是这个客户本人在进行交易了。 此处,需要解决的技术问题有两此: APPLET 调用本地 U 盘 a. b. 如何使用 java script 调用 U 盘 下面给出详细解决方案: a. 你买 U 盘时一定要记得它是支持 JAVA 调用的啊,一般 U 盘厂商会提供一个 DLL,如: abc.dll,然后 JAVA 通过 JNI 调用这个 dll,看到这边不要怕,厂商会提供完整的 sample 和 api 告诉你怎么调用该 DLL 的,照着 SAMPLE 写就行。 如果 applet 要调用客户端的 u 盘,该 dll 可以通过 installshield 等安装分发工具制作成分发 包给客户自行安装。
分享到:
收藏