现在的位置: 首页 > 综合 > 正文

C# Java间进行RSA加密解密交互 .

2018年02月12日 ⁄ 综合 ⁄ 共 46232字 ⁄ 字号 评论关闭

接着前面一篇C# Java间进行RSA加密解密交互(二)说吧,在上篇中为了实现

  1. /**  
  2.  * RSA加密  
  3.  * @param text--待加密的明文  
  4.  * @param key--公钥,由服务器端提供的经base64编码的字符串  
  5.  * @return  
  6.  */    
  7. public static String RSAEncryptoWithPublicKey(String text, String key) {    
  8.     String result = null;    
  9.     ......  
  10.     return result;    
  11. }  

加密过程,采用了折中办法,由Java产生Java客户端所需要的公钥数据信息,经由服务器传给客户端,而密钥则保存在服务器端。

现在,从根本上解决问题,有C#直接产生密钥对,私钥保存在服务器端,公钥传送给客户端,而且公钥正好满足上述方法要求。不过,这里用到了第三方插件BouncyCastle.cs。由于源码太长了,这里就不贴出来了。自己可以到http://www.bouncycastle.org/csharp/或者 http://yun.baidu.com/pcloud/album/file?album_id=7143016160664723357&uk=3895283693&fsid=421719398459611下载。这里演示其在Java
C#间交互加解密过程。

1、由C#生成及加解密过程

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. using Org.BouncyCastle.Crypto.Generators;  
  7. using Org.BouncyCastle.Crypto.Parameters;  
  8. using Org.BouncyCastle.Crypto;  
  9. using Org.BouncyCastle.Security;  
  10. using Org.BouncyCastle.Crypto.Engines;  
  11. using Org.BouncyCastle.Math;  
  12. using Org.BouncyCastle.Asn1.X509;  
  13. using Org.BouncyCastle.X509;  
  14. using Org.BouncyCastle.Utilities.Collections;   
  15. using Org.BouncyCastle.Asn1.Pkcs;  
  16. using Org.BouncyCastle.Pkcs;  
  17. using Org.BouncyCastle.Asn1;   
  18.   
  19. namespace ConsoleApplication2  
  20. {  
  21.     class Program  
  22.     {  
  23.         static void Main(string[] args)  
  24.         {  
  25.             //生成密钥对   
  26.             RsaKeyPairGenerator rsaKeyPairGenerator = new RsaKeyPairGenerator();  
  27.             RsaKeyGenerationParameters rsaKeyGenerationParameters = new RsaKeyGenerationParameters(BigInteger.ValueOf(3), new Org.BouncyCastle.Security.SecureRandom(), 1024, 25);  
  28.             rsaKeyPairGenerator.Init(rsaKeyGenerationParameters);//初始化参数
      
  29.             AsymmetricCipherKeyPair keyPair = rsaKeyPairGenerator.GenerateKeyPair();  
  30.             AsymmetricKeyParameter publicKey = keyPair.Public;//公钥
      
  31.             AsymmetricKeyParameter privateKey = keyPair.Private;//私钥
      
  32.   
  33.             SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);  
  34.             PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey);  
  35.   
  36.             Asn1Object asn1ObjectPublic = subjectPublicKeyInfo.ToAsn1Object();  
  37.             byte[] publicInfoByte = asn1ObjectPublic.GetEncoded();  
  38.             Asn1Object asn1ObjectPrivate = privateKeyInfo.ToAsn1Object();  
  39.             byte[] privateInfoByte = asn1ObjectPrivate.GetEncoded();  
  40.   
  41.             //这里可以将密钥对保存到本地
      
  42.             Console.WriteLine("PublicKey:\n" + Convert.ToBase64String(publicInfoByte));  
  43.             Console.WriteLine("PrivateKey:\n" + Convert.ToBase64String(privateInfoByte));  
  44.   
  45.             //加密、解密   
  46.             Asn1Object pubKeyObj = Asn1Object.FromByteArray(publicInfoByte);//这里也可以从流中读取,从本地导入
      
  47.             AsymmetricKeyParameter pubKey = PublicKeyFactory.CreateKey(SubjectPublicKeyInfo.GetInstance(pubKeyObj));  
  48.             IAsymmetricBlockCipher cipher = new RsaEngine();  
  49.             cipher.Init(true, pubKey);//true表示加密
      
  50.             //加密   
  51.             string data = "成功了。。。";  
  52.             Console.WriteLine("\n明文:" + data);  
  53.             byte[] encryptData = cipher.ProcessBlock(Encoding.UTF8.GetBytes(data), 0, Encoding.UTF8.GetBytes(data).Length);  
  54.             Console.WriteLine("密文:" + Convert.ToBase64String(encryptData));  
  55.             //解密   
  56.             AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(privateInfoByte);  
  57.             cipher.Init(false, priKey);//false表示解密
      
  58.             string decryptData = Encoding.UTF8.GetString(cipher.ProcessBlock(encryptData, 0, encryptData.Length));  
  59.             Console.WriteLine("解密后数据:" + decryptData);  
  60.             Console.Read();  
  61.         }  
  62.     }  
  63. }  

运行结果:

  1. PublicKey:  
  2. MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCzoQTA/zgahiaytyggCLoodqhuG8gRUXypUt+9HAtPsNhRHC2ksQazS8DnyyrfgrmPfv///AHURL2itn7L1gfrVcm7QDLwM/gXCjUV5lkRrlp7SDF6yxrF00PLWOvAae1eEmmg9ucymEjwq2pzEVMJyWslJdXjvYOSDstUMbqCtQIBAw==  
  3. PrivateKey:  
  4. MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALOhBMD/OBqGJrK3KCAIuih2qG4byBFRfKlS370cC0+w2FEcLaSxBrNLwOfLKt+CuY9+///8AdREvaK2fsvWB+tVybtAMvAz+BcKNRXmWRGuWntIMXrLGsXTQ8tY68Bp7V4SaaD25zKYSPCranMRUwnJayUl1eO9g5IOy1QxuoK1AgEDAoGAd8Ct1f96vFlvIc9wFVsmxaRwSWfatjZTG4yVKL1c38s64L1zwyCvIjKAmodx6lcmX6n///1WjYMpFyRUh+QFRm9H60Ger3PfUII4epgVHqX20aRWy32cmW3Gp+r04p7ENja/Jey6HsdXb7Q32fdZKsLZOO2lvNdUu/5+LsP6wTMCQQDsFcBU1JFA3l6vZyi3b+nzZgoaCo6kMTTG4i/S/kf8cVPw5jaEVGUMhsXPkicWXNpppXNU4yA4gbNRN2XXnsjnAkEAwsgaCPBXxUq/l3k1Ssl5wgI2t6S66n6q57efpX4kf1W4z2Sxj3ufYL8DTYSFB/BvO3/cbHooQgLEv9aoNCOYAwJBAJ1j1Y3jC4CUPx+aGyT1RqJEBrwHCcLLeISWyoyphVL2N/XuzwLi7ghZ2TUMGg7okZvDojiXatBWd4t6Q+UUhe8CQQCB2rwF9Y/Y3H+6UM4x26aBVs8lGHycVHHvz7/DqW2qOSXfmHZfp7+V1KzeWFiv9Z98/+hIUXAsAdh/5HAiwmVXAkEAmo9GTWqbRP6BU75MPPnL42zq/4cQBI4yya03NDZjU1lwA2YvmFzJaM4mVmrsxNeDv6qY7Ibl/GDwIbAUaEHaAA==  
  5. 明文:成功了。。。  
  6. 密文:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC68tDDx2RzUu/BP/x93GcohXJeZeN4TZXUHEji3jjnyQV1yqDLdm5cOqjkqBQZHDZCq5fLhgg=  
  7. 解密后数据:成功了。。。  

2、公钥提供给Java客户端进行加密(这里也给出了解密过程)

若是依据C#端提供的密钥对在Java端进行加解密,加解密匹配方式还是有好几种的。就下面代码中的Cipher.getInstance参数,列举几种可行方案。

Java RSA 加解密参数transformation匹配方案
encrypt
Cipher.getInstance(transformation)
decrypt
Cipher.getInstance(transformation)
encrypt
Cipher.getInstance(transformation)
decrypt
Cipher.getInstance(transformation, 
new org.bouncycastle.jce.
provider.BouncyCastleProvider())
RSA RSA RSA RSA
RSA RSA/ECB/PKCS1Padding RSA RSA/ECB/PKCS1Padding
RSA/ECB/PKCS1Padding RSA RSA/ECB/PKCS1Padding RSA
RSA/ECB/PKCS1Padding RSA/ECB/PKCS1Padding RSA/ECB/PKCS1Padding RSA/ECB/PKCS1Padding
    RSA/ECB/NoPadding RSA
    RSA/ECB/NoPadding RSA/ECB/NoPadding

注意:代码中注释的地方很重要

  1. import java.io.ByteArrayOutputStream;  
  2. import java.lang.reflect.Method;  
  3. import java.nio.charset.Charset;  
  4. import java.security.InvalidKeyException;  
  5. import java.security.KeyFactory;  
  6. import java.security.NoSuchAlgorithmException;  
  7. import java.security.PrivateKey;  
  8. import java.security.PublicKey;  
  9. import java.security.interfaces.RSAPrivateKey;  
  10. import java.security.interfaces.RSAPublicKey;  
  11. import java.security.spec.InvalidKeySpecException;  
  12. import java.security.spec.PKCS8EncodedKeySpec;  
  13. import java.security.spec.X509EncodedKeySpec;  
  14. import javax.crypto.BadPaddingException;  
  15. import javax.crypto.Cipher;  
  16. import javax.crypto.IllegalBlockSizeException;  
  17. import javax.crypto.NoSuchPaddingException;  
  18.   
  19. /** 
  20.  * @author 邓少林 
  21.  *  
  22.  */  
  23. public class RSAUtil {  
  24.     private static int MAXENCRYPTSIZE = 117;  
  25.     private static int MAXDECRYPTSIZE = 128;  
  26.   
  27.     /** 
  28.      * @param publicKeyByte 
  29.      * @return RSAPublicKey 
  30.      * @throws NoSuchAlgorithmException 
  31.      * @throws InvalidKeySpecException 
  32.      */  
  33.     public static RSAPublicKey getPublicKey(byte[] publicKeyByte) throws NoSuchAlgorithmException, InvalidKeySpecException{  
  34.         X509EncodedKeySpec x509 = new X509EncodedKeySpec(publicKeyByte);          
  35.         KeyFactory keyFactory = KeyFactory.getInstance("RSA");  
  36.         RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(x509);  
  37.         return publicKey;         
  38.     }  
  39.   
  40.     public static RSAPrivateKey getPrivateKey(byte[] privateKeyByte) throws InvalidKeySpecException, NoSuchAlgorithmException {  
  41.         PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyByte);  
  42.         KeyFactory keyFactory = KeyFactory.getInstance("RSA");  
  43.         return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);  
  44.     }  
  45.   
  46.   
  47.     /** 
  48.      * encrypt 
  49.      * @param source 
  50.      * @param publicKey 
  51.      * @return Bute[] encryptData 
  52.      * @throws Exception 
  53.      */  
  54.     public static byte[] encrypt(PublicKey publicKey, byte[] source)  
  55.             throws Exception {  
  56.         try {  
  57.             //此处填充方式选择部填充 NoPadding,当然模式和填充方式选择其他的,在Java端可以正确加密解密,
      
  58.             //但是解密后的密文提交给C#端,解密的得到的数据将产生乱码
      
  59.             Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");  
  60.             cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
  61.             int length = source.length;  
  62.             int offset = 0;  
  63.             byte[] cache;  
  64.             ByteArrayOutputStream outStream = new ByteArrayOutputStream();  
  65.             int i = 0;  
  66.             while (length - offset > 0) {  
  67.                 if (length - offset > MAXENCRYPTSIZE) {  
  68.                     cache = cipher.doFinal(source, offset, MAXENCRYPTSIZE);  
  69.                 } else {  
  70.                     cache = cipher.doFinal(source, offset, length - offset);  
  71.                 }  
  72.                 outStream.write(cache, 0, cache.length);  
  73.                 i++;  
  74.                 offset = i * MAXENCRYPTSIZE;  
  75.             }  
  76.             return outStream.toByteArray();  
  77.         } catch (NoSuchAlgorithmException e) {  
  78.             e.printStackTrace();  
  79.         } catch (NoSuchPaddingException e) {  
  80.             e.printStackTrace();  
  81.         } catch (InvalidKeyException e) {  
  82.             e.printStackTrace();  
  83.         } catch (IllegalBlockSizeException e) {  
  84.             e.printStackTrace();  
  85.         } catch (BadPaddingException e) {  
  86.             e.printStackTrace();  
  87.         }  
  88.         return null;  
  89.     }  
  90.   
  91.     /**RSA decrypt 
  92.      * @param privateKey 
  93.      * @param encryptData 
  94.      * @return decryptData 
  95.      * @throws IllegalBlockSizeException 
  96.      * @throws BadPaddingException 
  97.      * @throws InvalidKeyException 
  98.      * @throws NoSuchAlgorithmException 
  99.      * @throws NoSuchPaddingException 
  100.      */  
  101.     public static byte[] decrypt(PrivateKey privateKey, byte[] encryptData)  
  102.             throws IllegalBlockSizeException, BadPaddingException,  
  103.             InvalidKeyException, NoSuchAlgorithmException,  
  104.             NoSuchPaddingException {  
  105.         //此处模式选择与加密对应,但是需要添加第二个参数new org.bouncycastle.jce.provider.BouncyCastleProvider()
      
  106.         //若不添加第二个参数的话,解密后的数据前面出现大段空格符
      
  107.         Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding"new org.bouncycastle.jce.provider.BouncyCastleProvider());  
  108.         cipher.init(Cipher.DECRYPT_MODE, privateKey);  
  109.   
  110.         int length = encryptData.length;  
  111.         int offset = 0;  
  112.         int i = 0;  
  113.         byte[] cache;  
  114.         ByteArrayOutputStream outStream = new ByteArrayOutputStream();  
  115.         while (length - offset > 0) {  
  116.             if (length - offset > MAXDECRYPTSIZE) {  
  117.                 cache = cipher.doFinal(encryptData, offset, MAXDECRYPTSIZE);  
  118.             } else {  
  119.                 cache = cipher.doFinal(encryptData, offset, length - offset);  
  120.             }  
  121.             outStream.write(cache, 0, cache.length);  
  122.             i++;  
  123.             offset = i * MAXDECRYPTSIZE;  
  124.         }  
  125.         return outStream.toByteArray();  
  126.     }  
  127.   
  128.     /** 
  129.      * base64编码 
  130.      *  
  131.      * @param input 
  132.      * @return output with base64 encoded 
  133.      * @throws Exception 
  134.      */  
  135.     public static String encodeBase64(byte[] input) throws Exception {  
  136.         Class clazz = Class  
  137.                 .forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");  
  138.         Method mainMethod = clazz.getMethod("encode"byte[].class);  
  139.         mainMethod.setAccessible(true);  
  140.         Object retObj = mainMethod.invoke(nullnew Object[] { input });  
  141.         return (String) retObj;  
  142.     }  
  143.   
  144.     /** 
  145.      * base64解码 
  146.      *  
  147.      * @param input 
  148.      * @return 
  149.      * @throws Exception 
  150.      */  
  151.     public static byte[] decodeBase64(String input) throws Exception {  
  152.         Class clazz = Class  
  153.                 .forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");  
  154.         Method mainMethod = clazz.getMethod("decode", String.class);  
  155.         mainMethod.setAccessible(true);  
  156.         Object retObj = mainMethod.invoke(null, input);  
  157.         return (byte[]) retObj;  
  158.     }  
  159.       
  160.     public static void main(String[] args) throws Exception {  
  161.         RSAPublicKey rsaPublicKey = getPublicKey(decodeBase64("MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCzoQTA/zgahiaytyggCLoodqhuG8gRUXypUt+9HAtPsNhRHC2ksQazS8DnyyrfgrmPfv///AHURL2itn7L1gfrVcm7QDLwM/gXCjUV5lkRrlp7SDF6yxrF00PLWOvAae1eEmmg9ucymEjwq2pzEVMJyWslJdXjvYOSDstUMbqCtQIBAw=="));  
  162.         byte[] encryptData = encrypt(rsaPublicKey, "成功了...".getBytes(Charset.forName("utf-8")));  
  163.         System.out.println("密文:\n" + encodeBase64(encryptData));  
  164.         RSAPrivateKey privateKey = getPrivateKey(decodeBase64("MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALOhBMD/OBqGJrK3KCAIuih2qG4byBFRfKlS370cC0+w2FEcLaSxBrNLwOfLKt+CuY9+///8AdREvaK2fsvWB+tVybtAMvAz+BcKNRXmWRGuWntIMXrLGsXTQ8tY68Bp7V4SaaD25zKYSPCranMRUwnJayUl1eO9g5IOy1QxuoK1AgEDAoGAd8Ct1f96vFlvIc9wFVsmxaRwSWfatjZTG4yVKL1c38s64L1zwyCvIjKAmodx6lcmX6n///1WjYMpFyRUh+QFRm9H60Ger3PfUII4epgVHqX20aRWy32cmW3Gp+r04p7ENja/Jey6HsdXb7Q32fdZKsLZOO2lvNdUu/5+LsP6wTMCQQDsFcBU1JFA3l6vZyi3b+nzZgoaCo6kMTTG4i/S/kf8cVPw5jaEVGUMhsXPkicWXNpppXNU4yA4gbNRN2XXnsjnAkEAwsgaCPBXxUq/l3k1Ssl5wgI2t6S66n6q57efpX4kf1W4z2Sxj3ufYL8DTYSFB/BvO3/cbHooQgLEv9aoNCOYAwJBAJ1j1Y3jC4CUPx+aGyT1RqJEBrwHCcLLeISWyoyphVL2N/XuzwLi7ghZ2TUMGg7okZvDojiXatBWd4t6Q+UUhe8CQQCB2rwF9Y/Y3H+6UM4x26aBVs8lGHycVHHvz7/DqW2qOSXfmHZfp7+V1KzeWFiv9Z98/+hIUXAsAdh/5HAiwmVXAkEAmo9GTWqbRP6BU75MPPnL42zq/4cQBI4yya03NDZjU1lwA2YvmFzJaM4mVmrsxNeDv6qY7Ibl/GDwIbAUaEHaAA=="));  
  165.         System.out.println("解密后数据:" + new String(decrypt(privateKey, encryptData),"utf-8"));  
  166.     }  
  167. }  

运行结果:

  1. 密文:  
  2. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC68tDDx2RzUu/BP/x93GcohXJeZeN4TZXUHEji3jjnyQV1yqDLdm5cOqjkqBQZHDZCq5fLhgg=  
  3. 解密后数据:成功了。。。  

3、将加密后的密文提交给服务器端进行解密

  1. static void Main(string[] args)  
  2. {  
  3.     IAsymmetricBlockCipher cipher = new RsaEngine();  
  4.     byte[] encryptData = Convert.FromBase64String("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC68tDDx2RzUu/BP/x93GcohXJeZeN4TZXUHEji3jjnyQV1yqDLdm5cOqjkqBQZHDZCq5fLhgg=");  
  5.     AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(PrivateKeyInfo.GetInstance(Asn1Object.FromByteArray(Convert.FromBase64String("MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALOhBMD/OBqGJrK3KCAIuih2qG4byBFRfKlS370cC0+w2FEcLaSxBrNLwOfLKt+CuY9+///8AdREvaK2fsvWB+tVybtAMvAz+BcKNRXmWRGuWntIMXrLGsXTQ8tY68Bp7V4SaaD25zKYSPCranMRUwnJayUl1eO9g5IOy1QxuoK1AgEDAoGAd8Ct1f96vFlvIc9wFVsmxaRwSWfatjZTG4yVKL1c38s64L1zwyCvIjKAmodx6lcmX6n///1WjYMpFyRUh+QFRm9H60Ger3PfUII4epgVHqX20aRWy32cmW3Gp+r04p7ENja/Jey6HsdXb7Q32fdZKsLZOO2lvNdUu/5+LsP6wTMCQQDsFcBU1JFA3l6vZyi3b+nzZgoaCo6kMTTG4i/S/kf8cVPw5jaEVGUMhsXPkicWXNpppXNU4yA4gbNRN2XXnsjnAkEAwsgaCPBXxUq/l3k1Ssl5wgI2t6S66n6q57efpX4kf1W4z2Sxj3ufYL8DTYSFB/BvO3/cbHooQgLEv9aoNCOYAwJBAJ1j1Y3jC4CUPx+aGyT1RqJEBrwHCcLLeISWyoyphVL2N/XuzwLi7ghZ2TUMGg7okZvDojiXatBWd4t6Q+UUhe8CQQCB2rwF9Y/Y3H+6UM4x26aBVs8lGHycVHHvz7/DqW2qOSXfmHZfp7+V1KzeWFiv9Z98/+hIUXAsAdh/5HAiwmVXAkEAmo9GTWqbRP6BU75MPPnL42zq/4cQBI4yya03NDZjU1lwA2YvmFzJaM4mVmrsxNeDv6qY7Ibl/GDwIbAUaEHaAA=="))));  
  6.     cipher.Init(false, priKey);  
  7.     Console.WriteLine(Encoding.UTF8.GetString(cipher.ProcessBlock(encryptData, 0, encryptData.Length)));  
  8.     Console.WriteLine(Encoding.UTF8.GetString(cipher.ProcessBlock(encryptData, 0, encryptData.Length)).Equals("成功了。。。"));  
  9.     Console.Read();  
  10. }  

运行结果:

  1. 成功了。。。  
  2. True  

大家也试一试吧。

下面再简要的介绍一种交互方法。当然了,并非实现上面的要求,而与C# Java间进行RSA加密解密交互这篇中的略相似,相同的是都需要在客户端(Java)先进行解析。对于这种做法可以先参阅源码CryptoConvert.cs(namespace Mono.Security.Cryptography)源码地址:http://www.oschina.net/code/explore/mono-2.8.1/mcs/class/corlib/Mono.Security.Cryptography/CryptoConvert.cs
(此处所有处理都是针对密钥初始化长度为1024,其他情况类似分析)
1、C#端

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.IO;  
  6. using System.Security.Cryptography;  
  7.   
  8. namespace ConsoleApplication1  
  9. {  
  10.     class Program  
  11.     {  
  12.         static void Main(string[] args)  
  13.         {  
  14.             //------------------------------------------------------------------------------------------
      
  15.             RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();  
  16.             /*RSAParameters paras = rsa.ExportParameters(true); 
  17.             Console.WriteLine("-----------------------------------------------------------------------"); 
  18.             Console.WriteLine("Exponent:" + Convert.ToBase64String(paras.Exponent)); 
  19.             Console.WriteLine("Modulus:" + Convert.ToBase64String(paras.Modulus)); 
  20.             Console.WriteLine("P:" + Convert.ToBase64String(paras.P)); 
  21.             Console.WriteLine("Q:" + Convert.ToBase64String(paras.Q)); 
  22.             Console.WriteLine("DP:" + Convert.ToBase64String(paras.DP)); 
  23.             Console.WriteLine("DQ:" + Convert.ToBase64String(paras.DQ)); 
  24.             Console.WriteLine("InversQ:" + Convert.ToBase64String(paras.InverseQ)); 
  25.             Console.WriteLine("D:" + Convert.ToBase64String(paras.D)); 
  26.             Console.WriteLine("-----------------------------------------------------------------------"); 
  27.             Console.WriteLine("Exponent:" + paras.Exponent.Length + "\tModulus:" + paras.Modulus.Length + "\tP:" + paras.P.Length + "\tQ:" + paras.Q.Length + "\tDP:" + paras.DP.Length + "\tDQ:" + paras.DQ.Length + "\tInversQ:" + paras.InverseQ.Length + "\tD:" + paras.D.Length); 
  28.             Console.WriteLine("-----------------------------------------------------------------------"); 
  29.             Console.WriteLine("the length of ExportCspBlobPublic:" + rsa.ExportCspBlob(false).Length);*/  
  30.             Console.WriteLine("ExportCspBlobPublic:\n" + Convert.ToBase64String(rsa.ExportCspBlob(false)));//导出公钥数据
      
  31.             Console.WriteLine("-----------------------------------------------------------------------");  
  32.             //Console.WriteLine("the length of ExportCspBlobPrivate:" + rsa.ExportCspBlob(true).Length);
      
  33.             Console.WriteLine("ExportCspBlobPrivate:\n" + Convert.ToBase64String(rsa.ExportCspBlob(true)));//导出私钥数据
      
  34.             Console.WriteLine("-----------------------------------------------------------------------");  
  35.             Console.WriteLine("publicKeyResolve...");  
  36.             byte[] exportPublic = rsa.ExportCspBlob(false);  
  37.             Console.WriteLine(Convert.ToBase64String(PublicKeyResolve(exportPublic)));  
  38.             Console.WriteLine("-----------------------------------------------------------------------");  
  39.             Console.WriteLine("privateKeyResolve...");  
  40.             Dictionary<stringbyte[]> privateKeyParamaters = PrivateKeyResolve(rsa.ExportCspBlob(true));  
  41.             foreach (string key in privateKeyParamaters.Keys)  
  42.             {  
  43.                 Console.WriteLine(key + ":\n" + Convert.ToBase64String(privateKeyParamaters[key]));  
  44.             }  
  45.             Console.Read();  
  46.         }  
  47.   
  48.         /// <summary>   
  49.         /// 对ExportCspBlob(false)方法到处的私钥进行解析,提取私钥参数
      
  50.         /// </summary>   
  51.         /// <param name="cspblobPublicKey">RSA.ExportCspBlob(false)得到的包含私钥信息</param>
      
  52.         /// <returns>公钥模数</returns>
      
  53.         public static byte[] PublicKeyResolve(byte[] cspblobPublicKey)  
  54.         {  
  55.             byte[] modulus = new byte[128];  
  56.             Array.Reverse(cspblobPublicKey, 0, cspblobPublicKey.Length);  
  57.             Buffer.BlockCopy(cspblobPublicKey, 0, modulus, 0, 128);  
  58.             return modulus;  
  59.         }  
  60.   
  61.         /// <summary>   
  62.         /// 对ExportCspBlob(true)方法到处的私钥进行解析,提取私钥参数
      
  63.         /// </summary>
      
  64.         /// <param name="cspblobPrivateKey">RSA.ExportCspBlob(true)得到的包含私钥信息</param>
      
  65.         /// <returns>私钥参数</returns>
      
  66.         public static Dictionary<stringbyte[]> PrivateKeyResolve(byte[] cspblobPrivateKey)  
  67.         {  
  68.             Dictionary<stringbyte[]> privateKeyParameters = new Dictionary<stringbyte[]>();  
  69.   
  70.             Array.Reverse(cspblobPrivateKey, 0, cspblobPrivateKey.Length);  
  71.             int offset = 0;  
  72.             byte[] part = new byte[128];  
  73.             Buffer.BlockCopy(cspblobPrivateKey, offset, part, offset, part.Length);  
  74.             privateKeyParameters.Add("D", part);  
  75.   
  76.             offset += part.Length;  
  77.             part = new byte[64];  
  78.             Buffer.BlockCopy(cspblobPrivateKey, offset, part, 0, part.Length);  
  79.             privateKeyParameters.Add("INVERSEQ", part);  
  80.   
  81.             offset += part.Length;  
  82.             part = new byte[64];  
  83.             Buffer.BlockCopy(cspblobPrivateKey, offset, part, 0, part.Length);  
  84.             privateKeyParameters.Add("DQ", part);  
  85.   
  86.             offset += part.Length;  
  87.             part = new byte[64];  
  88.             Buffer.BlockCopy(cspblobPrivateKey, offset, part, 0, part.Length);  
  89.             privateKeyParameters.Add("DP", part);  
  90.   
  91.             offset += part.Length;  
  92.             part = new byte[64];  
  93.             Buffer.BlockCopy(cspblobPrivateKey, offset, part, 0, part.Length);  
  94.             privateKeyParameters.Add("Q", part);  
  95.   
  96.             offset += part.Length;  
  97.             part = new byte[64];  
  98.             Buffer.BlockCopy(cspblobPrivateKey, offset, part, 0, part.Length);  
  99.             privateKeyParameters.Add("P", part);  
  100.   
  101.             offset += part.Length;  
  102.             part = new byte[128];  
  103.             Buffer.BlockCopy(cspblobPrivateKey, offset, part, 0, part.Length);  
  104.             privateKeyParameters.Add("MODULUS", part);  
  105.             return privateKeyParameters;  
  106.         }  
  107.     }  
  108. }  

运行结果:

  1. ExportCspBlobPublic:  
  2. BgIAAACkAABSU0ExAAQAAAEAAQCdsw5SKF57lm1ez9Pu1CkEwRlW+fyEAFuz/N+mYe0iNyjA2ePhZoW4ZdwnaEBx9Gonskuch6pasypJhPr5bbvNVHQjtEEJSdFG1exKQ7AxpMmmft8PyhUcYqa15XUpebQaM0Zi+V1yiOqki54kCZSeGrMwa26+vJ4JCx3y+Fngmw==  
  3. -----------------------------------------------------------------------  
  4. ExportCspBlobPrivate:  
  5. BwIAAACkAABSU0EyAAQAAAEAAQCdsw5SKF57lm1ez9Pu1CkEwRlW+fyEAFuz/N+mYe0iNyjA2ePhZoW4ZdwnaEBx9Gonskuch6pasypJhPr5bbvNVHQjtEEJSdFG1exKQ7AxpMmmft8PyhUcYqa15XUpebQaM0Zi+V1yiOqki54kCZSeGrMwa26+vJ4JCx3y+Fngm9cPox4JtkoE0KVNsA98WFkAs3bseEqlcZhGbyLwBOBq7jeXJCFv5IZ8ZxDWrpWRz2HminmQEXjj54y9/FjJYs+r+b0J5W4GmZWBFkaO+0TkKoQAqK46x/c739e74GMf5p1ZyBNjiDPDts/CPf9OruGaTRM5t2HUA6pASU6De2rAR8nGRCxODmbeKb8w4Y/Q7b7eY4Omwr9sSAwDMlylXnrk4kyuuouHuP+Mb+LWppsv5WO+KfnT16CY5ZmpbfTlTV/oNppVgMSBKgdiI+FQFHJiCZh+4awb3tkOOIsdmWKEdg03NCbev3WbH6dU3ZDZFJ27zbTNhD4BlkyGmEkIQxfx895qWFJnqTOeEUQd1M5UGSDIEfIw51ByLKS/nPq1M3aUN4nRIm8EzDOa8529ZU0wLJvoipER8qpeb6AyKKGF6dcEq2HooM54+qF2oJXVc3CPwFTjmytbeKOq1waInDZfu0eWF5m5ET7WrXRjGA1txlPOhC4tBI6yJEgzdY5eVFJcqsYl8asHyaWIM07GZbS8opP1ePIv9YybeUEUg+Y4gsWBjTnmYgF4nEhLGmXtmGFQWbAnzQVsWqvmXb3RN5Y=  
  6. -----------------------------------------------------------------------  
  7. publicKeyResolve...  
  8. m+BZ+PIdCwmevL5uazCzGp6UCSSei6TqiHJd+WJGMxq0eSl15bWmYhwVyg/ffqbJpDGwQ0rs1UbRSQlBtCN0VM27bfn6hEkqs1qqh5xLsidq9HFAaCfcZbiFZuHj2cAoNyLtYabf/LNbAIT8+VYZwQQp1O7Tz15tlnteKFIOs50=  
  9. -----------------------------------------------------------------------  
  10. privateKeyResolve...  
  11. D:  
  12. ljfRvV3mq1psBc0nsFlQYZjtZRpLSJx4AWLmOY2BxYI45oMUQXmbjPUv8nj1k6K8tGXGTjOIpckHq/ElxqpcUlRejnUzSCSyjgQtLoTOU8ZtDRhjdK3WPhG5mReWR7tfNpyIBteqo3hbK5vjVMCPcHPVlaB2ofp4zqDoYasE1+k=  
  13. INVERSEQ:  
  14. haEoMqBvXqryEZGK6JssME1lvZ3zmjPMBG8i0Yk3lHYztfqcv6QsclDnMPIRyCAZVM7UHUQRnjOpZ1JYat7z8Q==  
  15. DQ:  
  16. F0MISZiGTJYBPoTNtM27nRTZkN1Upx+bdb/eJjQ3DXaEYpkdizgO2d4brOF+mAlichRQ4SNiByqBxIBVmjboXw==  
  17. DP:  
  18. TeX0bamZ5Zig19P5Kb5j5S+bptbib4z/uIeLuq5M4uR6XqVcMgMMSGy/wqaDY96+7dCP4TC/Kd5mDk4sRMbJRw==  
  19. Q:  
  20. wGp7g05JQKoD1GG3ORNNmuGuTv89ws+2wzOIYxPIWZ3mH2Pgu9ffO/fHOq6oAIQq5ET7jkYWgZWZBm7lCb35qw==  
  21. P:  
  22. z2LJWPy9jOfjeBGQeYrmYc+Rla7WEGd8huRvISSXN+5q4ATwIm9GmHGlSnjsdrMAWVh8D7BNpdAESrYJHqMP1w==  
  23. MODULUS:  
  24. m+BZ+PIdCwmevL5uazCzGp6UCSSei6TqiHJd+WJGMxq0eSl15bWmYhwVyg/ffqbJpDGwQ0rs1UbRSQlBtCN0VM27bfn6hEkqs1qqh5xLsidq9HFAaCfcZbiFZuHj2cAoNyLtYabf/LNbAIT8+VYZwQQp1O7Tz15tlnteKFIOs50=  

2、Java端的解析(与C#端的类似,解析后,用参数构造密钥)

  1. import java.util.Hashtable;  
  2.   
  3.   
  4. public class ExportCspBlobResolve {  
  5.     /** 
  6.      * 解析公钥 
  7.      * @param cspblobPublicKey由C# new RSACryptoServiceProvider().ExportCspBlob(false)提供 
  8.      * @return RSA公钥的Modulus参数 
  9.      */  
  10.     public static byte[] publicKeyResolve(byte[] cspblobPublicKey){  
  11.         int length = cspblobPublicKey.length;  
  12.         byte[] reversePublicKey = new byte[length];  
  13.         for (int i = 0; i < length; i++) {  
  14.             reversePublicKey[i] = cspblobPublicKey[length - 1 - i];  
  15.         }         
  16.         byte[] part = new byte[128];  
  17.         for (int i = 0; i < part.length; i++)  
  18.             part[i] = reversePublicKey[i];  
  19.         return part;          
  20.     }  
  21.       
  22.     /** 
  23.      * 解析私钥 
  24.      * @param cspblobPrivateKey由C# new RSACryptoServiceProvider().ExportCspBlob(true)提供 
  25.      * @return 返回包含私钥参数的Hashtable 
  26.      */  
  27.     public static Hashtable<String, byte[]> privateKeyResolve(byte[] cspblobPrivateKey) {  
  28.         Hashtable<String, byte[]> privateKeyParameters = new Hashtable<String, byte[]>();  
  29.         int length = cspblobPrivateKey.length;  
  30.         byte[] reversePrivateKey = new byte[length];  
  31.         for (int i = 0; i < length; i++) {  
  32.             reversePrivateKey[i] = cspblobPrivateKey[length - 1 - i];  
  33.         }  
  34.         int offset = 0;  
  35.         byte[] part = new byte[128];  
  36.         for (int i = 0; i < part.length; i++)  
  37.             part[i] = reversePrivateKey[offset + i];  
  38.         privateKeyParameters.put("D", part);  
  39.           
  40.         offset += part.length;  
  41.         part = new byte[64];  
  42.         for (int i = 0; i < part.length; i++)  
  43.             part[i] = reversePrivateKey[offset + i];  
  44.         privateKeyParameters.put("INVERSEQ", part);  
  45.           
  46.         offset += part.length;  
  47.         part = new byte[64];  
  48.         for (int i = 0; i < part.length; i++)  
  49.             part[i] = reversePrivateKey[offset + i];  
  50.         privateKeyParameters.put("DQ", part);  
  51.           
  52.         offset += part.length;  
  53.         part = new byte[64];  
  54.         for (int i = 0; i < part.length; i++)  
  55.             part[i] = reversePrivateKey[offset + i];  
  56.         privateKeyParameters.put("DP", part);  
  57.           
  58.         offset += part.length;  
  59.         part = new byte[64];  
  60.         for (int i = 0; i < part.length; i++)  
  61.             part[i] = reversePrivateKey[offset + i];  
  62.         privateKeyParameters.put("Q", part);  
  63.           
  64.         offset += part.length;  
  65.         part = new byte[64];  
  66.         for (int i = 0; i < part.length; i++)  
  67.             part[i] = reversePrivateKey[offset + i];  
  68.         privateKeyParameters.put("P", part);  
  69.           
  70.         offset += part.length;  
  71.         part = new byte[128];  
  72.         for (int i = 0; i < part.length; i++)  
  73.             part[i] = reversePrivateKey[offset + i];  
  74.         privateKeyParameters.put("MODULUS", part);  
  75.         return privateKeyParameters;  
  76.     }     
  77. }  

输入参数即为C#导出的ExportCspBlobPublic 和 ExportCspBlobPrivate,至于验证过程,这里就不再重复了。有兴趣的可以自己验证

顺便给个RSA参数在Java和C#间的对应关系

RSA参数在Java和C#间的对应关系
RSA for Java RSA for C# RSA forJava RSA for C#
PublicExPonent Exponent PrimeQ Q
Modules Modulus PrimeExponentP DP
PrivateExponent D PrimeExponentQ DQ
PrimeP P CrtCoefficient InverseQ

--------------------------------------------------------------------------------------------------------------------

C# Java间进行RSA加密解密交互

C# Java间进行RSA加密解密交互(二)

抱歉!评论已关闭.