IOS之RSA加密解密与后台之间的双向加密详解

  • Post author:
  • Post category:其他


IOS之RSA加密解密与后台之间的双向加密详解

序言

因为项目中需要用到

RSA

加密,刚开始也是有点乱,这两天也整理的差不多了,希望能帮到大家。

这次先上代码,我想大部分人肯定是着急解决问题,所以不要废话太多。

IOS端

后台是

PHP

,给我了一段公钥和他用私钥加密后的

base64

编码,让我先解一下,看看能否解出(请先不要纠结为什么给我公钥解密,公钥私钥都可以解密,具体后面会讲到)。

公钥:




  1. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3//sR2tXw0wrC2DySx8vNGlqt



  2. 3Y7ldU9+LBLI6e1KS5lfc5jlTGF7KBTSkCHBM3ouEHWqp1ZJ85iJe59aF5gIB2kl



  3. Bd6h4wrbbHA2XE1sq21ykja/Gqx7/IRia3zQfxGv/qEkyGOx+XALVoOlZqDwh76o



  4. 2n1vP1D+tD3amHsK7QIDAQAB

base64编码后的加密数据(注意:后台给你的一定是经过base64编码后的):

eZVIkIEDb83YfdpOQCTg1SMfJtAHjdl92oKCALYeItxwvvyBsIR/L2e7y1+rXYCztBELXff/L9SijAYrUWOcvPVLPlkJbiJhZjRn+v4L9UeLtSUfO/qv30K3JROb2OniOvRImK3ZcBq319VT8e62zjJscGBIlwfFfMxRVT/mAzY=

下面使用

RSA

这是一个封装的第三方框架,只需要将下面这两个文件导入到项目中,便可以使用(不用再导入其他的一些框架),别的框架不敢保证能使用,但这个是肯定可以使用的。

1.png

代码:



  1. //公钥


  2. NSString *publicKey = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3//sR2tXw0wrC2DySx8vNGlqt3Y7ldU9+LBLI6e1KS5lfc5jlTGF7KBTSkCHBM3ouEHWqp1ZJ85iJe59aF5gIB2klBd6h4wrbbHA2XE1sq21ykja/Gqx7/IRia3zQfxGv/qEkyGOx+XALVoOlZqDwh76o2n1vP1D+tD3amHsK7QIDAQAB";


  3. //base64编码后的加密数据


  4. NSString *base64Str = @"eZVIkIEDb83YfdpOQCTg1SMfJtAHjdl92oKCALYeItxwvvyBsIR/L2e7y1+rXYCztBELXff/L9SijAYrUWOcvPVLPlkJbiJhZjRn+v4L9UeLtSUfO/qv30K3JROb2OniOvRImK3ZcBq319VT8e62zjJscGBIlwfFfMxRVT/mAzY=";


  5. //结果:注意,这里是用公钥进行解密的,方法一定要用对


  6. NSString *resultStr = [RSA decryptString:base64Str publicKey:publicKey];


  7. NSLog(@"结果 = %@",resultStr);

打印结果:

2


这只是先进行测试的数据,如果给你私钥解密,就用别的方法,在

RSA.h

中可以很容易找到。

上面讲述的是单向加密,那么如何进行双向加密呢?

  • 1、

    iOS

    端和后台(这里后台使用的是java,因为我后台语言只会

    java

    ,效果都是一样的)各生成自己的公钥和私钥。
  • 2、

    iOS

    端生成的公钥和私钥定义为

    iOSPublicKey



    iOSPrivateKey



    java

    端生成的公钥私钥定义为

    javaPublicKey



    javaPrivateKey

    。将

    iOSPublicKey



    java

    ,让它用

    iOSPublicKey

    加密数据传给

    iOS

    端,

    iOS

    端用

    iOSPrivateKey

    解密;

    java

    端将

    javaPublicKey



    iOS

    端,

    iOS

    端用

    javaPublicKey

    加密数据后上传给

    java



    java

    端利用

    javaPrivateKey

    去解密,这样就实现了数据传输过程中的加密与解密,当然,也不一定非要按照我上面的步骤来,具体情况要和后台商量如何加密。

具体实现:

IOS端

  • 生成公钥和私钥

1)新建文件夹,用来保存生成的私钥和公钥,打开终端

cd 新建

,进入到新建文件夹中,

openssl

,打开openssl

3


  1. genrsa -out rsa_private_key.pem 1024

    生成私钥

4


  1. pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt

    这步一定要有,需要将私钥转成PKCS8的格式才能使用,此时复制私钥(先复制私钥,然后在4步取出公钥)

5

4)

rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

生成公钥

6

此时在新建文件夹中会出现两个文件

7


我们用文本编辑器打开便可获取

iOS

端生成的公钥和私钥。

  • Xcode项目实战

还得利用上面提到的

RSA

文件



  1. //公钥


  2. NSString *publicKey = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDl5RBHD3abOyeYCOLkaWkpJXgJQfMklOWPmdJAnG1eD6CV+UOpUKMy5LtfGHQEM7ao5x3BpMx4MNRUYVwBAmU84PhwNm6xpTJrg5zZCloFmsX+E5ukWE5YFRu8i5+5d8LuQTTTv4XfzbTCTOhON8uj+ypkomETuVNwgRFVFjHd1QIDAQAB";


  3. //私钥


  4. NSString *privateKey = @"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOXlEEcPdps7J5gI4uRpaSkleAlB8ySU5Y+Z0kCcbV4PoJX5Q6lQozLku18YdAQztqjnHcGkzHgw1FRhXAECZTzg+HA2brGlMmuDnNkKWgWaxf4Tm6RYTlgVG7yLn7l3wu5BNNO/hd/NtMJM6E43y6P7KmSiYRO5U3CBEVUWMd3VAgMBAAECgYEAkqHVDQ4O35oOegmI9plJauYsNvNqqzWRalN5aJ6dn3YmPiI8Bt2ZClgcLt6A+UEmy3qGX0HG7Q5wD9X9geNOQB3ZiD/pGAGW08wS/wTxnWSnSBwdtZ03pUttfnFctkxULfDq4iG1ywdjqEk3F8QVFajQ0c76kWbt9LGAv2OGIi0CQQD2CmbVFXy4JeNHK3TDoLMjsUCiLa+qPnyyVDLDG9Ozb7wN2ydTrMhI+0udmjKvy/Lm1E2bKyp42iYuubEqvSAXAkEA7zNZsOgUe0q73sxXqrLQ7Fs7TNtIEXghrGmkVTHN0I7uMKzQ7KEbA6hfcBm4hPMoLa6Ag3m9tiMNBWtDWc/Y8wJAK0//dEl5EC3TSccTohCbGJBukV47i1u+teHuobw3U2I7F7FZxfgntflPAWqQu7PKieob01IRAv9cM2OLFbv/dwJBAIniXedeQMA5ekaaIEbjwQ8eH/bTyJ1ZVH/gfbwmc2+vlJo2ZFCjJcFcA3fJO9ZXnGeI2cfwG22sksr24+IXsAUCQG5yvVIleTDYqWuWVG1Rc8fk5UFjoZzJpp0nil0z+0fR5rogr4fxcH7vbWsE0id7gSvtV7KxPzkvJTpOK3yGDN0=";


  5. //测试要加密的数据


  6. NSString *sourceStr = @"iOS端RSA";


  7. //公钥加密


  8. NSString *encryptStr = [RSA encryptString:sourceStr publicKey:publicKey];


  9. //私钥解密


  10. NSString *decrypeStr = [RSA decryptString:encryptStr privateKey:privateKey];


  11. NSLog(@"加密后的数据 %@ 解密后的数据 %@",encryptStr,decrypeStr);

打印结果:

8

经过测试,私钥和公钥是可以使用的。

JAVA端

我是用的是

Eclipse

,具体实现方法也是从网上找的,因为打开的东西太多,忘了是哪篇博客了,知道的请联系我,会注明作者的。

  • 前期准备

9



RSAUtils.java

代码:




  1. package RSA;



  2. import java.io.ByteArrayOutputStream;



  3. import java.security.Key;



  4. import java.security.KeyFactory;



  5. import java.security.KeyPair;



  6. import java.security.KeyPairGenerator;



  7. import java.security.PrivateKey;



  8. import java.security.PublicKey;



  9. import java.security.Signature;



  10. import java.security.interfaces.RSAPrivateKey;



  11. import java.security.interfaces.RSAPublicKey;



  12. import java.security.spec.PKCS8EncodedKeySpec;



  13. import java.security.spec.X509EncodedKeySpec;



  14. import java.util.HashMap;



  15. import java.util.Map;



  16. import javax.crypto.Cipher;



  17. /** *//**



  18. * <p>



  19. * RSA公钥/私钥/签名工具包



  20. * </p>



  21. * <p>



  22. * 罗纳德·李维斯特(Ron [R]ivest)、阿迪·萨莫尔(Adi [S]hamir)和伦纳德·阿德曼(Leonard [A]dleman)



  23. * </p>



  24. * <p>



  25. * 字符串格式的**在未在特殊说明情况下都为BASE64编码格式<br/>



  26. * 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>



  27. * 非对称加密算法可以用来对对称加密的**加密,这样保证**的安全也就保证了数据的安全



  28. * </p>



  29. *



  30. * @author IceWee



  31. * @date 2012-4-26



  32. * @version 1.0



  33. */



  34. public class RSAUtils {




  35. /** *//**



  36. * 加密算法RSA



  37. */



  38. public static final String KEY_ALGORITHM = "RSA";



  39. /** *//**



  40. * 签名算法



  41. */



  42. public static final String SIGNATURE_ALGORITHM = "MD5withRSA";



  43. /** *//**



  44. * 获取公钥的key



  45. */



  46. private static final String PUBLIC_KEY = "RSAPublicKey";



  47. /** *//**



  48. * 获取私钥的key



  49. */



  50. private static final String PRIVATE_KEY = "RSAPrivateKey";



  51. /** *//**



  52. * RSA最大加密明文大小



  53. */



  54. private static final int MAX_ENCRYPT_BLOCK = 117;



  55. /** *//**



  56. * RSA最大解密密文大小



  57. */



  58. private static final int MAX_DECRYPT_BLOCK = 128;



  59. /** *//**



  60. * <p>



  61. * 生成**对(公钥和私钥)



  62. * </p>



  63. *



  64. * @return



  65. * @throws Exception



  66. */



  67. public static Map<String, Object> genKeyPair() throws Exception {



  68. KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);



  69. keyPairGen.initialize(1024);



  70. KeyPair keyPair = keyPairGen.generateKeyPair();



  71. RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();



  72. RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();



  73. Map<String, Object> keyMap = new HashMap<String, Object>(2);



  74. keyMap.put(PUBLIC_KEY, publicKey);



  75. keyMap.put(PRIVATE_KEY, privateKey);



  76. return keyMap;



  77. }



  78. /** *//**



  79. * <p>



  80. * 用私钥对信息生成数字签名



  81. * </p>



  82. *



  83. * @param data 已加密数据



  84. * @param privateKey 私钥(BASE64编码)



  85. *



  86. * @return



  87. * @throws Exception



  88. */



  89. public static String sign(byte[] data, String privateKey) throws Exception {



  90. byte[] keyBytes = Base64Utils.decode(privateKey);



  91. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);



  92. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);



  93. PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);



  94. Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);



  95. signature.initSign(privateK);



  96. signature.update(data);



  97. return Base64Utils.encode(signature.sign());



  98. }



  99. /** *//**



  100. * <p>



  101. * 校验数字签名



  102. * </p>



  103. *



  104. * @param data 已加密数据



  105. * @param publicKey 公钥(BASE64编码)



  106. * @param sign 数字签名



  107. *



  108. * @return



  109. * @throws Exception



  110. *



  111. */



  112. public static boolean verify(byte[] data, String publicKey, String sign)



  113. throws Exception {



  114. byte[] keyBytes = Base64Utils.decode(publicKey);



  115. X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);



  116. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);



  117. PublicKey publicK = keyFactory.generatePublic(keySpec);



  118. Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);



  119. signature.initVerify(publicK);



  120. signature.update(data);



  121. return signature.verify(Base64Utils.decode(sign));



  122. }



  123. /** *//**



  124. * <P>



  125. * 私钥解密



  126. * </p>



  127. *



  128. * @param encryptedData 已加密数据



  129. * @param privateKey 私钥(BASE64编码)



  130. * @return



  131. * @throws Exception



  132. */



  133. public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)



  134. throws Exception {



  135. byte[] keyBytes = Base64Utils.decode(privateKey);



  136. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);



  137. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);



  138. Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);



  139. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());



  140. cipher.init(Cipher.DECRYPT_MODE, privateK);



  141. int inputLen = encryptedData.length;



  142. ByteArrayOutputStream out = new ByteArrayOutputStream();



  143. int offSet = 0;



  144. byte[] cache;



  145. int i = 0;



  146. // 对数据分段解密



  147. while (inputLen - offSet > 0) {



  148. if (inputLen - offSet > MAX_DECRYPT_BLOCK) {



  149. cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);



  150. } else {



  151. cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);



  152. }



  153. out.write(cache, 0, cache.length);



  154. i++;



  155. offSet = i * MAX_DECRYPT_BLOCK;



  156. }



  157. byte[] decryptedData = out.toByteArray();



  158. out.close();



  159. return decryptedData;



  160. }



  161. /** *//**



  162. * <p>



  163. * 公钥解密



  164. * </p>



  165. *



  166. * @param encryptedData 已加密数据



  167. * @param publicKey 公钥(BASE64编码)



  168. * @return



  169. * @throws Exception



  170. */



  171. public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)



  172. throws Exception {



  173. byte[] keyBytes = Base64Utils.decode(publicKey);



  174. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);



  175. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);



  176. Key publicK = keyFactory.generatePublic(x509KeySpec);



  177. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());



  178. cipher.init(Cipher.DECRYPT_MODE, publicK);



  179. int inputLen = encryptedData.length;



  180. ByteArrayOutputStream out = new ByteArrayOutputStream();



  181. int offSet = 0;



  182. byte[] cache;



  183. int i = 0;



  184. // 对数据分段解密



  185. while (inputLen - offSet > 0) {



  186. if (inputLen - offSet > MAX_DECRYPT_BLOCK) {



  187. cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);



  188. } else {



  189. cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);



  190. }



  191. out.write(cache, 0, cache.length);



  192. i++;



  193. offSet = i * MAX_DECRYPT_BLOCK;



  194. }



  195. byte[] decryptedData = out.toByteArray();



  196. out.close();



  197. return decryptedData;



  198. }



  199. /** *//**



  200. * <p>



  201. * 公钥加密



  202. * </p>



  203. *



  204. * @param data 源数据



  205. * @param publicKey 公钥(BASE64编码)



  206. * @return



  207. * @throws Exception



  208. */



  209. public static byte[] encryptByPublicKey(byte[] data, String publicKey)



  210. throws Exception {



  211. byte[] keyBytes = Base64Utils.decode(publicKey);



  212. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);



  213. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);



  214. Key publicK = keyFactory.generatePublic(x509KeySpec);



  215. // 对数据加密



  216. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());



  217. cipher.init(Cipher.ENCRYPT_MODE, publicK);



  218. int inputLen = data.length;



  219. ByteArrayOutputStream out = new ByteArrayOutputStream();



  220. int offSet = 0;



  221. byte[] cache;



  222. int i = 0;



  223. // 对数据分段加密



  224. while (inputLen - offSet > 0) {



  225. if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {



  226. cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);



  227. } else {



  228. cache = cipher.doFinal(data, offSet, inputLen - offSet);



  229. }



  230. out.write(cache, 0, cache.length);



  231. i++;



  232. offSet = i * MAX_ENCRYPT_BLOCK;



  233. }



  234. byte[] encryptedData = out.toByteArray();



  235. out.close();



  236. return encryptedData;



  237. }



  238. /** *//**



  239. * <p>



  240. * 私钥加密



  241. * </p>



  242. *



  243. * @param data 源数据



  244. * @param privateKey 私钥(BASE64编码)



  245. * @return



  246. * @throws Exception



  247. */



  248. public static byte[] encryptByPrivateKey(byte[] data, String privateKey)



  249. throws Exception {



  250. byte[] keyBytes = Base64Utils.decode(privateKey);



  251. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);



  252. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);



  253. Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);



  254. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());



  255. cipher.init(Cipher.ENCRYPT_MODE, privateK);



  256. int inputLen = data.length;



  257. ByteArrayOutputStream out = new ByteArrayOutputStream();



  258. int offSet = 0;



  259. byte[] cache;



  260. int i = 0;



  261. // 对数据分段加密



  262. while (inputLen - offSet > 0) {



  263. if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {



  264. cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);



  265. } else {



  266. cache = cipher.doFinal(data, offSet, inputLen - offSet);



  267. }



  268. out.write(cache, 0, cache.length);



  269. i++;



  270. offSet = i * MAX_ENCRYPT_BLOCK;



  271. }



  272. byte[] encryptedData = out.toByteArray();



  273. out.close();



  274. return encryptedData;



  275. }



  276. /** *//**



  277. * <p>



  278. * 获取私钥



  279. * </p>



  280. *



  281. * @param keyMap **对



  282. * @return



  283. * @throws Exception



  284. */



  285. public static String getPrivateKey(Map<String, Object> keyMap)



  286. throws Exception {



  287. Key key = (Key) keyMap.get(PRIVATE_KEY);



  288. return Base64Utils.encode(key.getEncoded());



  289. }



  290. /** *//**



  291. * <p>



  292. * 获取公钥



  293. * </p>



  294. *



  295. * @param keyMap **对 xs



  296. * @return



  297. * @throws Exception



  298. */



  299. public static String getPublicKey(Map<String, Object> keyMap)



  300. throws Exception {



  301. Key key = (Key) keyMap.get(PUBLIC_KEY);



  302. return Base64Utils.encode(key.getEncoded());



  303. }



  304. }


Base64Utils.java

文件代码:




  1. package RSA;



  2. import java.io.ByteArrayInputStream;



  3. import java.io.ByteArrayOutputStream;



  4. import java.io.File;



  5. import java.io.FileInputStream;



  6. import java.io.FileOutputStream;



  7. import java.io.InputStream;



  8. import java.io.OutputStream;



  9. import it.sauronsoftware.base64.Base64;



  10. public class Base64Utils {




  11. /** *//**



  12. * 文件读取缓冲区大小



  13. */



  14. private static final int CACHE_SIZE = 1024;



  15. /** *//**



  16. * <p>



  17. * BASE64字符串解码为二进制数据



  18. * </p>



  19. *



  20. * @param base64



  21. * @return



  22. * @throws Exception



  23. */



  24. public static byte[] decode(String base64) throws Exception {



  25. return Base64.decode(base64.getBytes());



  26. }



  27. /** *//**



  28. * <p>



  29. * 二进制数据编码为BASE64字符串



  30. * </p>



  31. *



  32. * @param bytes



  33. * @return



  34. * @throws Exception



  35. */



  36. public static String encode(byte[] bytes) throws Exception {



  37. return new String(Base64.encode(bytes));



  38. }



  39. /** *//**



  40. * <p>



  41. * 将文件编码为BASE64字符串



  42. * </p>



  43. * <p>



  44. * 大文件慎用,可能会导致内存溢出



  45. * </p>



  46. *



  47. * @param filePath 文件绝对路径



  48. * @return



  49. * @throws Exception



  50. */



  51. public static String encodeFile(String filePath) throws Exception {



  52. byte[] bytes = fileToByte(filePath);



  53. return encode(bytes);



  54. }



  55. /** *//**



  56. * <p>



  57. * BASE64字符串转回文件



  58. * </p>



  59. *



  60. * @param filePath 文件绝对路径



  61. * @param base64 编码字符串



  62. * @throws Exception



  63. */



  64. public static void decodeToFile(String filePath, String base64) throws Exception {



  65. byte[] bytes = decode(base64);



  66. byteArrayToFile(bytes, filePath);



  67. }



  68. /** *//**



  69. * <p>



  70. * 文件转换为二进制数组



  71. * </p>



  72. *



  73. * @param filePath 文件路径



  74. * @return



  75. * @throws Exception



  76. */



  77. public static byte[] fileToByte(String filePath) throws Exception {



  78. byte[] data = new byte[0];



  79. File file = new File(filePath);



  80. if (file.exists()) {



  81. FileInputStream in = new FileInputStream(file);



  82. ByteArrayOutputStream out = new ByteArrayOutputStream(2048);



  83. byte[] cache = new byte[CACHE_SIZE];



  84. int nRead = 0;



  85. while ((nRead = in.read(cache)) != -1) {



  86. out.write(cache, 0, nRead);



  87. out.flush();



  88. }



  89. out.close();



  90. in.close();



  91. data = out.toByteArray();



  92. }



  93. return data;



  94. }



  95. /** *//**



  96. * <p>



  97. * 二进制数据写文件



  98. * </p>



  99. *



  100. * @param bytes 二进制数据



  101. * @param filePath 文件生成目录



  102. */



  103. public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {



  104. InputStream in = new ByteArrayInputStream(bytes);



  105. File destFile = new File(filePath);



  106. if (!destFile.getParentFile().exists()) {



  107. destFile.getParentFile().mkdirs();



  108. }



  109. destFile.createNewFile();



  110. OutputStream out = new FileOutputStream(destFile);



  111. byte[] cache = new byte[CACHE_SIZE];



  112. int nRead = 0;



  113. while ((nRead = in.read(cache)) != -1) {



  114. out.write(cache, 0, nRead);



  115. out.flush();



  116. }



  117. out.close();



  118. in.close();



  119. }



  120. }


Test.java

文件中




  1. package RSA;



  2. import java.util.Map;



  3. public class Test {




  4. static String publicKey;



  5. static String privateKey;



  6. static {



  7. try {



  8. Map<String, Object> keyMap = RSAUtils.genKeyPair();



  9. publicKey = RSAUtils.getPublicKey(keyMap);



  10. privateKey = RSAUtils.getPrivateKey(keyMap);



  11. System.err.println("公钥: \n\r" + publicKey);



  12. System.err.println("私钥: \n\r" + privateKey);



  13. } catch (Exception e) {



  14. e.printStackTrace();



  15. }



  16. }



  17. public static void main(String[] args) throws Exception {




  18. test();



  19. }



  20. //加密数据



  21. static void test() throws Exception {



  22. String source = "Java端RSA";



  23. System.out.println("\r加密前文字:\r\n" + source);



  24. byte[] data = source.getBytes();



  25. byte[] encodedData = RSAUtils.encryptByPrivateKey(data,privateKey);



  26. System.out.println("加密后文字:\r\n" + new String(encodedData));



  27. byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, publicKey);



  28. String target = new String(decodedData);



  29. System.out.println("解密后文字: \r\n" + target);



  30. }



  31. //验证签名



  32. static void testSign() throws Exception {



  33. System.err.println("私钥加密——公钥解密");



  34. String source = "这是一行测试RSA数字签名的无意义文字";



  35. System.out.println("原文字:\r\n" + source);



  36. byte[] data = source.getBytes();



  37. byte[] encodedData = RSAUtils.encryptByPrivateKey(data, privateKey);



  38. System.out.println("加密后:\r\n" + new String(encodedData));



  39. byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, publicKey);



  40. String target = new String(decodedData);



  41. System.out.println("解密后: \r\n" + target);



  42. System.err.println("私钥签名——公钥验证签名");



  43. String sign = RSAUtils.sign(encodedData, privateKey);



  44. System.err.println("签名:\r" + sign);



  45. boolean status = RSAUtils.verify(encodedData, publicKey, sign);



  46. System.err.println("验证结果:\r" + status);



  47. }



  48. }

打印结果:

10


在此,我们可以获取java端生成的私钥和公钥


javaPrivateKey

:




  1. MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAICJzSMJQJWRMP/eAQpHpeFvoZ6TlEpDwzOu7U7COK0QFOfbSqw8+jVckcUXsbIeluay5kQBogrlzcBcEOUabMczFQRsb9Lo9fa1TObDPOb+Vexg2ndk6BjGO85npXTQlRx1PQzJ2JoFWjdwFxUX9bgkeZLgkYyPpQroHK4SIe5HAgMBAAECgYAYl8T67htAQp5IZjZ2vAyd3Fjk2UGnD936Nn7K8dgcLJaDYe6gk64fpY1yUz05YibnDtWFr3ZMdXlvU24cF3k2PoIyu/CK+/HxToAI1kx0yk52QdiBfiG9vPIqZmCCDWYm0kLE1ayEt2JMDbMWqlMfA7LWzlFEPsO63Jc4hH0BOQJBAPul4inORuoDgtBPxPGUcCICJJZ0xw+kFxgZjSnV0qcP3nQDdzqLiPPJ9Z8jJziIUEqXaxI0qOG7OFlMW8os5qUCQQCCwuBk/Gve/z+j386yiaJFQwxH8SAO97FuHDmYPJtdjrX7o6Uboq9GydzrPwNNK1odV4S858pXksZnU7K2lRl7AkEA6cv8i4qyJ8iLSK5T835Nj8sd4wsrxkRVkHZsyGl4BO6hZnex1hq9aoJASVGHpuY+co6rU4bJQK+Icq6WuQduYQJAaVcM5s3jKNaAMkhOf84ZB6sn7Zz2spggPBBI5beNgiVBveLrVAQPJ/vfGTS+OCDAi/rBWF1yyHHZm8v1oNkkmQJBAPJ5eXbeQngp3s4fi4wc+RuaXVpnwv1HHsUc3JlxfIRcuLthNKZJdLbQO8tjCfnEjztweJP6HjaO6VxZ50o/EDw=


javaPublicKey

:


上面的只是生成公钥和私钥并且是在当前环境测试,也就是iOS测试自己的,Java测试自己的,我上面也已经说了,

iOS

端与后台如何进行双向加密的,下面具体测试。

双向加密


  • iOS

    端加密,

    Java

    端解密


    iOS

    端利用

    javaPublicKey

    加密数据

11



java

端利用

javaPrivate

解密

12


打印结果:

13


  • Java

    端加密,

    iOS

    端解密


    Java

    端利用

    iOSPublicKey

    加密

14

15



iOS

端利用

iOSPrivateKey

解密

16

打印结果:

17

最后

至此,单向加密与双向加密,尤其是与后台之间的加密已经讲完了,因为之前看过一些文章有的很模糊,双向加密的讲解很少,并且一些文章的编辑格式真的是难看,根本就没办法看下去,所以花了一点时间讲讲我对这方面的理解,知识其实很浅,并不高深。

注意点:

1、关于

iOS

端保存的私钥和公钥最好是生成文件保存,并且设置密码,这样为了更安全,这个网上都有,可以找找。

2、在

RSA

原理上公钥和私钥是可以互相加密互相解密的。公钥加密,私钥解密一般是用于加密数据的,私钥加密公钥解密是用于验证身份的,也就是验证签名。但在iOS端只能用公钥加密私钥解密(不和后台交互,只是在iOS平台),只能用私钥加密公钥验签,请参考

文章

。如果是和后台进行加密,无论后台是用公钥加密还是私钥加密,iOS端都是可以解的。这个大家可以试试,在

RSA

文件中,其实他在

RSA.h

中已经说明了


// enc with private key NOT working YET!



+ (NSString *)encryptString:(NSString *)str privateKey:(NSString *)privKey;


用私钥加密的方法并未实现,具体

iOS

为何不能用私钥加密公钥解密还在搜索资料中,如果有知道的童鞋请告知,不胜感谢。

8月4日解答:关于非对称加密是没有说用私钥加密公钥解密的,私钥只能用来解密和生成签名,公钥只能用来加密和验签,特此声明!