.NET和java的RSA互通,仅此而已

.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端代码:

 

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

Java端演示截图

 

.NET端代码:

[c-sharp] view plaincopy
 
  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端代码:

[c-sharp] view plaincopy
 
  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端代码:

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

  

原文地址:https://www.cnblogs.com/adylee/p/3611758.html