RSA算法属非对称加密算法,在实际使用中,往往客户端使用公钥进行加密传递敏感数据,服务端server使用私钥进行解密,这样防止中间人从网络获取敏感数据的明文。
Android端主要代码如下:
1 package com.example.rsatest; 2 3 import java.io.UnsupportedEncodingException; 4 import java.math.BigInteger; 5 import java.security.KeyFactory; 6 import java.security.KeyPair; 7 import java.security.KeyPairGenerator; 8 import java.security.NoSuchAlgorithmException; 9 import java.security.PrivateKey; 10 import java.security.PublicKey; 11 import java.security.Signature; 12 import java.security.interfaces.RSAPrivateCrtKey; 13 import java.security.interfaces.RSAPublicKey; 14 import java.security.spec.RSAPrivateCrtKeySpec; 15 import java.security.spec.RSAPublicKeySpec; 16 import java.util.Date; 17 18 import javax.crypto.Cipher; 19 20 public class RsaHelper 21 { 22 /** 23 * 生成RSA密钥对(默认密钥长度为1024) 24 * 25 * @return 26 */ 27 public static KeyPair generateRSAKeyPair() 28 { 29 return generateRSAKeyPair(1024); 30 } 31 32 /** 33 * 生成RSA密钥对 34 * 35 * @param keyLength 密钥长度,范围:512~2048 36 * @return 37 */ 38 public static KeyPair generateRSAKeyPair(int keyLength) 39 { 40 try 41 { 42 KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA/ECB/PKCS1Padding"); 43 kpg.initialize(keyLength); 44 return kpg.genKeyPair(); 45 } 46 catch (NoSuchAlgorithmException e) 47 { 48 return null; 49 } 50 } 51 52 /* 53 * java端公钥转换成C#公钥 54 */ 55 public static String encodePublicKeyToXml(PublicKey key) 56 { 57 if (!RSAPublicKey.class.isInstance(key)) 58 { 59 return null; 60 } 61 RSAPublicKey pubKey = (RSAPublicKey) key; 62 StringBuilder sb = new StringBuilder(); 63 64 sb.append("<RSAKeyValue>"); 65 sb.append("<Modulus>") 66 .append(Base64Helper.encode(pubKey.getModulus().toByteArray())) 67 .append("</Modulus>"); 68 sb.append("<Exponent>") 69 .append(Base64Helper.encode(pubKey.getPublicExponent().toByteArray())) 70 .append("</Exponent>"); 71 sb.append("</RSAKeyValue>"); 72 return sb.toString(); 73 } 74 75 /* 76 * C#端公钥转换成java公钥 77 */ 78 public static PublicKey decodePublicKeyFromXml(String xml) 79 { 80 xml = xml.replaceAll("\r", "").replaceAll("\n", ""); 81 BigInteger modulus = 82 new BigInteger(1, Base64Helper.decode(StringUtils.getMiddleString(xml, 83 "<Modulus>", "</Modulus>"))); 84 BigInteger publicExponent = 85 new BigInteger(1, Base64Helper.decode(StringUtils.getMiddleString(xml, 86 "<Exponent>", "</Exponent>"))); 87 88 RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, publicExponent); 89 90 KeyFactory keyf; 91 try 92 { 93 keyf = KeyFactory.getInstance("RSA"); 94 return keyf.generatePublic(rsaPubKey); 95 } 96 catch (Exception e) 97 { 98 return null; 99 } 100 } 101 102 /* 103 * C#端私钥转换成java私钥 104 */ 105 public static PrivateKey decodePrivateKeyFromXml(String xml) 106 { 107 xml = xml.replaceAll("\r", "").replaceAll("\n", ""); 108 BigInteger modulus = 109 new BigInteger(1, Base64Helper.decode(StringUtils.getMiddleString(xml, 110 "<Modulus>", "</Modulus>"))); 111 BigInteger publicExponent = 112 new BigInteger(1, Base64Helper.decode(StringUtils.getMiddleString(xml, 113 "<Exponent>", "</Exponent>"))); 114 BigInteger privateExponent = 115 new BigInteger(1, Base64Helper.decode(StringUtils.getMiddleString(xml, "<D>", 116 "</D>"))); 117 BigInteger primeP = 118 new BigInteger(1, Base64Helper.decode(StringUtils.getMiddleString(xml, "<P>", 119 "</P>"))); 120 BigInteger primeQ = 121 new BigInteger(1, Base64Helper.decode(StringUtils.getMiddleString(xml, "<Q>", 122 "</Q>"))); 123 BigInteger primeExponentP = 124 new BigInteger(1, Base64Helper.decode(StringUtils.getMiddleString(xml, 125 "<DP>", "</DP>"))); 126 BigInteger primeExponentQ = 127 new BigInteger(1, Base64Helper.decode(StringUtils.getMiddleString(xml, 128 "<DQ>", "</DQ>"))); 129 BigInteger crtCoefficient = 130 new BigInteger(1, Base64Helper.decode(StringUtils.getMiddleString(xml, 131 "<InverseQ>", "</InverseQ>"))); 132 133 RSAPrivateCrtKeySpec rsaPriKey = 134 new RSAPrivateCrtKeySpec(modulus, publicExponent, privateExponent, primeP, 135 primeQ, primeExponentP, primeExponentQ, crtCoefficient); 136 137 KeyFactory keyf; 138 try 139 { 140 keyf = KeyFactory.getInstance("RSA"); 141 return keyf.generatePrivate(rsaPriKey); 142 } 143 catch (Exception e) 144 { 145 return null; 146 } 147 } 148 149 /* 150 * java端私钥转换成C#私钥 151 */ 152 public static String encodePrivateKeyToXml(PrivateKey key) 153 { 154 if (!RSAPrivateCrtKey.class.isInstance(key)) 155 { 156 return null; 157 } 158 RSAPrivateCrtKey priKey = (RSAPrivateCrtKey) key; 159 StringBuilder sb = new StringBuilder(); 160 161 sb.append("<RSAKeyValue>"); 162 sb.append("<Modulus>") 163 .append(Base64Helper.encode(priKey.getModulus().toByteArray())) 164 .append("</Modulus>"); 165 sb.append("<Exponent>") 166 .append(Base64Helper.encode(priKey.getPublicExponent().toByteArray())) 167 .append("</Exponent>"); 168 sb.append("<P>").append(Base64Helper.encode(priKey.getPrimeP().toByteArray())) 169 .append("</P>"); 170 sb.append("<Q>").append(Base64Helper.encode(priKey.getPrimeQ().toByteArray())) 171 .append("</Q>"); 172 sb.append("<DP>") 173 .append(Base64Helper.encode(priKey.getPrimeExponentP().toByteArray())) 174 .append("</DP>"); 175 sb.append("<DQ>") 176 .append(Base64Helper.encode(priKey.getPrimeExponentQ().toByteArray())) 177 .append("</DQ>"); 178 sb.append("<InverseQ>") 179 .append(Base64Helper.encode(priKey.getCrtCoefficient().toByteArray())) 180 .append("</InverseQ>"); 181 sb.append("<D>") 182 .append(Base64Helper.encode(priKey.getPrivateExponent().toByteArray())) 183 .append("</D>"); 184 sb.append("</RSAKeyValue>"); 185 return sb.toString(); 186 } 187 188 // 用公钥加密 189 public static byte[] encryptData(byte[] data, PublicKey pubKey) 190 { 191 try 192 { 193 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 194 cipher.init(Cipher.ENCRYPT_MODE, pubKey); 195 return cipher.doFinal(data); 196 } 197 catch (Exception e) 198 { 199 return null; 200 } 201 } 202 203 // 用私钥解密 204 public static byte[] decryptData(byte[] encryptedData, PrivateKey priKey) 205 { 206 try 207 { 208 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 209 cipher.init(Cipher.DECRYPT_MODE, priKey); 210 return cipher.doFinal(encryptedData); 211 } 212 catch (Exception e) 213 { 214 return null; 215 } 216 } 217 218 /** 219 * 根据指定公钥进行明文加密 220 * 221 * @param plainText 要加密的明文数据 222 * @param pubKey 公钥 223 * @return 224 */ 225 public static String encryptDataFromStr(String plainText, PublicKey pubKey) 226 { 227 228 try 229 { 230 byte[] dataByteArray = plainText.getBytes("UTF-8"); 231 byte[] encryptedDataByteArray = RsaHelper.encryptData(dataByteArray, pubKey); 232 return Base64Helper.encode(encryptedDataByteArray); 233 } 234 catch (UnsupportedEncodingException e) 235 { 236 // TODO Auto-generated catch block 237 e.printStackTrace(); 238 return ""; 239 } 240 } 241 242 /** 243 * 根据指定私钥对数据进行签名(默认签名算法为"SHA1withRSA") 244 * 245 * @param data 要签名的数据 246 * @param priKey 私钥 247 * @return 248 */ 249 public static byte[] signData(byte[] data, PrivateKey priKey) 250 { 251 return signData(data, priKey, "SHA1withRSA"); 252 } 253 254 /** 255 * 根据指定私钥和算法对数据进行签名 256 * 257 * @param data 要签名的数据 258 * @param priKey 私钥 259 * @param algorithm 签名算法 260 * @return 261 */ 262 public static byte[] signData(byte[] data, PrivateKey priKey, String algorithm) 263 { 264 try 265 { 266 Signature signature = Signature.getInstance(algorithm); 267 signature.initSign(priKey); 268 signature.update(data); 269 return signature.sign(); 270 } 271 catch (Exception ex) 272 { 273 return null; 274 } 275 } 276 277 /** 278 * 用指定的公钥进行签名验证(默认签名算法为"SHA1withRSA") 279 * 280 * @param data 数据 281 * @param sign 签名结果 282 * @param pubKey 公钥 283 * @return 284 */ 285 public static boolean verifySign(byte[] data, byte[] sign, PublicKey pubKey) 286 { 287 return verifySign(data, sign, pubKey, "SHA1withRSA"); 288 } 289 290 /** 291 * @param data 数据 292 * @param sign 签名结果 293 * @param pubKey 公钥 294 * @param algorithm 签名算法 295 * @return 296 */ 297 public static boolean verifySign(byte[] data, byte[] sign, PublicKey pubKey, 298 String algorithm) 299 { 300 try 301 { 302 Signature signature = Signature.getInstance(algorithm); 303 signature.initVerify(pubKey); 304 signature.update(data); 305 return signature.verify(sign); 306 } 307 catch (Exception ex) 308 { 309 return false; 310 } 311 } 312 313 public static void main(String[] args) 314 { 315 KeyPair kp = RsaHelper.generateRSAKeyPair(); 316 PublicKey pubKey = kp.getPublic(); 317 PrivateKey priKey = kp.getPrivate(); 318 319 String pubKeyXml = RsaHelper.encodePublicKeyToXml(pubKey); 320 String priKeyXml = RsaHelper.encodePrivateKeyToXml(priKey); 321 System.out.println("====公钥===="); 322 System.out.println(pubKeyXml); 323 System.out.println("====私钥===="); 324 System.out.println(priKeyXml); 325 326 PublicKey pubKey2 = RsaHelper.decodePublicKeyFromXml(pubKeyXml); 327 PrivateKey priKey2 = RsaHelper.decodePrivateKeyFromXml(priKeyXml); 328 329 System.out.println("====公钥对比===="); 330 System.out.println(pubKey.toString()); 331 System.out.println("------"); 332 System.out.println(pubKey2.toString()); 333 334 System.out.println("====私钥对比===="); 335 System.out.println(priKey.toString()); 336 System.out.println("------"); 337 System.out.println(priKey2.toString()); 338 339 try 340 { 341 String pubKeyXml3 = 342 "<RSAKeyValue><Modulus>rHESyuI3ny4MLsqDBalW9ySaodCL0e6Bsrl01Q5G1qm2wjUoGULazZSNqZY+JQNjU92tW3Snk5RPIkv+wDj+uOT9LTUjQImltHnzqMvbt06GipVXDOyBLTa7G/zRIe/CrjyJ+XEYX2xIhpe5ayowl3HHUpZ71jRNioyxaVVZ8S0=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"; 343 String priKeyXml3 = 344 "<RSAKeyValue><Modulus>rHESyuI3ny4MLsqDBalW9ySaodCL0e6Bsrl01Q5G1qm2wjUoGULazZSNqZY+JQNjU92tW3Snk5RPIkv+wDj+uOT9LTUjQImltHnzqMvbt06GipVXDOyBLTa7G/zRIe/CrjyJ+XEYX2xIhpe5ayowl3HHUpZ71jRNioyxaVVZ8S0=</Modulus><Exponent>AQAB</Exponent><P>5a7uM+IeY8QMVQl0q88ZTqWbB555l7+366cUIClTN8z2ZXzTnWFCNoQzUrG14FouJFYumFZD12Ni5MkJK6gqSw==</P><Q>wDMhwwO4kz82uSG+FlCBr06fYk2COTg0TofmSp/5OrVqgkBIe7FgpTpVGzGLk0mvOLcy6UZftq//W0Saow6nZw==</Q><DP>FbjDgliiMyE5YVlxlUYSyKNU1BWivj09caXte1UtL5vMubBiewHVtz4tdGamIr+kmX8lDPcrl1Uo5yY0HdLbnQ==</DP><DQ>kIjjJsgxkWnEOUyKqjU4kSDK8x3ehDEkBLpmEFBlGCU9R14YJAyr5RUM0zpbABQ1VK1P9+UYLUYE/hmFQIHQmQ==</DQ><InverseQ>pxQDThwSnUZ4EaNaCPl1ovYypdQUZaZ/Sld1+0n8FEjkmRcGP1R9VMuj1ViPZg3rvm2GeP8Xv1SJqJUVueWiGA==</InverseQ><D>DxBNoPWEAF7IZ6n/KhZx52MGMw6BuFQKdm9m+lml7Iik03BLUXGapYzNlzvtr9QM8D2UMEIPhX/WLdvPpEEWVzGnD7XpLXjGwfu1ZkJRcXPEZEZ2subh5ZBqOWCFWKv5WwgGYWuYDLHfrBlBgSFWR8cZuyqkmMsWl4CiadXqGA0=</D></RSAKeyValue>"; 345 346 System.out.println((new Date()).toLocaleString() + ": 加载公钥中。。。"); 347 PublicKey pubKey3 = RsaHelper.decodePublicKeyFromXml(pubKeyXml3); 348 System.out.println((new Date()).toLocaleString() + ": 加载私钥中。。。"); 349 PrivateKey priKey3 = RsaHelper.decodePrivateKeyFromXml(priKeyXml3); 350 351 String dataStr = "Java与.NET和平共处万岁!"; 352 byte[] dataByteArray = dataStr.getBytes("utf-8"); 353 System.out.println("data的Base64表示:" + Base64Helper.encode(dataByteArray)); 354 355 System.out.println((new Date()).toLocaleString() + ": 加密中。。。"); // 加密 356 byte[] encryptedDataByteArray = RsaHelper.encryptData(dataByteArray, pubKey3); 357 358 System.out.println("encryptedData的Base64表示:" 359 + Base64Helper.encode(encryptedDataByteArray)); 360 System.out.println((new Date()).toLocaleString() + ": 解密中。。。"); // 解密 361 // byte[] 362 byte[] decryptedDataByteArray = 363 RsaHelper.decryptData(encryptedDataByteArray, priKey3); 364 System.out.println(new String(decryptedDataByteArray, "utf-8"));// 签名 365 System.out.println((new Date()).toLocaleString() + ": 签名中。。。"); 366 byte[] signDataByteArray = RsaHelper.signData(dataByteArray, priKey3); 367 System.out.println("signData的Base64表示:" 368 + Base64Helper.encode(signDataByteArray)); // 验签 369 System.out.println((new Date()).toLocaleString() + ": 验签中。。。"); 370 boolean isMatch = 371 RsaHelper.verifySign(dataByteArray, signDataByteArray, pubKey3); 372 System.out.println("验签结果:" + isMatch); 373 374 } 375 catch (Exception ex) 376 { 377 ex.printStackTrace(); 378 } 379 } 380 }