zoukankan      html  css  js  c++  java
  • .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. }     

      

  • 相关阅读:
    HDU 5883 F
    关于codeblock 为什么不能调试
    Codeforces Round #378 (Div. 2) D. Kostya the Sculptor 分组 + 贪心
    51NOD 区间的价值 V2
    NYOJ 42 一笔画问题
    如何对二维字符数组进行排序
    hihoCoder 1383 : The Book List 北京网络赛
    利用IDA学习一个简单的安卓脱壳
    iOS APP可执行文件的组成
    Mac10.11 搭建php开发环境
  • 原文地址:https://www.cnblogs.com/adylee/p/3611758.html
Copyright © 2011-2022 走看看