本文转自:http://www.fengfly.com/plus/view-210090-1.html
一、通过用户名和密码来进行认证的弊病
我们有一个网站,为了保证用户在线交易传输数据的安全性,我们会启用一个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.jar shnlap93X509(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转一下就成了上面这一堆东西了,下载地址为:
这个是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、C++、PB、VB、DELPHI)的加密狗和U盾身份验证的实例程序,帮助开发者理解和实现这一过程。 1. **JAVA**:Java作为跨平台的编程语言,提供了丰富的安全库和API,如Java ...
这份手册可能指导如何使用U盾来安全地进行移动云MAS的API调用和操作。 5. **HTTP(1).docx**: 这份文档详细阐述了如何通过HTTP协议与移动云MAS的服务器进行通信,包括请求格式、请求头、请求体以及响应格式等关键...
稳压罐sw16_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip
内容概要:本文详细介绍了利用递推最小二乘法(RLS)进行永磁同步电机参数辨识的方法及其MATLAB仿真过程。首先解释了RLS算法的优势,如不需要概率模型、计算量适中以及适用于嵌入式系统的实时参数更新。接着展示了将电机电压方程转换为标准形式Y=φθ的具体步骤,并提供了核心的RLS迭代代码。文中还讨论了仿真过程中的一些关键技术细节,如遗忘因子的选择、协方差矩阵的初始化和更新方式、电流信号的处理方法等。最终给出了仿真结果,显示电阻和电感的辨识误差分别达到了0.08%和0.12%,并指出了实际应用中需要注意的数据同步和数值稳定性问题。 适合人群:从事电机控制研究的技术人员、研究生及以上学历的学生。 使用场景及目标:①帮助研究人员理解和掌握RLS算法在电机参数辨识中的应用;②提供详细的仿真代码和配置建议,便于快速搭建实验环境;③指导如何优化算法性能,提高参数辨识精度。 其他说明:本文不仅涵盖了理论推导,还包括了大量的实践经验分享和技术细节探讨,有助于读者全面理解RLS算法的实际应用。同时,文中提到的仿真方案可以方便地移植到DSP平台,进一步扩展了其实用价值。
零起点Python大数据与量化交易
管道清污机器人sw16可编辑_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip
电子仿真教程,从基础到精通,每个压缩包15篇教程,每篇教程5000字以上。
电子仿真教程,从基础到精通,每个压缩包15篇教程,每篇教程5000字以上。
1、文件说明: Centos8操作系统thai-scalable-garuda-fonts-0.6.5-1.el8.rpm以及相关依赖,全打包为一个tar.gz压缩包 2、安装指令: #Step1、解压 tar -zxvf thai-scalable-garuda-fonts-0.6.5-1.el8.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm
内容概要:本文详细介绍了利用ABAQUS进行滑坡和沉降对埋地管道影响的有限元分析方法。主要内容涵盖了几何建模、材料属性定义、接触设置、边界条件与加载等方面的技术细节。通过具体的Python脚本示例展示了如何构建模型,并深入探讨了滑坡和沉降条件下管道的应力、应变分布及其潜在破坏机制。此外,还分享了一些实战经验和优化技巧,如材料模型选择、接触条件设置、边界条件处理等,强调了这些因素对结果准确性的重要影响。 适合人群:从事地下管道工程设计、施工及维护的专业技术人员,尤其是那些希望深入了解滑坡和沉降对管道影响的研究人员和技术专家。 使用场景及目标:适用于评估和预测滑坡和沉降对埋地管道造成的力学响应,帮助工程师们更好地理解和应对复杂的地质灾害环境,从而提高管道系统的安全性与稳定性。 其他说明:文中提供的Python代码片段仅为示意,具体实施时需结合ABAQUS的实际接口和项目需求进行适当调整。同时,对于大规模模型的计算,建议使用高性能计算资源以确保效率和精度。
Java一天面试突击,迅速掌握Java常见面试题
莲子去壳机设计模型SW10_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip
MFRC-522+RC522+RFID射频+IC卡感应模块
内容概要:《学术研究提示设计 50 招》是一份详尽的指南,旨在帮助研究人员提高学术写作和研究效率。该文档涵盖了从论文撰写、润色、翻译、查重降重、参考文献管理、投稿审稿到文献阅读等多个方面的具体操作指令。每一章节均针对特定任务提供了详细的步骤和注意事项,例如如何撰写标题、摘要、致谢,如何进行英文润色、中英翻译,以及如何优化逻辑结构等。文档还介绍了如何利用AI工具进行文献分析、术语表提取和研究方向探索等内容,为研究者提供了全面的支持。 适合人群:适用于学术研究人员,特别是那些需要撰写、润色和提交学术论文的研究者,包括研究生、博士生及高校教师等。 使用场景及目标:① 提供一系列具体的指令,帮助研究者高效完成论文的各个部分,如撰写标题、摘要、致谢等;② 提供润色和翻译的详细指导,确保论文语言的准确性和专业性;③ 提供查重降重的方法,确保论文的原创性;④ 提供参考文献管理和投稿审稿的指导,帮助研究者顺利发表论文;⑤ 利用AI工具进行文献分析、术语表提取和研究方向探索,提高研究效率。 阅读建议:此资源不仅提供了具体的指令和方法,更重要的是引导研究者如何思考和解决问题。因此,在学习过程中,不仅要关注具体的步骤,还要理解背后的原理和逻辑,结合实际案例进行实践和反思。
项目optionc-20250409
2023年c语言程序设计基本概念考点归纳.doc
电子仿真教程,从基础到精通,每个压缩包15篇教程,每篇教程5000字以上。
内容概要:本文详细介绍了使用Matlab进行模拟和数字滤波器设计的方法,涵盖了巴特沃斯、切比雪夫等多种经典滤波器类型。首先讲解了模拟滤波器的设计,如巴特沃斯滤波器的通带平坦性和切比雪夫滤波器的通带波纹特性,并提供了具体的代码示例。接着讨论了数字滤波器的设计,包括IIR滤波器的递归特性和FIR滤波器的线性相位特性,同样附有详细的代码实现。文中还特别强调了不同类型滤波器之间的转换方法以及设计过程中常见的注意事项,如频率归一化、阶数选择等。最后推荐了一些实用的Matlab工具,如fvtool和FDATool,帮助用户更直观地理解和调试滤波器设计。 适合人群:具有一定信号处理基础和技术背景的研究人员、工程师及学生。 使用场景及目标:适用于需要进行滤波器设计的实际工程应用,如通信系统、音频处理等领域。目标是让读者掌握滤波器设计的基本原理和具体实现方法,能够独立完成滤波器的设计和调试。 其他说明:文章不仅提供了理论知识,还通过大量实例代码帮助读者更好地理解和应用所学内容。建议读者在实践中多尝试不同的参数配置,以加深对滤波器特性的理解。
饲料干燥装置sw16_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip
内容概要:本文详细介绍了独立分量分析(ICA)在MATLAB环境下的应用,特别是在土木工程、航空航天和机械领域的振动信号处理方面。文章通过具体实例展示了如何利用ICA将复杂的混合信号分解为独立分量,从而帮助识别结构损伤、故障特征等问题。文中提供了详细的MATLAB代码示例,涵盖数据预处理、核心算法实现以及结果可视化的全过程。此外,还讨论了ICA的应用限制及其与其他信号处理方法的结合使用。 适合人群:从事土木工程、航空航天、机械等领域研究和技术工作的工程师及研究人员,尤其是那些需要处理复杂振动信号的人群。 使用场景及目标:① 土木工程中用于结构健康监测,如桥梁、建筑物的振动数据分析;② 航空航天领域用于飞行器复合载荷分离;③ 机械设备故障诊断,如齿轮箱、轴承等部件的故障特征提取。通过ICA能够有效地从多源混合信号中分离出有用的独立分量,辅助决策。 其他说明:ICA并非适用于所有情况,在某些特定条件下可能会失效,因此需要结合实际情况灵活运用。对于初学者来说,可以从简单的仿真数据入手,逐步过渡到真实的工程项目中。