.NETjavaRSA互通,仅此而已

在开始这篇文章之前,先请读者朋友阅读老唐的这两篇文章:

1、Java与.Net环境下RSA加密解密交互不成功的问题解决

2、Java与.Net环境下RSA加密解密交互不成功的问题解决【续】

和我的这篇文章

3、.NET_RSA加密全接触(重、难点解析)

前面老唐的两篇文章中提到,要想实现.NET和Java的RSA互通,只能抛弃.NET现有的加密算法,而是利用http://www.codeproject.com/csharp/biginteger.asp 项目中的BigInteger类(.NET Framework4中已增加了这个类的实现,在System.Numberic命名空间中),这个BigInteger类实际上就是仿照着java的BigInteger类来写的。

利用这个类的确可以很好的实现RSA的加解密,比如,在.NET端,构建一个公钥对应的BigInteger  e、一个模对应的BigInteger n和一个明文对应的BigInteger  m,然后执行语句BigInteger c=m.modPow(e,n),便可以实现加密操作,密文为c,这样的加密是标准加密,没有附加任何填充算法的加密。

老唐的文章中说,不能互通是因为加密标准不一样,导致一方加密而另一方不能解密,其实不然,.NET采用的加密标准是PKCS1Padding(或OAEPPadding——只支持XP以上版本),这也是我在前面一篇文章中提到的一种填充算法,而java同样支持这一填充标准,既然可以遵循统一的标准,那么.NET和java的RSA互通,无需添加任何新代码便可以轻松实现!

请看下面的示例(.NET端加密,Java端解密):

Java端代码:

  1. import java.math.BigInteger;
  2. import java.util.Scanner;
  3. import java.security.KeyFactory;
  4. import java.security.PrivateKey;
  5. import java.security.KeyPair;
  6. import java.security.KeyPairGenerator;
  7. import java.security.PublicKey;
  8. import java.security.interfaces.RSAPrivateKey;
  9. import java.security.interfaces.RSAPublicKey;
  10. import java.security.spec.RSAPublicKeySpec;
  11. import javax.crypto.Cipher;
  12. import sun.misc.*;
  13. public class RsaKey {
  14. public static void main(String[] args) throws Exception {
  15. //生成公私钥对
  16. KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
  17. keyPairGen.initialize(1024);
  18. KeyPair keyPair = keyPairGen.generateKeyPair();
  19. PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  20. PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
  21. //将公钥和模进行Base64编码
  22. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  23. RSAPublicKeySpec publicSpec= keyFactory.getKeySpec(publicKey,RSAPublicKeySpec.class);
  24. BigInteger modulus = publicSpec.getModulus();
  25. BigInteger exponent=publicSpec.getPublicExponent();
  26. byte[] ary_m=modulus.toByteArray();//注意:对公钥和模进行Base64编码时,不是对BigInteger对应的字符串编码,而是对其内部 的字节数组进行编码
  27. byte[] ary_e=exponent.toByteArray();
  28. String str_m;
  29. String str_e;
  30. if(ary_m[0]==0 && ary_m.length==129)//判断数组首元素是否为0,若是,则将其删除,保证模的位数是128
  31. {
  32. byte[] temp=new byte[ary_m.length-1];
  33. for(int i=1;i<ary_m.length;i++)
  34. {
  35. temp[i-1]=ary_m[i];
  36. }
  37. str_m=(new BASE64Encoder()).encodeBuffer(temp);
  38. }
  39. else
  40. {
  41. str_m=(new BASE64Encoder()).encodeBuffer(ary_m);
  42. }
  43. str_e=(new BASE64Encoder()).encodeBuffer(ary_e);
  44. System.out.println("公钥为:"+str_e);
  45. System.out.println("模为:"+str_m);
  46. System.out.println("运行.NET程序,用所提供的公钥和模进行加密,然后将加密结果输入本程序进行解密:");
  47. Scanner sc=new Scanner(System.in);
  48. String str_en="";
  49. String st="";
  50. while(!(st=sc.nextLine()).equals(""))
  51. {
  52. str_en+=st;
  53. }
  54. byte[] ary_en=(new BASE64Decoder()).decodeBuffer(str_en);
  55. //解密
  56. //注意Cipher初始化时的参数“RSA/ECB/PKCS1Padding”,代表和.NET用相同的填充算法,如果是标准RSA加密,则参数为“RSA”
  57. Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
  58. cipher.init(Cipher.DECRYPT_MODE, privateKey);
  59. byte[] deBytes = cipher.doFinal(ary_en);
  60. String s = new String(deBytes );
  61. System.out.println("解密结果为:" + s);
  62. }
  63. }

Java端演示截图

.NET端代码:

  1. static void Main(string[] args)
  2. {
  3. try
  4. {
  5. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  6. RSAParameters para = new RSAParameters();
  7. //加密
  8. Console.WriteLine("请输入公钥");
  9. string publicKey = Console.ReadLine();
  10. Console.WriteLine("请输入模:");
  11. string modulus = Console.ReadLine();
  12. while(true)
  13. {
  14. string s = Console.ReadLine();
  15. if (s == "")
  16. {
  17. break;
  18. }
  19. else
  20. {
  21. modulus += s;
  22. }
  23. }
  24. Console.WriteLine("请输入明文:");
  25. string m = Console.ReadLine();
  26. para.Exponent = Convert.FromBase64String(publicKey);
  27. para.Modulus = Convert.FromBase64String(modulus);
  28. rsa.ImportParameters(para);
  29. byte[] enBytes = rsa.Encrypt(UTF8Encoding.UTF8.GetBytes(m),false);
  30. Console.WriteLine("密文为:"+Convert.ToBase64String(enBytes));
  31. Console.ReadLine();
  32. }
  33. catch(Exception  ex)
  34. {
  35. Console.WriteLine(ex.Message);
  36. Console.ReadLine();
  37. }

.NET端演示截图:

接下来的示例是(java端加密,.NET端解密):

.net端代码:

  1. static void Main(string[] args)
  2. {
  3. try
  4. {
  5. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
  6. RSAParameters para = rsa.ExportParameters(true);
  7. //加¨®密¨¹
  8. Console.WriteLine("公?钥?为a:êo"+ Convert.ToBase64String(para.Exponent));
  9. Console.WriteLine("模¡ê为a:êo" + Convert.ToBase64String(para.Modulus));
  10. Console.WriteLine("请?输º?入¨?密¨¹文?");
  11. string enStr = Console.ReadLine();
  12. while(true)
  13. {
  14. string s = Console.ReadLine();
  15. if (s == "")
  16. {
  17. break;
  18. }
  19. else
  20. {
  21. enStr += s;
  22. }
  23. }
  24. byte[] deBytes = rsa.Decrypt(Convert.FromBase64String(enStr),false);
  25. Console.WriteLine("明¡Â文?为a:êo"+UTF8Encoding.UTF8.GetString(deBytes));
  26. Console.ReadLine();
  27. }
  28. catch(Exception  ex)
  29. {
  30. Console.WriteLine(ex.Message);
  31. Console.ReadLine();
  32. }
  33. }

Java端代码:

  1. public static void main(String[] args) throws Exception {
  2. Scanner sc=new Scanner(System.in);
  3. //获取公钥、模及明文的字符串
  4. System.out.println("请输入公钥:");
  5. String str_exponent=sc.nextLine();
  6. System.out.println("请输入模:");
  7. String str_modulus="";
  8. String st="";
  9. while(!(st=sc.nextLine()).equals(""))
  10. {
  11. str_modulus+=st;
  12. }
  13. System.out.println("请输入明文:");
  14. String str_m=sc.nextLine();
  15. //创建公钥
  16. byte[] ary_exponent=(new BASE64Decoder()).decodeBuffer(str_exponent);
  17. byte[] ary_modulus=(new BASE64Decoder()).decodeBuffer(str_modulus);
  18. //注意构造函数,调用时指明正负值,1代表正值,否则报错
  19. BigInteger big_exponent = new BigInteger(1,ary_exponent);
  20. BigInteger big_modulus = new BigInteger(1,ary_modulus);
  21. RSAPublicKeySpec keyspec=new RSAPublicKeySpec(big_modulus,big_exponent);
  22. KeyFactory keyfac=KeyFactory.getInstance("RSA");
  23. PublicKey publicKey=keyfac.generatePublic(keyspec);
  24. //进行加密
  25. Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
  26. cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  27. byte[] enBytes = cipher.doFinal(str_m.getBytes());
  28. String s = (new BASE64Encoder()).encodeBuffer(enBytes);
  29. System.out.println("加密结果为:" + s);
  30. }

.NET和java的RSA互通,仅此而已的更多相关文章

  1. Java & PHP RSA 互通密钥、签名、验签、加密、解密

    RSA加密算法是一种非对称加密算法.在公开密钥加密和电子商业中RSA被广泛使用.RSA是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Le ...

  2. php与JAVA的RSA加密互通

    Java 版本RSA 进行加密解密 在网上查询了好几天,最终找到解决方案,网络上都是通过Cipher.getInstance("RSA"); 而改成Cipher.getInstan ...

  3. Java加密算法 RSA

    Java加密算法 RSA 2015-06-06 08:44 511人阅读 评论(0) 收藏 举报  分类: JAVA(57)  公钥加密也称为非对称加密.速度慢.加密和解密的钥匙不相同,某一个人持有私 ...

  4. Java前端Rsa公钥加密,后端Rsa私钥解密(目前还不支持中文加密解密,其他都行)

    Base64工具类,可以让rsa编码的乱码变成一串字符序列 package com.utils; import java.io.ByteArrayInputStream; import java.io ...

  5. Java前端Rsa公钥加密,后端Rsa私钥解密(支持字符和中文)

    Base64工具类,可以让rsa编码的乱码变成一串字符序列 package com.utils; import java.io.ByteArrayInputStream; import java.io ...

  6. JAVA实现RSA加密,非对称加密算法

    RSA.java package org.icesnow.jeasywx.util.security; import java.security.Key; import java.security.K ...

  7. JAVA实现RSA加密解密 非对称算法

    首先RSA是一个非对称的加密算法.所以在使用该算法加密解密之前,必须先行生成密钥对.包含公钥和私钥 JDK中提供了生成密钥对的类KeyPairGenerator,实比例如以下: public stat ...

  8. 【转】 Java 进行 RSA 加解密时不得不考虑到的那些事儿

    [转] Java 进行 RSA 加解密时不得不考虑到的那些事儿 1. 加密的系统不要具备解密的功能,否则 RSA 可能不太合适 公钥加密,私钥解密.加密的系统和解密的系统分开部署,加密的系统不应该同时 ...

  9. java生成RSA公私钥字符串,简单易懂

    java生成RSA公私钥字符串,简单易懂   解决方法: 1.下载bcprov-jdk16-140.jar包,参考:http://www.yayihouse.com/yayishuwu/chapter ...

随机推荐

  1. ci总结

    1.创建模型,在模型中加载$this->load->database();2.在模型中写入想实现的功能方法3.在控制器中加载辅助函数和模型,$this->load->model ...

  2. 服务调用方案(Spring Http Invoker) - 我们到底能走多远系列(40)

    我们到底能走多远系列(40) 扯淡:  判断是否加可以效力于这家公司,一个很好的判断是,接触下这公司工作几年的员工,了解下生活工作状态,这就是你几年后的状态,如果满意就可以考虑加入了. 主题: 场景: ...

  3. ANTLR3完全参考指南读书笔记[02]

    前言 程序语言是什么? 用wiki上的描述,程序语言是一种人工设计的语言,用于通过指令与机器交互:程序语言是编程程序的标记,而程序是一种计算或算法的描述.详细介绍和背景信息参考: Programmin ...

  4. POJ 1797 Heavy Transportation

    题目链接:http://poj.org/problem?id=1797 Heavy Transportation Time Limit: 3000MS   Memory Limit: 30000K T ...

  5. android中的空格及汉字的宽度

    在Android布局中进行使用到空格,以便实现文字的对齐.那么在Android中如何表示一个空格呢? 空格:  窄空格:  一个汉字宽度的空格:   [用两个空格(  )占一个汉字的宽度时,两个空格比 ...

  6. session处理超时的三种方式

    1.      在web容器中设置(此处以tomcat为例) 在tomcat-5.0.28\conf\web.xml中设置,以下是tomcat 5.0中的默认配置: <!-- ========= ...

  7. SQL Server用户自定义函数

    用户自定义函数不能用于执行一系列改变数据库状态的操作,但它可以像系统 函数一样在查询或存储过程等的程序段中使用,也可以像存储过程一样通过EXECUTE 命令来执行.在 SQL Server 中根据函数 ...

  8. Android—进度条

    layout文件: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:an ...

  9. HDU-1828 Picture(扫描线)

    题目大意:给若干个矩形,求轮廓边长. 题目分析:与求面积类似.按从下往上扫描,仍然是底边添加,上边删除.但要同时维护竖边的数目,每次扫描对答案的贡献为扫描线上总覆盖长度的变化量加上竖边的增量.总覆盖长 ...

  10. Java theory and practice

    This content is part of the series: Java theory and practice A brief history of garbage collection A ...