Java中RSA非对称密钥加解密使用示例
上一篇 / 下一篇 2012-09-10 09:20:32 / 个人分类:Java
一、简介:51Testing软件测试网FL0o~V5yY
'L N3] C m F2t3b q0 RSA加密算法是最常用的非对称加密算法,CFCA在证书服务中离不了它。 RSA是第一个比较完善的公开密钥算法,它既能用于加密,也能用于数字签名。这个算法经受住了多年深入的密码分析,虽然密码分析者既不能证明也不能否定 RSA的安全性,但这恰恰说明该算法有一定的可信性,目前它已经成为最流行的公开密钥算法。
#`Ye&A#\t%\h!F051Testing软件测试网&CX8C x#iL!K;r{二、RSA的公钥、私钥的组成,以及加密、解密的公式可见于下表
*e(t.s8R_!V0Z"yR6M6l:R k0 三、使用方式:51Testing软件测试网6I{r|!K+zn&Rp/P8f
51Testing软件测试网Gz'e(Q4bn① 假设A、B机器进行通信,已A机器为主;
f Em%B]|Z051Testing软件测试网,Q$WD.^U^"^|② A首先需要用自己的私钥为发送请求数据签名,并将公钥一同发送给B;
$m2`b;T:cT\|0Ie3Fu/qA [ { [3an0 ③ B收到数据后,需要用A发送的公钥进行验证,已确保收到的数据是未经篡改的;
'U GMQ9cX8nn0SIE { @\"ZgDS0 ④ B验签通过后,处理逻辑,并把处理结果返回,返回数据需要用A发送的公钥进行加密(公钥加密后,只能用配对的私钥解密);51Testing软件测试网e.n3_jrC J
51Testing软件测试网mQ8_a3K'y(}(g0X⑤ A收到B返回的数据,使用私钥解密,至此,一次数据交互完成。
B[C.HQ0C$yf"F*J"z ZA[0 四、代码示例:51Testing软件测试网$]8[%Ove2}FR"Q
r"k(G#QLuh&w{0 1、第一步获取私钥,为签名做准备。51Testing软件测试网nAx;nR
/**51Testing软件测试网]!Xjj&Bh * 读取私钥 返回PrivateKey51Testing软件测试网3Qb4Vc-NAI * @param path 包含私钥的证书路径 w-pz,^ T,C"|*|v0 * @param password 私钥证书密码51Testing软件测试网+N W&f+M'qD4^9s * @return 返回私钥PrivateKey &vi8_J@H+xG0 * @throws KeyStoreException {+f&lc^;v"OBtN&FFG0 * @throws NoSuchAlgorithmException xn e0s#{#Y0 * @throws CertificateException51Testing软件测试网c:luz.JP"r * @throws IOException cORs+b0 * @throws UnrecoverableKeyException51Testing软件测试网7G~#l M*B#w2d4P */ E%e vL^\{-E$K0 private static PrivateKey getPrivateKey(String path,String password)51Testing软件测试网*znA-``a+W H-m5@| throws KeyStoreException, NoSuchAlgorithmException, CertificateException, ~#S#p%?}rT*bhn0 IOException, UnrecoverableKeyException { E0wa e y3{9~'|v0 KeyStore ks = KeyStore.getInstance("PKCS12"); 3R9?+h Cf ?D0 FileInputStream fis = new FileInputStream(path);51Testing软件测试网;pvm1F1g5p char[] nPassword = null;51Testing软件测试网4L)A)WVZ9d2v7r if ((password == null) || password.trim().equals("")) { Z7PA7^!?HI}0 nPassword = null;51Testing软件测试网C*W3h#]O ehuG } else { PlYs!Lz8c8Bm0 nPassword = password.toCharArray(); '_O4t~2z0 } 0z#mFc9[s&eI[-gc0 ks.load(fis, nPassword);51Testing软件测试网A)kNw9V+DA i"c ~ fis.close();51Testing软件测试网ga'?;O}1[~QlY Enumeration<String> en = ks.aliases();51Testing软件测试网h` X$U^d] String keyAlias = null; 6K,J#QD6k%B1k"_0 if (en.hasMoreElements()) {51Testing软件测试网 Q&K~*R-L!Yz2J.d6W keyAlias = (String) en.nextElement();51Testing软件测试网+P)]#x0C$MyXR }51Testing软件测试网k YdT`.Od"Ha 51Testing软件测试网"N9|-Dq/nM v8aY'L&g return (PrivateKey) ks.getKey(keyAlias, nPassword); ^/g4Hm?3o0 } |
2、签名示例:通过第一步得到的私钥,进行签名操作,具体请看以下代码:
|.T|*_T4^)\5xQ0/**yC3Z`)I,F)OK0 * 私钥签名: 签名方法如下:BASE64(RSA(MD5(src),privatekey)),其中src为需要签名的字符串,51Testing软件测试网/\I:[ D2d3N
privatekey是商户的CFCA证书私钥。51Testing软件测试网Q^iyT
* @param plainText 待签名字符串
,fLAd$T3t-Qa*d0 * @param path 签名私钥路径
uAK0m5gk0 * @param password 签名私钥密码
`krc^,q#?LV0 * @return 返回签名后的字符串51Testing软件测试网 Bl0b0s_ J
* @throws Exception51Testing软件测试网4Qb:[g"W~Tq
*/51Testing软件测试网1NXKNk AP6r
public static String sign(String plainText,String path,String password)51Testing软件测试网'?hz$YL
throws Exception {
X;FRzh i.E-m0 /*51Testing软件测试网.N!j$r~Im(s
* MD5加密
K:E \7R^o*z(U0 */
#npE m$f0 MessageDigest md5 = MessageDigest.getInstance("MD5");51Testing软件测试网n7e-dc Z\#~\W
md5.update(plainText.getBytes("utf-8"));51Testing软件测试网0wUB xztq
byte[] digestBytes = md5.digest();
#`Hh"L!T2SzR9]0 /*
rrtJ*Y/s`A B/e0 * 用私钥进行签名 RSA
s hR'[j{j#p0 * Cipher负责完成加密或解密工作,基于RSA51Testing软件测试网-A$H*Zo3G*z%y/Y
*/
(X5X:i fXadl%S-h0 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
eL/b6Wj4X7Y4L0 //ENCRYPT_MODE表示为加密模式51Testing软件测试网G7G:r4xn(BO9U
cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey(path, password));
"UnO7c k0uY d6MI0 //加密
y|3xnEU"r0 byte[] rsaBytes = cipher.doFinal(digestBytes);51Testing软件测试网9h'RelIQ?;i5K1V
//Base64编码
R e_sbDN0 return Base64.byteArrayToBase64(rsaBytes);51Testing软件测试网.eLOO$V
3、B收到数据后,需要使用A提供的公钥信息进行验签,此处使用公钥的N、E进行验签51Testing软件测试网2mU#Pm_@P
首先通过公钥N、E得到公钥PublicKey,如下:
"[2wa z?og"X051Testing软件测试网 Zr4W8bcUu.l7nLI:i-I/I t%T0/**51Testing软件测试网^0k)c |;O%d * 根据公钥n、e生成公钥51Testing软件测试网%]H9d.JN * @param modulus 公钥n串51Testing软件测试网#]4GM*tf6e * @param publicExponent 公钥e串51Testing软件测试网)f*`GdU * @return 返回公钥PublicKey51Testing软件测试网"C,w i R-g v$y * @throws Exception51Testing软件测试网Ddlp3~\y/wv */51Testing软件测试网|nw\u.S%MxL:\!Z public static PublicKey getPublickKey(String modulus, String publicExponent)51Testing软件测试网"jSdg4R_3~bE} throws Exception { c3p_-j v2~| \0 KeySpec publicKeySpec = new RSAPublicKeySpec( 1B0I*T~a:IW8@;e!F$`r0 new BigInteger(modulus, 16), new BigInteger(publicExponent, 16)); 8qWrp[$?l0 KeyFactory factory = KeyFactory.getInstance("RSA");51Testing软件测试网"nE$l4m-Qz/t PublicKey publicKey = factory.generatePublic(publicKeySpec); yE)Y ],b#rX0 return publicKey;51Testing软件测试网'?,v+\pi3@hxg } |
得到公钥PublicKey后,再去验证签名,代码如下:51Testing软件测试网r[Z-T%O}^7Vw(yo
l.G GUOpxY0
}j i+_+{ k0/** DE"@v-R J6FK+x0 * 用公钥证书进行验签51Testing软件测试网%C*dv n Gt * @param message 签名之前的原文51Testing软件测试网8q^1i P@-QN(x'S,B-I * @param cipherText 签名51Testing软件测试网T-Lr/U+aA?D * @param pubKeyn 公钥n串51Testing软件测试网]3s(H5r%W0k1KO#l * @param pubKeye 公钥e串 e%jIW;ciLu0 * @return boolean 验签成功为true,失败为false %sz~myY0 * @throws Exception @ j@?? r0 */51Testing软件测试网6ay tcX R+E4Jxp#R4_ public static boolean verify(String message, String cipherText,String pubKeyn,51Testing软件测试网&Z+z/MDQd o:{}mt String pubKeye) throws Exception {51Testing软件测试网S&JN^|5f Cipher c4 = Cipher.getInstance("RSA/ECB/PKCS1Padding");51Testing软件测试网A(\+RU0wL9~{dZ // 根据密钥,对Cipher对象进行初始化,DECRYPT_MODE表示解密模式 ueZ6`{5GC0 c4.init(Cipher.DECRYPT_MODE, getPublickKey(pubKeyn,pubKeye));51Testing软件测试网\:j0LF~5ZQ:p'JQ c // 解密51Testing软件测试网qz"?,i9["H(hqm byte[] desDecTextBytes = c4.doFinal(Base64.base64ToByteArray(cipherText));51Testing软件测试网+ZU2}:nA#V,S // 得到前置对原文进行的MD551Testing软件测试网-fx#U*RJS_:V String md5Digest1 = Base64.byteArrayToBase64(desDecTextBytes);51Testing软件测试网Pa)\ ag_!D MessageDigest md5 = MessageDigest.getInstance("MD5");51Testing软件测试网w5LpT|MfQ md5.update(message.getBytes("utf-8")); 5C2sZFU7c ]RY0 byte[] digestBytes = md5.digest();51Testing软件测试网mKfRF#} // 得到商户对原文进行的MD551Testing软件测试网o1lnra:d.H String md5Digest2 = Base64.byteArrayToBase64(digestBytes);51Testing软件测试网0n |$D/q}Iq2e&\ // 验证签名51Testing软件测试网Sh?Fp if (md5Digest1.equals(md5Digest2)) { h.C/Y{y0 return true;51Testing软件测试网p8iB4ftg0M*gnu[ W } else {51Testing软件测试网7@7B+w,^8cWn7|:e return false; /bW { Y }}H Kz0 }51Testing软件测试网y6W;I z1X } |
至此,签名验签已经完毕51Testing软件测试网/FS;O-| v+n
51Testing软件测试网7S^R)[RC1gur(e(|4、提供一个从.cer文件读取公钥的方法:
9gn`PQ7mXd0D F`wRWa0
+ZS%hv7q'Au0l\!Y0/**w w Ty%e K(i0 * 读取公钥cer51Testing软件测试网#zG1_Z-r+F
* @param path .cer文件的路径 如:c:/abc.cer
iPw~.v-u `-w0 * @return base64后的公钥串
;P E)|G:s M)qI3I0 * @throws IOException
Yv:q8G`r%O0 * @throws CertificateException
6Y7ha5F:@z}W0 */
$}-Oi%W-O q0 public static String getPublicKey(String path) throws IOException,51Testing软件测试网z&d"f,N'n)z
CertificateException{51Testing软件测试网2D j%L X+X _
InputStream inStream = new FileInputStream(path);51Testing软件测试网'tj"qIv!`V"CD!v
ByteArrayOutputStream ut = new ByteArrayOutputStream();
Ux)s4~0`!A0 int ch;51Testing软件测试网f1`B+c?6q h
String res = "";51Testing软件测试网_'r,d\'~I
while ((ch = inStream.read()) != -1) {51Testing软件测试网q/B#m]Ck+~
out.write(ch);
)z[0H3W5q}q$U0 }51Testing软件测试网r"S9[&Zp/K
byte[] result = out.toByteArray();
x!B wI+g0 res = Base64.byteArrayToBase64(result);51Testing软件测试网H4n9D!wUN
return res;51Testing软件测试网sz{9aT"E
}
-\+[sc;FpDZ0
TAG:
不要让那些真正对你好的人,慢慢的从你的生活中消失,无论爱情还是友情,都需要用心经营。
我的栏目
标题搜索
日历
|
|||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
1 | 2 | ||||||||
3 | 4 | 5 | 6 | 7 | 8 | 9 | |||
10 | 11 | 12 | 13 | 14 | 15 | 16 | |||
17 | 18 | 19 | 20 | 21 | 22 | 23 | |||
24 | 25 | 26 | 27 | 28 | 29 | 30 | |||
31 |
我的存档
数据统计
- 访问量: 3333849
- 日志数: 1640
- 建立时间: 2011-12-07
- 更新时间: 2019-12-24