`
wangshiyang
  • 浏览: 71015 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

网上交易安全之九阳神功-使用JAVA调用U盾进行客户认证的total solution

 
阅读更多

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

我们有一个网站,为了保证用户在线交易传输数据的安全性,我们会启用一个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 -out client.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实现),在实现双向认证后,其实还不够,需要加一个参数,很多人可能没注意到这个参数,下面给出方案:

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"

enableLookups="false"disableUploadTimeout="true"

useURIValidationHack="false"

scheme="https"secure="true"

keystoreFile="D:/tomcat/conf/shnlap93.jks"keystorePass="xxxxxxx"

truststoreFile="D:/tomcat/conf/truststore.jks"truststorePass="aaaaaa"

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 -alias shnlap93X509trust -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 -alias shnlap93X509trust -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.jarshnlap93X509(key entry的别名)

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

<script language="javascript">

function getSignByPrivKey(){

var dcmsg=document.authClient.getSignature();

//alert(msg);

if(dcmsg!="-1")

{

document.digitalsig.dc_code.value=dcmsg;

document.digitalsig.submit();

}else{

alert("请插入正确的U盾");

}

}

</script>

<OBJECT id="authClient" classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"

WIDTH = 100 HEIGHT = 25 ALIGN = middle VSPACE = 0 HSPACE = 0 codebase="http://java.sun.com/products/plugin/1.2/jinstall-12-win32.cab#Version=1,2,0,0">

<PARAM NAME = CODE VALUE = "alice/framework/applet/AuthClient.class" >

<PARAM NAME = ARCHIVE VALUE = "ClientAuthenticationApplet.jar" >

<PARAM NAME="type" VALUE="application/x-java-applet;version=1.2">

</OBJECT>

上面这个object就是applet的写法,啰哩啰嗦一堆东西,怎么写啊,很简单,大家在制作这个html页时先用标准的applet标签写法

<APPLET CODE="test/AuthClient.class"

ARCHIVE="ClientAuthenticationApplet.jar" WIDTH=350 HEIGHT=200

HSPACE=0 VSPACE=0 ALIGN=middle> </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:

<OBJECT id="authClient"classid="clsid:8AD9C840-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代码:

<html>

<head>

<script language="javascript">

function getSignByPrivKey(){

var dcmsg=document.authClient.getSignature();

//alert(msg);

if(dcmsg!="-1")

{

document.digitalsig.dc_code.value=dcmsg;

document.digitalsig.submit();

}else{

alert("请插入正确的U盾");

}

}

</script>

</head>

<body>

<form name="digitalsig"

action="https://shnlap93.cts.com/alice/servlet/securityReceive"

method="post">

<input type="hidden" name="dc_code">

<table border="0" align="center">

<tr>

<td>

交易密码(请查入U盾):

</td>

<td align="left">

<OBJECT id="authClient" classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"

WIDTH = 100 HEIGHT = 25 ALIGN = middle VSPACE = 0 HSPACE = 0 codebase="http://java.sun.com/products/plugin/1.2/jinstall-12-win32.cab#Version=1,2,0,0">

<PARAM NAME = CODE VALUE = "alice/framework/applet/AuthClient.class" >

<PARAM NAME = ARCHIVE VALUE = "ClientAuthenticationApplet.jar" >

<PARAM NAME="type" VALUE="application/x-java-applet;version=1.2">

</OBJECT>

</td>

</tr>

<tr>

<td>交易密码:</td>

<td align="left"><input type="password" name="inputPwd"></td>

</tr>

<tr>

<td align="right" colspan="2">

<input type="button" name="submit_btn" value="submit" onclick="getSignByPrivKey();">

</td>

</tr>

</table>

</form>

</body>

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[]) 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)

throws 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 */

// <editor-fold 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);

}

// </editor-fold>

/* 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")

// <editor-fold 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);

}// </editor-fold>

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[] 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[1024];

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

}



分享到:
评论

相关推荐

    网上交易安全之九阳神功-使用JAVA调用U盾进行客户认证的total solution.doc

    本文档主要探讨了如何使用JAVA调用U盾进行客户认证,以增强网上交易的安全性,抵御中间人攻击(MIMAT)和其他网络威胁。 首先,传统的用户名和密码认证方式存在明显的安全隐患。当通信链路被中间人攻击者劫持,他们...

    智能车竞赛介绍(竞赛目标和赛程安排).zip

    全国大学生智能汽车竞赛自2006年起,由教育部高等教育司委托高等学校自动化类教学指导委员会举办,旨在加强学生实践、创新能力和培养团队精神的一项创意性科技竞赛。该竞赛至今已成功举办多届,吸引了众多高校学生的积极参与,此文件为智能车竞赛介绍

    集字卡v4.3.4微信公众号原版三种UI+关键字卡控制+支持强制关注.zip

    字卡v4.3.4 原版 三种UI+关键字卡控制+支持获取用户信息+支持强制关注 集卡模块从一开始的版本到助力版本再到现在的新规则版本。 集卡模块难度主要在于 如何控制各种不同的字卡组合 被粉丝集齐的数量。 如果不控制那么一定会出现超过数量的粉丝集到指定的字卡组合,造成奖品不够的混乱,如果大奖价值高的话,超过数量的粉丝集到大奖后,就造成商家的活动费用超支了。我们冥思苦想如何才能限制集到指定字卡组合的粉丝数,后我们想到了和支付宝一样的选一张关键字卡来进行规则设置的方式来进行限制,根据奖品所需的关键字卡数,设定规则就可以控制每种奖品所需字卡组合被粉丝集到的数量,规则可以在活动进行中根据需要进行修改,活动规则灵活度高。新版的集卡规则,在此次政府发布号的活动中经受了考验,集到指定字卡组合的粉丝没有超出规则限制。有了这个规则限制后,您无需盯着活动,建好活动后就无人值守让活动进行就行了,您只需要时不时来看下蹭蹭上涨的活动数据即可。 被封? 无需担心,模块内置有防封功能,支持隐藏主域名,显示炮灰域名,保护活动安全进行。 活动准备? 只需要您有一个认证服务号即可,支持订阅号借用认证服务号来做活动。如果您

    出口设备线体程序详解:PLC通讯下的V90控制与开源FB284工艺对象实战指南,出口设备线体程序详解:PLC通讯与V90控制集成,工艺对象与FB284协同工作,开源学习V90控制技能,出口设备1200

    出口设备线体程序详解:PLC通讯下的V90控制与开源FB284工艺对象实战指南,出口设备线体程序详解:PLC通讯与V90控制集成,工艺对象与FB284协同工作,开源学习V90控制技能,出口设备1200线体程序,多个plc走通讯,内部有多个v90,采用工艺对象与fb284 共同控制,功能快全部开源,能快速学会v90的控制 ,出口设备; 1200线体程序; PLC通讯; 多个V90; 工艺对象; FB284; 功能开源; V90控制。,V90工艺控制:开源功能快,快速掌握1200线体程序与PLC通讯

    基于Arduino与DAC8031的心电信号模拟器资料:心电信号与正弦波的双重输出应用方案,Arduino与DAC8031心电信号模拟器:生成心电信号与正弦波输出功能详解,基于arduino +DAC

    基于Arduino与DAC8031的心电信号模拟器资料:心电信号与正弦波的双重输出应用方案,Arduino与DAC8031心电信号模拟器:生成心电信号与正弦波输出功能详解,基于arduino +DAC8031的心电信号模拟器资料,可输出心电信号,和正弦波 ,基于Arduino;DAC8031;心电信号模拟器;输出心电信号;正弦波输出;模拟器资料,基于Arduino与DAC8031的心电信号模拟器:输出心电与正弦波

    (参考项目)MATLAB口罩识别检测.zip

    MATLAB口罩检测的基本流程 图像采集:通过摄像头或其他图像采集设备获取包含面部的图像。 图像预处理:对采集到的图像进行灰度化、去噪、直方图均衡化等预处理操作,以提高图像质量,便于后续的人脸检测和口罩检测。 人脸检测:利用Haar特征、LBP特征等经典方法或深度学习模型(如MTCNN、FaceBoxes等)在预处理后的图像中定位人脸区域。 口罩检测:在检测到的人脸区域内,进一步分析是否佩戴口罩。这可以通过检测口罩的边缘、纹理等特征,或使用已经训练好的口罩检测模型来实现。 结果输出:将检测结果以可视化方式展示,如在图像上标注人脸和口罩区域,或输出文字提示是否佩戴口罩。

    kernel-debug-devel-3.10.0-1160.119.1.el7.x64-86.rpm.tar.gz

    1、文件内容:kernel-debug-devel-3.10.0-1160.119.1.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/kernel-debug-devel-3.10.0-1160.119.1.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊

    day02供应链管理系统-补充.zip

    该文档提供了一个关于供应链管理系统开发的详细指南,重点介绍了项目安排、技术实现和框架搭建的相关内容。 文档分为以下几个关键部分: 项目安排:主要步骤包括搭建框架(1天),基础数据模块和权限管理(4天),以及应收应付和销售管理(5天)。 供应链概念:供应链系统的核心流程是通过采购商品放入仓库,并在销售时从仓库提取商品,涉及三个主要订单:采购订单、销售订单和调拨订单。 大数据的应用:介绍了数据挖掘、ETL(数据抽取)和BI(商业智能)在供应链管理中的应用。 技术实现:讲述了DAO(数据访问对象)的重用、服务层的重用、以及前端JS的继承机制、jQuery插件开发等技术细节。 系统框架搭建:包括Maven环境的配置、Web工程的创建、持久化类和映射文件的编写,以及Spring配置文件的实现。 DAO的需求和功能:供应链管理系统的各个模块都涉及分页查询、条件查询、删除、增加、修改操作等需求。 泛型的应用:通过示例说明了在Java语言中如何使用泛型来实现模块化和可扩展性。 文档非常技术导向,适合开发人员参考,用于构建供应链管理系统的架构和功能模块。

    基于四旋翼无人机的PD控制研究 附Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    C#与VB实现欧姆龙PLC的Fins TCP通信案例源码:调用动态链接库进行数据读写,定时器与计数器数据区的简洁读写操作示例,C#与VB实现欧姆龙PLC的Fins TCP通信案例源码:调用动态链接库进

    C#与VB实现欧姆龙PLC的Fins TCP通信案例源码:调用动态链接库进行数据读写,定时器与计数器数据区的简洁读写操作示例,C#与VB实现欧姆龙PLC的Fins TCP通信案例源码:调用动态链接库进行读写操作,涵盖定时器计数器数据区学习案例,C#欧姆龙plc Fins Tcp通信案例上位机源码,有c#和VB的Demo,c#上位机和欧姆龙plc通讯案例源码,调用动态链接库,可以实现上位机的数据连接,可以简单实现D区W区定时器计数器等数据区的读写,是一个非常好的学习案例 ,C#; 欧姆龙PLC; Fins Tcp通信; 上位机源码; 动态链接库; 数据连接; D区W区读写; 定时器计数器; 学习案例,C#实现欧姆龙PLC Fins Tcp通信上位机源码,读写数据区高效学习案例

    可调谐石墨烯超材料吸收体的FDTD仿真模拟研究报告:吸收光谱的化学势调节策略与仿真源文件解析,可调谐石墨烯超材料吸收体:化学势调节光谱的FDTD仿真模拟研究,可调谐石墨烯超材料吸收体FDTD仿真模拟

    可调谐石墨烯超材料吸收体的FDTD仿真模拟研究报告:吸收光谱的化学势调节策略与仿真源文件解析,可调谐石墨烯超材料吸收体:化学势调节光谱的FDTD仿真模拟研究,可调谐石墨烯超材料吸收体FDTD仿真模拟 【案例内容】该案例提供了一种可调谐石墨烯超材料吸收体,其吸收光谱可以通过改变施加于石墨烯的化学势来进行调节。 【案例文件】仿真源文件 ,可调谐石墨烯超材料吸收体; FDTD仿真模拟; 化学势调节; 仿真源文件,石墨烯超材料吸收体:FDTD仿真调节吸收光谱案例解析

    RBF神经网络控制仿真-第二版

    RBF神经网络控制仿真-第二版

    松下PLC与威纶通触摸屏转盘设备控制:FPWINPRO7与EBPRO智能编程与宏指令应用,松下PLC与威纶通触摸屏转盘设备控制解决方案:FPWINPRO7与EBPRO协同工作,实现多工位转盘加工与IE

    松下PLC与威纶通触摸屏转盘设备控制:FPWINPRO7与EBPRO智能编程与宏指令应用,松下PLC与威纶通触摸屏转盘设备控制解决方案:FPWINPRO7与EBPRO协同工作,实现多工位转盘加工与IEC编程模式控制,松下PLC+威纶通触摸屏的转盘设备 松下PLC工程使用程序版本为FPWINPRO7 7.6.0.0版本 威纶通HMI工程使用程序版本为EBPRO 6.07.02.410S 1.多工位转盘加工控制。 2.国际标准IEC编程模式。 3.触摸屏宏指令应用控制。 ,松下PLC; 威纶通触摸屏; 转盘设备控制; 多工位加工控制; IEC编程模式; 触摸屏宏指令应用,松下PLC与威纶通HMI联控的转盘设备控制程序解析

    基于循环神经网络(RNN)的多输入单输出预测模型(适用于时间序列预测与回归分析,需Matlab 2021及以上版本),基于循环神经网络(RNN)的多输入单输出预测模型(matlab版本2021+),真

    基于循环神经网络(RNN)的多输入单输出预测模型(适用于时间序列预测与回归分析,需Matlab 2021及以上版本),基于循环神经网络(RNN)的多输入单输出预测模型(matlab版本2021+),真实值与预测值对比,多种评价指标与线性拟合展示。,RNN预测模型做多输入单输出预测模型,直接替数据就可以用。 程序语言是matlab,需求最低版本为2021及以上。 程序可以出真实值和预测值对比图,线性拟合图,可打印多种评价指标。 PS:以下效果图为测试数据的效果图,主要目的是为了显示程序运行可以出的结果图,具体预测效果以个人的具体数据为准。 2.由于每个人的数据都是独一无二的,因此无法做到可以任何人的数据直接替就可以得到自己满意的效果。 这段程序主要是一个基于循环神经网络(RNN)的预测模型。它的应用领域可以是时间序列预测、回归分析等。下面我将对程序的运行过程进行详细解释和分析。 首先,程序开始时清空环境变量、关闭图窗、清空变量和命令行。然后,通过xlsread函数导入数据,其中'数据的输入'和'数据的输出'是两个Excel文件的文件名。 接下来,程序对数据进行归一化处理。首先使用ma

    【图像识别】手写文字识别研究 附Matlab代码+运行结果.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    旅游管理系统(基于springboot,mysql,java).zip

    旅游管理系统中的功能模块主要是实现管理员;首页、个人中心、用户管理、旅游方案管理、旅游购买管理、系统管理,用户;首页、个人中心、旅游方案管理、旅游购买管理、我的收藏管理。前台首页;首页、旅游方案、旅游资讯、个人中心、后台管理等功能。经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与旅游管理系统实现的实际需求相结合,讨论了Java开发旅游管理系统的使用。 从上面的描述中可以基本可以实现软件的功能: 1、开发实现旅游管理系统的整个系统程序;  2、管理员;首页、个人中心、用户管理、旅游方案管理、旅游购买管理、系统管理等。 3、用户:首页、个人中心、旅游方案管理、旅游购买管理、我的收藏管理。 4、前台首页:首页、旅游方案、旅游资讯、个人中心、后台管理等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流查看及回复相应操作。

    Boost二级升压光伏并网结构的Simulink建模与MPPT最大功率点追踪:基于功率反馈的扰动观察法调整电压方向研究,Boost二级升压光伏并网结构的Simulink建模与MPPT最大功率点追踪:基

    Boost二级升压光伏并网结构的Simulink建模与MPPT最大功率点追踪:基于功率反馈的扰动观察法调整电压方向研究,Boost二级升压光伏并网结构的Simulink建模与MPPT最大功率点追踪:基于功率反馈的扰动观察法调整电压方向研究,Boost二级升压光伏并网结构,Simulink建模,MPPT最大功率点追踪,扰动观察法采用功率反馈方式,若ΔP>0,说明电压调整的方向正确,可以继续按原方向进行“干扰”;若ΔP<0,说明电压调整的方向错误,需要对“干扰”的方向进行改变。 ,Boost升压;光伏并网结构;Simulink建模;MPPT最大功率点追踪;扰动观察法;功率反馈;电压调整方向。,光伏并网结构中Boost升压MPPT控制策略的Simulink建模与功率反馈扰动观察法

    基于matlab平台的图像去雾设计.zip

    运行GUI版本,可二开

    Deepseek相关参考资源文档

    Deepseek相关主题资源及行业影响

    WP Smush Pro3.16.12 一款专为 WordPress 网站设计的图像优化插件开心版.zip

    WP Smush Pro 是一款专为 WordPress 网站设计的图像优化插件。 一、主要作用 图像压缩 它能够在不影响图像质量的前提下,大幅度减小图像文件的大小。例如,对于一些高分辨率的产品图片或者风景照片,它可以通过先进的压缩算法,去除图像中多余的数据。通常 JPEG 格式的图像经过压缩后,文件大小可以减少 40% – 70% 左右。这对于网站性能优化非常关键,因为较小的图像文件可以加快网站的加载速度。 该插件支持多种图像格式的压缩,包括 JPEG、PNG 和 GIF。对于 PNG 图像,它可以在保留透明度等关键特性的同时,有效地减小文件尺寸。对于 GIF 图像,也能在一定程度上优化文件大小,减少动画 GIF 的加载时间。 懒加载 WP Smush Pro 实现了图像懒加载功能。懒加载是一种延迟加载图像的技术,当用户滚动页面到包含图像的位置时,图像才会加载。这样可以避免一次性加载大量图像,尤其是在页面内容较多且包含许多图像的情况下。例如,在一个新闻网站的长文章页面,带有大量配图,懒加载可以让用户在浏览文章开头部分时,不需要等待所有图片加载,从而提高页面的初始加载速度,同时也能

Global site tag (gtag.js) - Google Analytics