MD5和RSA是网络传输中最常用的两个算法,了解这两个算法原理后就能大致知道加密是怎么一回事了。但这两种算法使用环境有差异,刚好互补。

一、MD5算法

首先MD5是不可逆的,只能加密而不能解密。比如明文是yanzi1225627,得到MD5加密后的字符串是:14F2AE15259E2C276A095E7394DA0CA9  但不能由后面一大串倒推出yanzi1225627.因此可以用来存储用户输入的密码在服务器上。现在下载文件校验文件是否中途被篡改也是用的它,原理参见:http://blog.csdn.net/forgotaboutgirl/article/details/7258109 无论在Android上还是pc上用java实现MD5都比较容易,因为java已经把它做到了java.security.MessageDigest里。下面是一个MD5Util.java类:

  1. <span style="font-family:Comic Sans MS;font-size:18px;">package org.md5.util;
  2. import java.security.MessageDigest;
  3. public class MD5Util {
  4. public final static String getMD5String(String s) {
  5. char hexDigits[] = { '0', '1', '2', '3', '4',
  6. '5', '6', '7', '8', '9',
  7. 'A', 'B', 'C', 'D', 'E', 'F' };
  8. try {
  9. byte[] btInput = s.getBytes();
  10. //获得MD5摘要算法的 MessageDigest 对象
  11. MessageDigest mdInst = MessageDigest.getInstance("MD5");
  12. //使用指定的字节更新摘要
  13. mdInst.update(btInput);
  14. //获得密文
  15. byte[] md = mdInst.digest();
  16. //把密文转换成十六进制的字符串形式
  17. int j = md.length;
  18. char str[] = new char[j * 2];
  19. int k = 0;
  20. for (int i = 0; i < j; i++) {
  21. byte byte0 = md[i];
  22. str[k++] = hexDigits[byte0 >>> 4 & 0xf];
  23. str[k++] = hexDigits[byte0 & 0xf];
  24. }
  25. return new String(str);
  26. }
  27. catch (Exception e) {
  28. e.printStackTrace();
  29. return null;
  30. }
  31. }
  32. }</span>

通过下面两行代码调用:

/************************************MD5加密测试*****************************/
String srcString = "yanzi1225627";
System.out.println("MD5加密后 = " + MD5Util.getMD5String(srcString));

二、RSA加密

RSA是可逆的,一个字符串可以经rsa加密后,经加密后的字符串传到对端如服务器上,再进行解密即可。前提是服务器知道解密的私钥,当然这个私钥最好不要再网络传输。RSA算法描述中需要以下几个变量:

1、p和q 是不相等的,足够大的两个质数。 p和q是保密的

2、n = p*q n是公开的

3、f(n) = (p-1)*(q-1)

4、e 是和f(n)互质的质数

5、计算参数d

6、经过上面5步计算得到公钥KU=(e,n) 私钥KR=(d,n)

下面两篇文章对此有清晰的描述:

http://wenku.baidu.com/view/e53fbe36a32d7375a417801b.html

http://bank.hexun.com/2009-06-24/118958531.html

下面是java实现RSAUtil.java类:

  1. <span style="font-family:Comic Sans MS;font-size:18px;">package org.rsa.util;
  2. import javax.crypto.Cipher;
  3. import java.security.*;
  4. import java.security.spec.RSAPublicKeySpec;
  5. import java.security.spec.RSAPrivateKeySpec;
  6. import java.security.spec.InvalidKeySpecException;
  7. import java.security.interfaces.RSAPrivateKey;
  8. import java.security.interfaces.RSAPublicKey;
  9. import java.io.*;
  10. import java.math.BigInteger;
  11. /**
  12. * RSA 工具类。提供加密,解密,生成密钥对等方法。
  13. * 需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。
  14. * RSA加密原理概述
  15. * RSA的安全性依赖于大数的分解,公钥和私钥都是两个大素数(大于100的十进制位)的函数。
  16. * 据猜测,从一个密钥和密文推断出明文的难度等同于分解两个大素数的积
  17. * ===================================================================
  18. * (该算法的安全性未得到理论的证明)
  19. * ===================================================================
  20. * 密钥的产生:
  21. * 1.选择两个大素数 p,q ,计算 n=p*q;
  22. * 2.随机选择加密密钥 e ,要求 e 和 (p-1)*(q-1)互质
  23. * 3.利用 Euclid 算法计算解密密钥 d , 使其满足 e*d = 1(mod(p-1)*(q-1)) (其中 n,d 也要互质)
  24. * 4:至此得出公钥为 (n,e) 私钥为 (n,d)
  25. * ===================================================================
  26. * 加解密方法:
  27. * 1.首先将要加密的信息 m(二进制表示) 分成等长的数据块 m1,m2,...,mi 块长 s(尽可能大) ,其中 2^s<n
  28. * 2:对应的密文是: ci = mi^e(mod n)
  29. * 3:解密时作如下计算: mi = ci^d(mod n)
  30. * ===================================================================
  31. * RSA速度
  32. * 由于进行的都是大数计算,使得RSA最快的情况也比DES慢上100倍,无论 是软件还是硬件实现。
  33. * 速度一直是RSA的缺陷。一般来说只用于少量数据 加密。
  34. *文件名:RSAUtil.java<br>
  35. *@author 董利伟<br>
  36. *版本:<br>
  37. *描述:<br>
  38. *创建时间:2008-9-23 下午09:58:16<br>
  39. *文件描述:<br>
  40. *修改者:<br>
  41. *修改日期:<br>
  42. *修改描述:<br>
  43. */
  44. public class RSAUtil {
  45. //密钥对
  46. private KeyPair keyPair = null;
  47. /**
  48. * 初始化密钥对
  49. */
  50. public RSAUtil(){
  51. try {
  52. this.keyPair = this.generateKeyPair();
  53. } catch (Exception e) {
  54. e.printStackTrace();
  55. }
  56. }
  57. /**
  58. * 生成密钥对
  59. * @return KeyPair
  60. * @throws Exception
  61. */
  62. private KeyPair generateKeyPair() throws Exception {
  63. try {
  64. KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());
  65. //这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低
  66. final int KEY_SIZE = 1024;
  67. keyPairGen.initialize(KEY_SIZE, new SecureRandom());
  68. KeyPair keyPair = keyPairGen.genKeyPair();
  69. return keyPair;
  70. } catch (Exception e) {
  71. throw new Exception(e.getMessage());
  72. }
  73. }
  74. /**
  75. * 生成公钥
  76. * @param modulus
  77. * @param publicExponent
  78. * @return RSAPublicKey
  79. * @throws Exception
  80. */
  81. private RSAPublicKey generateRSAPublicKey(byte[] modulus, byte[] publicExponent) throws Exception {
  82. KeyFactory keyFac = null;
  83. try {
  84. keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
  85. } catch (NoSuchAlgorithmException ex) {
  86. throw new Exception(ex.getMessage());
  87. }
  88. RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(publicExponent));
  89. try {
  90. return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
  91. } catch (InvalidKeySpecException ex) {
  92. throw new Exception(ex.getMessage());
  93. }
  94. }
  95. /**
  96. * 生成私钥
  97. * @param modulus
  98. * @param privateExponent
  99. * @return RSAPrivateKey
  100. * @throws Exception
  101. */
  102. private RSAPrivateKey generateRSAPrivateKey(byte[] modulus, byte[] privateExponent) throws Exception {
  103. KeyFactory keyFac = null;
  104. try {
  105. keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
  106. } catch (NoSuchAlgorithmException ex) {
  107. throw new Exception(ex.getMessage());
  108. }
  109. RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(privateExponent));
  110. try {
  111. return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
  112. } catch (InvalidKeySpecException ex) {
  113. throw new Exception(ex.getMessage());
  114. }
  115. }
  116. /**
  117. * 加密
  118. * @param key 加密的密钥
  119. * @param data 待加密的明文数据
  120. * @return 加密后的数据
  121. * @throws Exception
  122. */
  123. public byte[] encrypt(Key key, byte[] data) throws Exception {
  124. try {
  125. Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
  126. cipher.init(Cipher.ENCRYPT_MODE, key);
  127. //获得加密块大小,如:加密前数据为128个byte,而key_size=1024 加密块大小为127 byte,加密后为128个byte;
  128. //因此共有2个加密块,第一个127 byte第二个为1个byte
  129. int blockSize = cipher.getBlockSize();
  130. int outputSize = cipher.getOutputSize(data.length);//获得加密块加密后块大小
  131. int leavedSize = data.length % blockSize;
  132. int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize;
  133. byte[] raw = new byte[outputSize * blocksSize];
  134. int i = 0;
  135. while (data.length - i * blockSize > 0) {
  136. if (data.length - i * blockSize > blockSize)
  137. cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize);
  138. else
  139. cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize);
  140. //这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到ByteArrayOutputStream中
  141. //,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了OutputSize所以只好用dofinal方法。
  142. i++;
  143. }
  144. return raw;
  145. } catch (Exception e) {
  146. throw new Exception(e.getMessage());
  147. }
  148. }
  149. /**
  150. * 解密
  151. * @param key 解密的密钥
  152. * @param raw 已经加密的数据
  153. * @return 解密后的明文
  154. * @throws Exception
  155. */
  156. public byte[] decrypt(Key key, byte[] raw) throws Exception {
  157. try {
  158. Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
  159. cipher.init(cipher.DECRYPT_MODE, key);
  160. int blockSize = cipher.getBlockSize();
  161. ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
  162. int j = 0;
  163. while (raw.length - j * blockSize > 0) {
  164. bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
  165. j++;
  166. }
  167. return bout.toByteArray();
  168. } catch (Exception e) {
  169. throw new Exception(e.getMessage());
  170. }
  171. }
  172. /**
  173. * 返回公钥
  174. * @return
  175. * @throws Exception
  176. */
  177. public RSAPublicKey getRSAPublicKey() throws Exception{
  178. //获取公钥
  179. RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
  180. //获取公钥系数(字节数组形式)
  181. byte[] pubModBytes = pubKey.getModulus().toByteArray();
  182. //返回公钥公用指数(字节数组形式)
  183. byte[] pubPubExpBytes = pubKey.getPublicExponent().toByteArray();
  184. //生成公钥
  185. RSAPublicKey recoveryPubKey = this.generateRSAPublicKey(pubModBytes,pubPubExpBytes);
  186. return recoveryPubKey;
  187. }
  188. /**
  189. * 获取私钥
  190. * @return
  191. * @throws Exception
  192. */
  193. public RSAPrivateKey getRSAPrivateKey() throws Exception{
  194. //获取私钥
  195. RSAPrivateKey priKey = (RSAPrivateKey) keyPair.getPrivate();
  196. //返回私钥系数(字节数组形式)
  197. byte[] priModBytes = priKey.getModulus().toByteArray();
  198. //返回私钥专用指数(字节数组形式)
  199. byte[] priPriExpBytes = priKey.getPrivateExponent().toByteArray();
  200. //生成私钥
  201. RSAPrivateKey recoveryPriKey = this.generateRSAPrivateKey(priModBytes,priPriExpBytes);
  202. return recoveryPriKey;
  203. }
  204. }
  205. </span>

测试代码:

/****************************RSA加密解密测试********************************/
try {
RSAUtil rsa = new RSAUtil();
String str = "yanzi1225627";
RSAPublicKey pubKey = rsa.getRSAPublicKey();
RSAPrivateKey priKey = rsa.getRSAPrivateKey();
byte[] enRsaBytes = rsa.encrypt(pubKey,str.getBytes());
String enRsaStr = new String(enRsaBytes, "UTF-8");
System.out.println("加密后==" + enRsaStr);
System.out.println("解密后==" + new String(rsa.decrypt(priKey, rsa.encrypt(pubKey,str.getBytes()))));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

下面是执行结果:

加密后==s?ko?1@lo????BJ?iE???1Ux?Kx&??=??n
O? ?l?>?????2r?y??8v- \A??`????r?t3?-3y?hjL?M??Se?Z???????~?"??e??XZ?苜?
解密后==yanzi1225627

上面代码需要用到一个包rsa.jar,下载链接及上面的测试代码我已打包,下载链接见下:

http://download.csdn.net/detail/yanzi1225627/7382263

Android网络传输中必用的两个加密算法:MD5 和 RSA (附java完成测试代码)的更多相关文章

  1. Android网络传输中必用的两个加密算法:MD5 和 RSA (附java完毕測试代码)

    MD5和RSA是网络传输中最经常使用的两个算法,了解这两个算法原理后就能大致知道加密是怎么一回事了.但这两种算法使用环境有差异,刚好互补. 一.MD5算法 首先MD5是不可逆的,仅仅能加密而不能解密. ...

  2. Android网络传输中必用的两个加密算法:MD5 和 RSA

    MD5和RSA是网络传输中最常用的两个算法,了解这两个算法原理后就能大致知道加密是怎么一回事了.但这两种算法使用环境有差异,刚好互补. 一.MD5算法 首先MD5是不可逆的,只能加密而不能解密.比如明 ...

  3. Android网络传输中必用的两个加密算法:MD5 和 RSA 及Base64加密总结

    (1)commons-codec包简介 包含一些通用的编码解码算法.包括一些语音编码器,Hex,Base64.MD5 一.md5.base64.commons-codec包 commons-codec ...

  4. [转载]详解网络传输中的三张表,MAC地址表、ARP缓存表以及路由表

    [转载]详解网络传输中的三张表,MAC地址表.ARP缓存表以及路由表 虽然学过了计算机网络,但是这部分还是有点乱.正好在网上看到了一篇文章,讲的很透彻,转载过来康康. 本文出自 "邓奇的Bl ...

  5. (转载)详解网络传输中的三张表,MAC地址表、ARP缓存表以及路由表

    郑重声明:原文转载于http://dengqi.blog.51cto.com/5685776/1223132 向好文章致敬!!! 一:MAC地址表详解 说到MAC地址表,就不得不说一下交换机的工作原理 ...

  6. 网络传输中的三张表,MAC地址表、ARP缓存表以及路由表

    一:MAC地址表详解 说到MAC地址表,就不得不说一下交换机的工作原理了,因为交换机是根据MAC地址表转发数据帧的.在交换机中有一张记录着局域网主机MAC地址与交换机接口的对应关系的表,交换机就是根据 ...

  7. 详解网络传输中的三张表,MAC地址表、ARP缓存表以及路由表

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://dengqi.blog.51cto.com/5685776/1223132 一:M ...

  8. 网络传输中利用fastjson将复杂嵌套数据类型Json格式转换(GeoJsonPolygon)

    如果一个对象太复杂了,那么在网络传输键的JSON格式数据转换容易出问题. 比如下面一个类Area.java import lombok.AllArgsConstructor; import lombo ...

  9. 网络传输中的各种加密算法+SSL+CA证书详解

    1. 数据传输分类 在互联网上数据传输有两种:明文传输和加密传输.明文传输的协议有:ftp.http.smtp.telnet.但是为了数据的完整性和安全性,所以后来引用了加密等相关手段来保证数据的安全 ...

随机推荐

  1. Mac自定义隐藏或显示文件的快捷键

    Mac自定义隐藏或显示文件的快捷键 本教程教大家学会自定义隐藏和显示文件夹的快捷键(Command+Shift+.). 1. 打开应用程序--Automator--选择"服务"-- ...

  2. Hadoop学习(4)-- MapReduce

    MapReduce是一种用于大规模数据集的并行计算编程模型,由Google提出,主要用于搜索领域,解决海量数据的计算问题.其主要思想Map(映射)和Reduce(规约)都是从函数是编程语言中借鉴而来的 ...

  3. Java Thread线程控制

    一.线程和进程 进程是处于运行中的程序,具有一定的独立能力,进程是系统进行资源分配和调度的一个独立单位. 进程特征: A.独立性:进程是系统中独立存在的实体,可以拥有自己独立的资源,每个进程都拥有自己 ...

  4. PAT 解题报告 1047. Student List for Course (25)

    1047. Student List for Course (25) Zhejiang University has 40000 students and provides 2500 courses. ...

  5. SQL2008 R2 SP3中使用pivot实现行转列

    同事遇到一个问题,怎么实现行转列,参考了别人的示例,我是这样解决的. 创建数据源: create table #temp ( objectid int, sitename ), cities ), p ...

  6. System.Windows.Forms.Timer与System.Timers.Timer的区别(zz)

    .NET Framework里面提供了三种Timer: System.Windows.Forms.Timer System.Timers.Timer System.Threading.Timer VS ...

  7. java中HashSet详解(转)

    HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...

  8. iptables使用

    iptables规则的查看.添加.删除和修改 1.查看 iptables -nvL --line-number (这个命令跟/etc/init.d/iptables status 输出差不多) -L ...

  9. C++Primer 第三章

    //1.位于头文件中的代码一般不应该使用using声明.这是因为头文件的内容会拷贝到所有引用它的文件中,可能会产生始料未及的命名空间冲突. // 三种使用命名空间中的名字的方法 using names ...

  10. 系统性能调优CPU与内存

    CPU相关术语 处理器:插到系统插槽或者处理器版上的物理芯片,以核或者硬件线程的方式包含了一块或者多块CPU. 核:一颗多核处理器上的一个独立CPU实例.核的使用时处理器扩展的一种方式,有称为芯片级多 ...