zoukankan      html  css  js  c++  java
  • C# Java间进行RSA加密解密交互(三)

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

    [java] view plain copy
     
    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#生成及加解密过程

    [csharp] view plain copy
     
    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: " + Convert.ToBase64String(publicInfoByte));  
    43.             Console.WriteLine("PrivateKey: " + 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(" 明文:" + 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. }  

    运行结果:

    [html] view plain copy
     
    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

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

    [java] view plain copy
     
    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(null, new 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("密文: " + 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. }  

    运行结果:

    [html] view plain copy
     
    1. 密文:  
    2. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC68tDDx2RzUu/BP/x93GcohXJeZeN4TZXUHEji3jjnyQV1yqDLdm5cOqjkqBQZHDZCq5fLhgg=  
    3. 解密后数据:成功了。。。  

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

    [csharp] view plain copy
     
    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. }  

    运行结果:

    [plain] view plain copy
     
    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#端

    [csharp] view plain copy
     
    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 + " Modulus:" + paras.Modulus.Length + " P:" + paras.P.Length + " Q:" + paras.Q.Length + " DP:" + paras.DP.Length + " DQ:" + paras.DQ.Length + " InversQ:" + paras.InverseQ.Length + " D:" + paras.D.Length); 
    28.             Console.WriteLine("-----------------------------------------------------------------------"); 
    29.             Console.WriteLine("the length of ExportCspBlobPublic:" + rsa.ExportCspBlob(false).Length);*/  
    30.             Console.WriteLine("ExportCspBlobPublic: " + Convert.ToBase64String(rsa.ExportCspBlob(false)));//导出公钥数据  
    31.             Console.WriteLine("-----------------------------------------------------------------------");  
    32.             //Console.WriteLine("the length of ExportCspBlobPrivate:" + rsa.ExportCspBlob(true).Length);  
    33.             Console.WriteLine("ExportCspBlobPrivate: " + 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<string, byte[]> privateKeyParamaters = PrivateKeyResolve(rsa.ExportCspBlob(true));  
    41.             foreach (string key in privateKeyParamaters.Keys)  
    42.             {  
    43.                 Console.WriteLine(key + ": " + 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<string, byte[]> PrivateKeyResolve(byte[] cspblobPrivateKey)  
    67.         {  
    68.             Dictionary<string, byte[]> privateKeyParameters = new Dictionary<string, byte[]>();  
    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. }  

    运行结果:

    [html] view plain copy
     
    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#端的类似,解析后,用参数构造密钥)

    [java] view plain copy
     
    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 JavaRSA for C#RSA forJavaRSA for C#
    PublicExPonent Exponent PrimeQ Q
    Modules Modulus PrimeExponentP DP
    PrivateExponent D PrimeExponentQ DQ
    PrimeP P CrtCoefficient InverseQ

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

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

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

  • 相关阅读:
    Mysql:存储过程
    mysql-8.0.21的安装
    java8:四大函数式接口(Consumer、Supplier、Function、Predicate)
    java8:Lambda表达式、函数式接口
    Nginx:负载均衡
    JeecgBoot:开发环境准备(安装Node.js、yarn、WebStorm、Nodejs镜像)
    Nginx:反向代理(案例)
    Mysql:性能分析
    Nginx:初识Nginx(概念、在Docker中安装Nginx、常用命令、配置文件)
    Docker 实战之Registry以及持续集成
  • 原文地址:https://www.cnblogs.com/amylis_chen/p/8604977.html
Copyright © 2011-2022 走看看