Java中RSA非对称密钥加解密使用示例

上一篇 / 下一篇  2012-09-10 09:20:32 / 个人分类:Java

51Testing软件测试网m](K9oro P&{

  一、简介: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_!V0

Z"yR6M6l:R k0  三、使用方式:51Testing软件测试网6I{r|!K+zn&Rp/P8f

51Testing软件测试网Gz'e(Q4b n

  ① 假设A、B机器进行通信,已A机器为主;

f Em%B]|Z051Testing软件测试网,Q$WD.^U^"^|

  ② A首先需要用自己的私钥为发送请求数据签名,并将公钥一同发送给B;

$m2`b;T:cT\|0

Ie3Fu/qA[ { [3an0  ③ B收到数据后,需要用A发送的公钥进行验证,已确保收到的数据是未经篡改的;

'U GMQ9cX8nn0

SIE{ @\"ZgDS0  ④ B验签通过后,处理逻辑,并把处理结果返回,返回数据需要用A发送的公钥进行加密(公钥加密后,只能用配对的私钥解密);51Testing软件测试网e.n3_jr C J

51Testing软件测试网mQ8_a3K'y(}(g0X

  ⑤ A收到B返回的数据,使用私钥解密,至此,一次数据交互完成。

B [C.HQ0

C$yf"F*J"z ZA[0  四、代码示例:51Testing软件测试网$]8[%O ve2}FR"Q

r"k(G#QLuh&w{0  1、第一步获取私钥,为签名做准备。51Testing软件测试网nAx;nR

/**51Testing软件测试网]!Xjj&Bh
     * 读取私钥  返回PrivateKey51Testing软件测试网3Qb4Vc-N AI
     * @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&F FG0     * @throws NoSuchAlgorithmException
xn e0s#{#Y0     * @throws CertificateException51Testing软件测试网c:luz.J P"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*bh n0            IOException, UnrecoverableKeyException {
E0wa e y3{9~'|v0        KeyStore ks = KeyStore.getInstance("PKCS12");
3R9?+h Cf?D0        FileInputStream fis = new FileInputStream(path);51Testing软件测试网;p vm1F1g5p
        char[] nPassword = null;51Testing软件测试网4L)A)WVZ9d2v7r
        if ((password == null) || password.trim().equals("")) {
Z7PA7^!?HI}0            nPassword = null;51Testing软件测试网C*W3h#]OehuG
        } else {
PlYs!Lz8c8Bm0            nPassword = password.toCharArray();
'_O4t~2z0        }
0z#mFc9[s&eI [-g c0        ks.load(fis, nPassword);51Testing软件测试网A)kNw9V+D A i"c ~
        fis.close();51Testing软件测试网g a'?;O }1[~Q lY
        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$My X R
        }51Testing软件测试网k YdT`.O d"Ha
 51Testing软件测试网"N9|-Dq/nM v8aY'L&g
        return (PrivateKey) ks.getKey(keyAlias, nPassword);
^/g4Hm?3o0    }
51Testing软件测试网2HQ9pe"{1^,daY

  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(B O9U
        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_sbD N0        return Base64.byteArrayToBase64(rsaBytes);51Testing软件测试网.eLOO$V
 3、B收到数据后,需要使用A提供的公钥信息进行验签,此处使用公钥的N、E进行验签
51Testing软件测试网2mU#Pm _@P

  首先通过公钥N、E得到公钥PublicKey,如下:

"[2wa z?og"X051Testing软件测试网 Zr4W8bcUu.l7n

LI: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#r X0        return publicKey;51Testing软件测试网'?,v+\pi3@hxg
    }
51Testing软件测试网Tj u"d'F'uy

  得到公钥PublicKey后,再去验证签名,代码如下:51Testing软件测试网r[Z-T%O}^7Vw(yo

l.GGUOpxY0

}ji+_+{ k0
/**
DE"@ v-R J6FK+x0     * 用公钥证书进行验签51Testing软件测试网%C*dv nGt
     * @param message  签名之前的原文51Testing软件测试网8q ^1iP@-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;c iLu0     * @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(\+R U0wL9~{ d Z
        // 根据密钥,对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软件测试网+Z U2}: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软件测试网 S h?Fp
        if (md5Digest1.equals(md5Digest2)) {
h.C/Y{ y0            return true;51Testing软件测试网p8iB4f tg0M*gnu[ W
        } else {51Testing软件测试网7@7B+w,^8cWn7|:e
            return false;
/bW { Y }}H Kz0        }51Testing软件测试网y6W;I z1X
    }
51Testing软件测试网4@pZLYn

  至此,签名验签已经完毕51Testing软件测试网/FS;O-| v+n

51Testing软件测试网7S^R)[RC1gur(e(|

  4、提供一个从.cer文件读取公钥的方法:

9gn`PQ7mXd0

D F`wRWa0

+ZS%hv7q'Au0l \!Y0/**
w w T y%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?6qh
        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:

 

评分:0

我来说两句

Open Toolbar