一、通过用户名和密码来进行认证的弊病
我们有一个网站,为了保证用户在线交易传输数据的安全性,我们会启用一个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转一下就成了上面这一堆东西了,下载地址为:
这个是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 }
|
相关推荐
4. **API接口**:为了能够调用u盾进行加解密操作,开发者需要使用银行提供的API接口。这些接口允许程序与u盾硬件进行通信,执行读写操作。 5. **文件操作**:在实际应用中,需要将文件读入内存,使用u盾进行加密,...
【工行捷德U盾 Win7 32/64位 官方驱动】是一款专为工商银行用户设计的安全认证工具,适用于Windows操作系统,包括32位和64位版本。这款驱动程序的主要功能是确保用户的捷德U盾在Win7系统上能够正常工作,提供安全的...
通过以上知识点的学习和实践,你可以掌握如何使用Java调用SOAP接口,以及如何根据具体需求进行定制。在处理天气信息这样的案例中,理解SOAP协议和相关API的使用,将使你能够轻松地与各种Web服务进行交互。
Java调用Qt DLL是一个跨平台的技术实践,涉及到Java与C++之间的互操作性,其中Qt是一个流行的C++库,主要用于图形用户界面开发。这个主题主要包含以下几个知识点: 1. **JNI(Java Native Interface)**:JNI是Java...
易语言JAVA调用是将Java代码与易语言程序进行交互的一种技术,这使得开发者能够利用易语言编写主程序,同时利用Java的丰富库资源。在本例子中,我们看到几个关键文件,它们分别是: 1. **Test.class**:这是一个...
java调用Gmssl中国密接口进行对称与非对称加解密等运算,动态so库进行接口jni方式调用,采取接口形式对外暴露,方便对接系统调用相关java接口进行相关运算操作。
**标题解析:** "java调用snmp协议" 指的是使用Java编程语言来实现对SNMP(简单网络管理协议)的调用。SNMP主要用于监控和管理网络设备,如路由器、交换机等,而Java作为一种跨平台的编程语言,能够方便地实现这种...
本文将详细介绍如何使用Java调用SAP ODATA服务,并针对描述中的几个关键问题进行深入探讨。 #### 1. 未经授权 (401) 在调用SAP ODATA服务时,如果出现“401 Unauthorized”错误,通常是因为服务器拒绝了请求,因为...
使用Java API,我们可以将XML中的语法解析并执行,然后获取分析结果。 总的来说,Java调用SPSS是一项实用的技术,它允许开发者利用Java的强大功能和SPSS的统计分析能力,实现数据处理和分析的自动化。不过,由于...
在Java代码中,通过`Subject`对象和`LoginContext`来调用KerberosLoginModule进行登录操作。登录成功后,可以从`Subject`中获取到验证过的凭据,用于后续的授权和服务请求。 3. **示例代码** ```java import ...
当我们需要在Java应用中实现与硬件设备交互的功能,如调用扫描仪进行文档扫描,就需要借助特定的库和接口。本篇文章将深入探讨如何在Java环境中调用扫描仪,并提供相关实践示例。 首先,理解Java与硬件设备交互的...
java调用comfyui接口,通过api json调用,同时可以通过参数替换 api的json中的参数,返回数据包含 :url 、path、base64方式
Java调用COM+组件是一种常见的跨语言交互技术,它允许Java应用程序利用已有的COM(Component Object Model)或COM+组件,这些组件通常是用其他语言如C++或Visual Basic编写的。这种技术对于整合遗留系统或者利用...
使用JNI,Java程序可以调用GMSSL库进行SM3哈希计算,适用于数据完整性校验和数字签名的摘要生成。 3. **SM4算法**:SM4是一种对称分组密码算法,用于块加密。它具有128位的密钥和块大小,与AES相似。通过JNI,我们...
Java调用USB并口打印机是一项技术任务,涉及到Java编程、硬件接口通信以及打印技术。在本文中,我们将深入探讨如何通过Java实现这一功能,以及相关的技术细节。 首先,理解“并口”(LPT)是一种古老的接口,常用于...
- 安全考量:避免命令注入,可能使用Java内置库或第三方库进行证书管理。 - 数字证书和SSL/TLS协议的基础知识。 - Java与外部工具交互的最佳实践。 在实际开发中,确保正确、安全地处理证书和密钥是至关重要的,...
在IT行业中,尤其是在开发零售或餐饮系统的背景下,Java调用小票打印机打印购物清单是一项常见的任务。这个过程涉及到几个关键的技术点,包括打印机驱动的处理、串口通信、文本格式化以及与硬件设备的交互。以下是对...
为了使程序更具通用性,你可能需要读取来自文件的ZPL指令,这可以使用Java的`FileReader`和`BufferedReader`类实现。假设你有一个名为`Print.zpl`的文件,包含预定义的ZPL指令,可以这样读取并发送: ```java try ...
java调用phantomJs进行网页截图源码,有需要的朋友自行下载