快捷搜索:  as  test  1111  test aNd 8=8  test++aNd+8=8  as++aNd+8=8  as aNd 8=8

手机BET365客户端_酒文化网进入



一、经由过程用户名和密码来进行认证的弊病

我们有一个网站,为了包管用户在线买卖营业传输数据的安然性,我们会启用一个HTTPS/SSL:

然则,对付一些网上银行或者是网购来说,黑客分外爱好进击这样的网站, 有一种进击伎俩叫MIMAT(中心者进击), 捏造SSL证书,让客户真个HTTP流,流到他那边去, 然后再进一步用暴力破解,来破解你HTTP传输时的密码。

一、改进的买卖营业流程

我们假设密码已经被MIM拿到了,拿到就拿到呗,大年夜家知道工商银行网上转贴划款时除了输入用户名和密码外,还会在点”下一步”时,跳出一个页面,让你插上你的U盾,然后再送一下买卖营业密码的历程吧?

这个便是”电子署名认证”

二、先往返首一下什么叫电子署名:

公钥加密,私钥解密

私钥署名,公钥认证

举例:

1.A用自己的私钥,对abcdefg进行sign,sign()函数返回一个byte[],这便是电子署名。

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.");

}else{

System.out.println("Signature did not match.");

}

}

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 -outclient.p12

1.大年夜家看到第4步中的那个key了吧,这个key便是客户真个私钥

大年夜家看到第4步中的那个crt文件了吧?那个文件里存着客户真个公钥(不是那个.key文件啊)

2.写一个servlet,客户端造访这个servlet时,该servlet自动从客户真个IE获取client.p12,然后把里面的公钥抽出来(因为是公钥,公开的,以是这个不存在安然不安然的身分)

3.办事器拿着该客户的私钥(此处我们先用这种措施来做),下面会讲更高档的U盾存客户端私钥的做法)

一、然后套用(用JAVA实现署名历程)中的算法,就可以实现应用证书来进行客户端和办事器的认证啦

必要办理的问题:

1.Servlet若何读客户真个认证

很多网上的同伙都说

“我用X509Certificate[]certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");

获得的证书是个null”

险些没有谜底,这边给出办理规划

a.客户端造访这个servlet,客户端和放这个servlet的j2eeapp必须实现“双向认证”

b.J2ee app端(假设我们这边用TOMCAT实现),在实现双向认证后,着实还不敷,必要加一个参数,很多人可能没留意到这个参数,下面给出规划:

truststoreType="JKS"

clientAuth="true"sslProtocol="TLS" />

看到上面那个标红的地方了吧?便是这个参数没加,是以很多人就算启用了双向认证,你的servlet在拿ie真个证书时照样会获得null值

2.好,现在客户真个公钥拿到了,怎么拿私钥?

前面说了,我们先做一个简单的,写逝世的,便是把客户真个私钥放在我们的网站的某个目录下,然后用法度榜样去读出来。

是以我们的历程如下:

a.客户端经由过程IE输入他的买卖营业密码

b.然后点“提交”按钮,POST到我们的这个servlet

c.Servlet先读放在网站某个目录下的该客户的私钥,loadPrivateKey后用私钥对客户提交的form里的密码进行署名。

d.Servlet得到客户端IE里的证书,把公钥拿出来,然后用公钥对签完名的byte[]进行verify, 获得true代表认签成功,false认签掉败,下面是我们的servlet

此处必要留意的是我们用openssl签出的private key是不能直接被java所造访的,由于它含用:

#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,这样就可以包管是这个客户本人在进行买卖营业了。

此处,必要办理的技巧问题有两此:

a.APPLET调用本地U盘

b.若何应用java script调用U盘

下面给出具体办理规划:

a.你买U盘时必然要记得它是支持JAVA调用的啊,一样平常U盘厂商会供给一个DLL,如:abc.dll,然后JAVA经由过程JNI调用这个dll,看到这边不要怕,厂商会供给完备的sample和api奉告你怎么调用该DLL的,照着SAMPLE写就行。

假如applet要调用客户真个u盘,该dll可以经由过程installshield等安装分发对象制作因素发包给客户自行安装。

在制作DLL安装分发包时,必然要把用于给javajni调用的dll经由过程安装对象自动copy到客户真个xp/windows的system32目录下,一样平常installshield或者是installanywhere等对象都带这个功能的。

这也是大年夜家在第一次用工行的U盾时,IE会提示要装一个什么控件,然后再要下载一个控件让你容许的事理,着实第一步便是把用来读U盾的dllcopy到你的系统的system32目录的一个历程,后一个历程便是让你容许下载applet/activex的历程。

然则,这边的问题是APPLET因为JAVA的沙箱机制,不能调用数据库,SOCKET及本地资本的,OK,不要担心。

我们不是已经有了CA和证书了吗?现在我们用我们的证书对这个APPLET签个名,它就能够调用本地的统统资本了。

我们现在用shnlap93.key,shnlap93.crt两个办事器端用的证书,我们有ca.crt,ca.key自署名root根证书,下面我们来造一个用于署名applet的jks文件吧。

对付applet署名必然要用JKS文件,为什么?

1)由于jks是含有私钥的

2)套用万能定律“私钥署名,公钥认证”

是以要用jks 文件

下面我们来天生这个jks吧:

keytool -genkey -alias shnlap93X509 -keyalg RSA -keysize 1024 -dname "CN=shnlap93.cts.com, OU=insurance, O=CTS, L=SH, S=SH, C=CN" -keypass aaaaaa -keystore shnlap93.jks -storepass aaaaaa

keytool -certreq -alias shnlap93X509 -sigalg "MD5withRSA" -file shnlap93.csr -keypass aaaaaa -keystore shnlap93.jks -storepass aaaaaa

openssl x509 -req -in shnlap93x509.csr -out shnlap93x509.pem -CA ca.crt -CAkey ca.key -CAserial ca-cert.srl -CAcreateserial -days 7200

keytool -import -alias rootca -trustcacerts -file ca.crt -keystore shnlap93.jks -storepass aaaaaa

keytool -import -aliasshnlap93X509trust -file shnlap93x509.pem -keystore shnlap93.jks -storepass aaaaaa

留意:

1)在提示要求输入CN值是(common name),这个值的IP必须和你的办事器(我们指TOMCAT)所在的IP或者是机械名(强烈建议大年夜家用机械名而不要用IP)必须一至的啊

现在我们有了这个JKS,这个JKS是我们在上面实现TOMCAT双向SSL认证时所必要用的JKS,也是我们署名时必要用的JKS

2)keytool -import -aliasshnlap93X509trust -file shnlap93x509.pem-keystore shnlap93.jks -storepass aaaaaa这一步中的alias中的又名的值绝对不能够和第一步:

keytool -genkey-alias shnlap93X509 -keyalg RSA -keysize 1024 -dname "CN=shnlap93.cts.com,OU=insurance, O=CTS, L=SH, S=SH, C=CN" -keypass aaaaaa -keystoreshnlap93.jks -storepass aaaaaa

中的值重名的啊。

3)这个jks天生完后应用:

Keytool –v –list –keystore shnlap93.jks后,你应该会看到“3”条entry,此中一条keyentry, 两条trustcert。

下面给出applet的署名历程:

jarsigner -verbose -verifyClientAuthenticationApplet.jar shnlap93X509(key entry的又名)

b.Javascript调用applet, 下面直接看我们的测试html页的源码吧:

上面这个object便是applet的写法,啰哩烦琐一堆器械,怎么写啊,很简单,大年夜家在制作这个html页时先用标准的applet标签写法

然后再去下一个HtmlConvert把这个html转一下就成了上面这一堆器械了,下载地址为:

http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-client-419417.html#7251-plugin-1.2-win-JPR

这个是SUN(不,现在是ORACLE-SUN)免费供给的applet转IE所认款式的语句的标准对象。

必然要转啊,不转的话下面javascript调用不认啊

转完后,要加一个ID:

id="authClient"classid="clsid:8AD9C8手机BET365客户端40-044E-11D1-B3E9-00805F499D93"

如上血色标粗的部分,不是classid啊,这个是htmlconvert自动给加的,必然要加这个id,不加这个id,javascript就不能经由过程documnt.authClient这样的形式调用applet了。

是以到这边大年夜家知道了吧,着实javascript调用applet便是把applet当一个html中的组件事调用的,只要这个applet有publich声明开首的措施,javascript就可以调用这种措施了,如:

vardcmsg=document.authClient.getSignature();

三、完备客户端买卖营业认证流程

1. 客户先安装U盘驱动(客户端运行vender做的dll安装至windows的system32目录的安装法度榜样)

2. 客户打开一个HTML(不用https造访,直接用http造访就行了)

3. 客户在网页的表单中提入用户名密码点提交

4. 此时弹出一个窗口,该窗口含有applet

5. 该弹出HTML窗口中的经署名的applet自动下载到客户端

6. Applet经由过程loadSystemLibrary(dll名)调用相关U盘驱动读出U盘内客户自己的私钥

7. Applet内部法度榜样用私钥对客户刚才输入的密码进行sign,把sign后的md5/sha(哈希值)还给表单,追跟着表单内客户输入的密码一路提交给我们的servlet

8. 我们的servlet从客户的IE导出客户安装的办事真个证书,从证书导出公钥

9. 用公钥对post过来的客户的sign的那个hash值进行verify()操作,返回是true,代表认证成功,然后接下拿拿客户输入的密码再颠末基于DB或者是LDAP的authentication,假如verify()是false直接经由过程servletresponse给客户一条差错代码,如:

请精确插入U盘(你就插吧, Come on BAYBAY!)。

下面给出完备的html,servlet, applet代码:

买卖营业密码(请查入U盾):

买卖营业密码:

SecurityReceiveServlet代码

public class SecurityReceive extends HttpServlet {

private static final long serialVersionUID = 1L;

/**

* @see HttpServlet#HttpServlet()

*/

public SecurityReceive() {

super();

// TODO Auto-generated constructor stub

}

/**

* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse

*response)

*/

private byte[] sign(String password) throws Exception {

try {

byte[] privKeyCode = SecurityHelper

.loadOpenSSLKey("d:/ca/pkcs8_der.key");

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

EncodedKeySpec privateKeySpec =

new PKCS8EncodedKeySpec(privKeyCode);

RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory

.generatePrivate(privateKeySpec);

Signature dsa = Signature.getInstance("MD5WithRSA");

dsa.initSign(privateKey);

dsa.update(password.getBytes());

byte[] sig = dsa.sign();

return sig;

} catch (Exception e) {

throw new Exception(e);

}

}

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[])手机BET365客户端 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);

}

}

private boolean verifySignature(byte[] dcByPriv, String password,

HttpServletRequest request, HttpServletResponse response)

throw手机BET365客户端s ServletException, IOException {

boolean verified = false;

try {

if (dcByPriv == null) {

return false;

}

byte[] data = password.getBytes("UTF8");

Signature sig = Signature.getInstance("MD5WithRSA");

sig.initVerify(getPubKeyFromIE(request, response));

sig.update(data);

try {

verified = sig.verify(dcByPriv);

} catch (SignatureException se) {

se.printStackTrace();

verified = false;

}

return verified;

} catch (Exception e) {

throw new ServletException(e);

}

}

protected void doGet(HttpServletRequest request,

HttpServletResponse response) throws ServletException, IOException {

boolean answer = false;

String password = "";

String dcByPrivBase64 = "";

byte[] dcByPriv = null;

password = (String) request.getParameter("inputPwd");

dcByPrivBase64 = (String) request.getParameter("dc_code");

try {

dcByPriv = Base64.decode(dcByPrivBase64.getBytes());

} catch (Exception e) {

e.printStackTrace();

dcByPriv = null;

}

answer = verifySignature(dcByPriv, password, request, response);

System.out.println("answer=====" + answer);

}

/**

* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse

*response)

*/

protected void doPost(HttpServletRequest request,

HttpServletResponse response) throws ServletException, IOException {

doGet(request, response);

}

}

我们的appletAuthClient的代码

/*

* To change this template, choose Tools | Templates

* and open the template in the editor.

*/

/*

* AuthClient.java

*

* Created on 2011-9-6, 13:08:02

*/

package alice.framework.applet;

import RY3jni.*;

import java.lang.*;

import java.security.KeyFactory;

import java.security.Signature;

import java.security.interfaces.RSAPrivateKey;

import java.security.spec.EncodedKeySpec;

import java.security.spec.PKCS8EncodedKeySpec;

import java.io.*;

import alice.util.Base64;

/**

*

*/

public class AuthClient extends javax.swing.JApplet {

/** Initializes the applet AuthClient */

@Override

public void init() {

/* Set the Nimbus look and feel */

// defaultstate="collapsed"

// desc=" Look and feel setting code (optional) ">

/*

* If Nimbus (introduced in Java SE 6) is not available, stay with the

* default look and feel. For details see

* http://download.oracle.com/javase

* /tutorial/uiswing/lookandfeel/plaf.html

*/

try {

for (javax.swing.UIManager.LookAndFeelInfo info :

javax.swing.UIManager

.getInstalledLookAndFeels()) {

if ("Nimbus".equals(info.getName())) {

javax.swing.UIManager.

setLookAndFeel(info.getClassName());

break;

}

}

} catch (ClassNotFoundException ex) {

java.util.logging.Logger.getLogger(AuthClient.class.getName()).log(

java.util.logging.Level.SEVERE, null, ex);

} catch (InstantiationException ex) {

java.util.logging.Logger.getLogger(AuthClient.class.getName()).log(

java.util.logging.Level.SEVERE, null, ex);

} catch (IllegalAccessException ex) {

java.util.logging.Logger.getLogger(AuthClient.class.getName()).log(

java.util.logging.Level.SEVERE, null, ex);

} catch (javax.swing.UnsupportedLookAndFeelException ex) {

java.util.logging.Logger.getLogger(AuthClient.class.getName()).log(

java.util.logging.Level.SEVERE, null, ex);

}

//

/* Create and display the applet */

try {

java.awt.EventQueue.invokeAndWait(new Runnable() {

public void run() {

initComponents();

}

});

} catch (Exception ex) {

ex.printStackTrace();

}

}

/**

* This method is called from within the init() method to initialize the

* form. WARNING: Do NOT modify this code. The content of this method is

* always regenerated by the Form Editor.

*/

@SuppressWarnings("unchecked")

// defaultstate="collapsed" desc="Generated Code">

private void initComponents() {

inputPassword = new javax.swing.JPasswordField();

getContentPane().setLayout(

new javax.swing.BoxLayout(getContentPane(),

javax.swing.BoxLayout.LINE_AXIS));

inputPassword.setText("jPasswordField1");

getContentPane().add(inputPassword);

}//

private IRY3 getROCK3Handler() throws Exception {

IRY3 ry = new CRY3();

RY3Def flag = new RY3Def();

//

String chPid = "";

String chPin = "";

String chSeed = "123456";

//

int[] Count = new int[4];

int[] RemainCount = new int[4];

int[] FreeSize = new int[1];

//

char[] charPid = new char[16]; // 8

char[]手机BET365客户端 charPin = new char[30]; // 24

char[] charSeed = new char[16]; // 6

char[] charHardID = new char[32]; // 16

//

byte[] randbuf = new byte[16];

byte[] tmpbuf = new byte[2048];

String voucher = "aaaaaa";

charPid = new char[] { 'F', 'E', 'C', '2', 'B', 'F', 'E', '1' };

//

chPin = "123456781234567812345678";

charPin = chPin.toCharArray();

try {

ry.RY3_Find(charPid, Count);

if (Count[0] != 0) {

ry.RY3_Open(1);

} else {

return null;

}

return ry;

} catch (Exception e) {

throw new Exception(e);

}

}

private RSAPrivateKey getPrivateKeyFromRC3() throws Exception {

IRY3 ry = null;

RSAPrivateKey privateKey = null;

byte[] privKeyCode = new byte[10手机BET365客户端24];

try {

ry = getROCK3Handler();

ry.RY3_Read(0, privKeyCode, 1024);

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privKeyCode);

privateKey = (RSAPrivateKey) keyFactory

.generatePrivate(privateKeySpec);

return privateKey;

} catch (Exception e) {

throw new Exception(e);

}

}

public String getUserInputPwd() {

return new String(this.inputPassword.getPassword());

}

public String getSignature() {

RSAPrivateKey privateKey = null;

try {

privateKey = getPrivateKeyFromRC3();

Signature dsa = Signature.getInstance("MD5WithRSA");

dsa.initSign(privateKey);

String pwd = new String(this.inputPassword.getPassword());

dsa.update(pwd.getBytes());

byte[] sig = dsa.sign();

System.out.println("success");

return new String(Base64.encode(sig));

} catch (Exception e) {

System.out.println("error: " + e);

e.printStackTrace();

return "-1";

}

}

// Variables declaration - do not modify

private javax.swing.JPasswordField inputPassword;

// End of variables declaration

}

转自:http://blog.csdn.net/lifetragedy/article/details/6764189

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

您可能还会对下面的文章感兴趣: