您的位置:首页 > 编程语言 > Java开发

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

2015-05-13 14:57 771 查看
接着前面一篇C# Java间进行RSA加密解密交互(二)说吧,在上篇中为了实现

[java] view
plaincopy

/**

* RSA加密

* @param text--待加密的明文

* @param key--公钥,由服务器端提供的经base64编码的字符串

* @return

*/

public static String RSAEncryptoWithPublicKey(String text, String key) {

String result = null;

......

return result;

}

加密过程,采用了折中办法,由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
plaincopy

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Org.BouncyCastle.Crypto.Generators;

using Org.BouncyCastle.Crypto.Parameters;

using Org.BouncyCastle.Crypto;

using Org.BouncyCastle.Security;

using Org.BouncyCastle.Crypto.Engines;

using Org.BouncyCastle.Math;

using Org.BouncyCastle.Asn1.X509;

using Org.BouncyCastle.X509;

using Org.BouncyCastle.Utilities.Collections;

using Org.BouncyCastle.Asn1.Pkcs;

using Org.BouncyCastle.Pkcs;

using Org.BouncyCastle.Asn1;

namespace ConsoleApplication2

{

class Program

{

static void Main(string[] args)

{

//生成密钥对

RsaKeyPairGenerator rsaKeyPairGenerator = new RsaKeyPairGenerator();

RsaKeyGenerationParameters rsaKeyGenerationParameters = new RsaKeyGenerationParameters(BigInteger.ValueOf(3), new Org.BouncyCastle.Security.SecureRandom(), 1024, 25);

rsaKeyPairGenerator.Init(rsaKeyGenerationParameters);//初始化参数

AsymmetricCipherKeyPair keyPair = rsaKeyPairGenerator.GenerateKeyPair();

AsymmetricKeyParameter publicKey = keyPair.Public;//公钥

AsymmetricKeyParameter privateKey = keyPair.Private;//私钥

SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);

PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey);

Asn1Object asn1ObjectPublic = subjectPublicKeyInfo.ToAsn1Object();

byte[] publicInfoByte = asn1ObjectPublic.GetEncoded();

Asn1Object asn1ObjectPrivate = privateKeyInfo.ToAsn1Object();

byte[] privateInfoByte = asn1ObjectPrivate.GetEncoded();

//这里可以将密钥对保存到本地

Console.WriteLine("PublicKey:\n" + Convert.ToBase64String(publicInfoByte));

Console.WriteLine("PrivateKey:\n" + Convert.ToBase64String(privateInfoByte));

//加密、解密

Asn1Object pubKeyObj = Asn1Object.FromByteArray(publicInfoByte);//这里也可以从流中读取,从本地导入

AsymmetricKeyParameter pubKey = PublicKeyFactory.CreateKey(SubjectPublicKeyInfo.GetInstance(pubKeyObj));

IAsymmetricBlockCipher cipher = new RsaEngine();

cipher.Init(true, pubKey);//true表示加密

//加密

string data = "成功了。。。";

Console.WriteLine("\n明文:" + data);

byte[] encryptData = cipher.ProcessBlock(Encoding.UTF8.GetBytes(data), 0, Encoding.UTF8.GetBytes(data).Length);

Console.WriteLine("密文:" + Convert.ToBase64String(encryptData));

//解密

AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(privateInfoByte);

cipher.Init(false, priKey);//false表示解密

string decryptData = Encoding.UTF8.GetString(cipher.ProcessBlock(encryptData, 0, encryptData.Length));

Console.WriteLine("解密后数据:" + decryptData);

Console.Read();

}

}

}

运行结果:

[html] view
plaincopy

PublicKey:

MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCzoQTA/zgahiaytyggCLoodqhuG8gRUXypUt+9HAtPsNhRHC2ksQazS8DnyyrfgrmPfv///AHURL2itn7L1gfrVcm7QDLwM/gXCjUV5lkRrlp7SDF6yxrF00PLWOvAae1eEmmg9ucymEjwq2pzEVMJyWslJdXjvYOSDstUMbqCtQIBAw==

PrivateKey:

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==

明文:成功了。。。

密文:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC68tDDx2RzUu/BP/x93GcohXJeZeN4TZXUHEji3jjnyQV1yqDLdm5cOqjkqBQZHDZCq5fLhgg=

解密后数据:成功了。。。

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())
RSARSARSARSA
RSARSA/ECB/PKCS1PaddingRSARSA/ECB/PKCS1Padding
RSA/ECB/PKCS1PaddingRSARSA/ECB/PKCS1PaddingRSA
RSA/ECB/PKCS1PaddingRSA/ECB/PKCS1PaddingRSA/ECB/PKCS1PaddingRSA/ECB/PKCS1Padding
RSA/ECB/NoPaddingRSA
RSA/ECB/NoPaddingRSA/ECB/NoPadding
注意:代码中注释的地方很重要

[java] view
plaincopy

import java.io.ByteArrayOutputStream;

import java.lang.reflect.Method;

import java.nio.charset.Charset;

import java.security.InvalidKeyException;

import java.security.KeyFactory;

import java.security.NoSuchAlgorithmException;

import java.security.PrivateKey;

import java.security.PublicKey;

import java.security.interfaces.RSAPrivateKey;

import java.security.interfaces.RSAPublicKey;

import java.security.spec.InvalidKeySpecException;

import java.security.spec.PKCS8EncodedKeySpec;

import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;

import javax.crypto.Cipher;

import javax.crypto.IllegalBlockSizeException;

import javax.crypto.NoSuchPaddingException;

/**

* @author 邓少林

*

*/

public class RSAUtil {

private static int MAXENCRYPTSIZE = 117;

private static int MAXDECRYPTSIZE = 128;

/**

* @param publicKeyByte

* @return RSAPublicKey

* @throws NoSuchAlgorithmException

* @throws InvalidKeySpecException

*/

public static RSAPublicKey getPublicKey(byte[] publicKeyByte) throws NoSuchAlgorithmException, InvalidKeySpecException{

X509EncodedKeySpec x509 = new X509EncodedKeySpec(publicKeyByte);

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(x509);

return publicKey;

}

public static RSAPrivateKey getPrivateKey(byte[] privateKeyByte) throws InvalidKeySpecException, NoSuchAlgorithmException {

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyByte);

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);

}

/**

* encrypt

* @param source

* @param publicKey

* @return Bute[] encryptData

* @throws Exception

*/

public static byte[] encrypt(PublicKey publicKey, byte[] source)

throws Exception {

try {

//此处填充方式选择部填充 NoPadding,当然模式和填充方式选择其他的,在Java端可以正确加密解密,

//但是解密后的密文提交给C#端,解密的得到的数据将产生乱码

Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");

cipher.init(Cipher.ENCRYPT_MODE, publicKey);

int length = source.length;

int offset = 0;

byte[] cache;

ByteArrayOutputStream outStream = new ByteArrayOutputStream();

int i = 0;

while (length - offset > 0) {

if (length - offset > MAXENCRYPTSIZE) {

cache = cipher.doFinal(source, offset, MAXENCRYPTSIZE);

} else {

cache = cipher.doFinal(source, offset, length - offset);

}

outStream.write(cache, 0, cache.length);

i++;

offset = i * MAXENCRYPTSIZE;

}

return outStream.toByteArray();

} catch (NoSuchAlgorithmException e) {

e.printStackTrace();

} catch (NoSuchPaddingException e) {

e.printStackTrace();

} catch (InvalidKeyException e) {

e.printStackTrace();

} catch (IllegalBlockSizeException e) {

e.printStackTrace();

} catch (BadPaddingException e) {

e.printStackTrace();

}

return null;

}

/**RSA decrypt

* @param privateKey

* @param encryptData

* @return decryptData

* @throws IllegalBlockSizeException

* @throws BadPaddingException

* @throws InvalidKeyException

* @throws NoSuchAlgorithmException

* @throws NoSuchPaddingException

*/

public static byte[] decrypt(PrivateKey privateKey, byte[] encryptData)

throws IllegalBlockSizeException, BadPaddingException,

InvalidKeyException, NoSuchAlgorithmException,

NoSuchPaddingException {

//此处模式选择与加密对应,但是需要添加第二个参数new org.bouncycastle.jce.provider.BouncyCastleProvider()

//若不添加第二个参数的话,解密后的数据前面出现大段空格符

Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding", new org.bouncycastle.jce.provider.BouncyCastleProvider());

cipher.init(Cipher.DECRYPT_MODE, privateKey);

int length = encryptData.length;

int offset = 0;

int i = 0;

byte[] cache;

ByteArrayOutputStream outStream = new ByteArrayOutputStream();

while (length - offset > 0) {

if (length - offset > MAXDECRYPTSIZE) {

cache = cipher.doFinal(encryptData, offset, MAXDECRYPTSIZE);

} else {

cache = cipher.doFinal(encryptData, offset, length - offset);

}

outStream.write(cache, 0, cache.length);

i++;

offset = i * MAXDECRYPTSIZE;

}

return outStream.toByteArray();

}

/**

* base64编码

*

* @param input

* @return output with base64 encoded

* @throws Exception

*/

public static String encodeBase64(byte[] input) throws Exception {

Class clazz = Class

.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");

Method mainMethod = clazz.getMethod("encode", byte[].class);

mainMethod.setAccessible(true);

Object retObj = mainMethod.invoke(null, new Object[] { input });

return (String) retObj;

}

/**

* base64解码

*

* @param input

* @return

* @throws Exception

*/

public static byte[] decodeBase64(String input) throws Exception {

Class clazz = Class

.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");

Method mainMethod = clazz.getMethod("decode", String.class);

mainMethod.setAccessible(true);

Object retObj = mainMethod.invoke(null, input);

return (byte[]) retObj;

}

public static void main(String[] args) throws Exception {

RSAPublicKey rsaPublicKey = getPublicKey(decodeBase64("MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCzoQTA/zgahiaytyggCLoodqhuG8gRUXypUt+9HAtPsNhRHC2ksQazS8DnyyrfgrmPfv///AHURL2itn7L1gfrVcm7QDLwM/gXCjUV5lkRrlp7SDF6yxrF00PLWOvAae1eEmmg9ucymEjwq2pzEVMJyWslJdXjvYOSDstUMbqCtQIBAw=="));

byte[] encryptData = encrypt(rsaPublicKey, "成功了...".getBytes(Charset.forName("utf-8")));

System.out.println("密文:\n" + encodeBase64(encryptData));

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=="));

System.out.println("解密后数据:" + new String(decrypt(privateKey, encryptData),"utf-8"));

}

}

运行结果:

[html] view
plaincopy

密文:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC68tDDx2RzUu/BP/x93GcohXJeZeN4TZXUHEji3jjnyQV1yqDLdm5cOqjkqBQZHDZCq5fLhgg=

解密后数据:成功了。。。

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

[csharp] view
plaincopy

static void Main(string[] args)

{

IAsymmetricBlockCipher cipher = new RsaEngine();

byte[] encryptData = Convert.FromBase64String("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC68tDDx2RzUu/BP/x93GcohXJeZeN4TZXUHEji3jjnyQV1yqDLdm5cOqjkqBQZHDZCq5fLhgg=");

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=="))));

cipher.Init(false, priKey);

Console.WriteLine(Encoding.UTF8.GetString(cipher.ProcessBlock(encryptData, 0, encryptData.Length)));

Console.WriteLine(Encoding.UTF8.GetString(cipher.ProcessBlock(encryptData, 0, encryptData.Length)).Equals("成功了。。。"));

Console.Read();

}

运行结果:

[plain] view
plaincopy

成功了。。。

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
plaincopy

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.IO;

using System.Security.Cryptography;

namespace ConsoleApplication1

{

class Program

{

static void Main(string[] args)

{

//------------------------------------------------------------------------------------------

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

/*RSAParameters paras = rsa.ExportParameters(true);

Console.WriteLine("-----------------------------------------------------------------------");

Console.WriteLine("Exponent:" + Convert.ToBase64String(paras.Exponent));

Console.WriteLine("Modulus:" + Convert.ToBase64String(paras.Modulus));

Console.WriteLine("P:" + Convert.ToBase64String(paras.P));

Console.WriteLine("Q:" + Convert.ToBase64String(paras.Q));

Console.WriteLine("DP:" + Convert.ToBase64String(paras.DP));

Console.WriteLine("DQ:" + Convert.ToBase64String(paras.DQ));

Console.WriteLine("InversQ:" + Convert.ToBase64String(paras.InverseQ));

Console.WriteLine("D:" + Convert.ToBase64String(paras.D));

Console.WriteLine("-----------------------------------------------------------------------");

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);

Console.WriteLine("-----------------------------------------------------------------------");

Console.WriteLine("the length of ExportCspBlobPublic:" + rsa.ExportCspBlob(false).Length);*/

Console.WriteLine("ExportCspBlobPublic:\n" + Convert.ToBase64String(rsa.ExportCspBlob(false)));//导出公钥数据

Console.WriteLine("-----------------------------------------------------------------------");

//Console.WriteLine("the length of ExportCspBlobPrivate:" + rsa.ExportCspBlob(true).Length);

Console.WriteLine("ExportCspBlobPrivate:\n" + Convert.ToBase64String(rsa.ExportCspBlob(true)));//导出私钥数据

Console.WriteLine("-----------------------------------------------------------------------");

Console.WriteLine("publicKeyResolve...");

byte[] exportPublic = rsa.ExportCspBlob(false);

Console.WriteLine(Convert.ToBase64String(PublicKeyResolve(exportPublic)));

Console.WriteLine("-----------------------------------------------------------------------");

Console.WriteLine("privateKeyResolve...");

Dictionary<string, byte[]> privateKeyParamaters = PrivateKeyResolve(rsa.ExportCspBlob(true));

foreach (string key in privateKeyParamaters.Keys)

{

Console.WriteLine(key + ":\n" + Convert.ToBase64String(privateKeyParamaters[key]));

}

Console.Read();

}

/// <summary>

/// 对ExportCspBlob(false)方法到处的私钥进行解析,提取私钥参数

/// </summary>

/// <param name="cspblobPublicKey">RSA.ExportCspBlob(false)得到的包含私钥信息</param>

/// <returns>公钥模数</returns>

public static byte[] PublicKeyResolve(byte[] cspblobPublicKey)

{

byte[] modulus = new byte[128];

Array.Reverse(cspblobPublicKey, 0, cspblobPublicKey.Length);

Buffer.BlockCopy(cspblobPublicKey, 0, modulus, 0, 128);

return modulus;

}

/// <summary>

/// 对ExportCspBlob(true)方法到处的私钥进行解析,提取私钥参数

/// </summary>

/// <param name="cspblobPrivateKey">RSA.ExportCspBlob(true)得到的包含私钥信息</param>

/// <returns>私钥参数</returns>

public static Dictionary<string, byte[]> PrivateKeyResolve(byte[] cspblobPrivateKey)

{

Dictionary<string, byte[]> privateKeyParameters = new Dictionary<string, byte[]>();

Array.Reverse(cspblobPrivateKey, 0, cspblobPrivateKey.Length);

int offset = 0;

byte[] part = new byte[128];

Buffer.BlockCopy(cspblobPrivateKey, offset, part, offset, part.Length);

privateKeyParameters.Add("D", part);

offset += part.Length;

part = new byte[64];

Buffer.BlockCopy(cspblobPrivateKey, offset, part, 0, part.Length);

privateKeyParameters.Add("INVERSEQ", part);

offset += part.Length;

part = new byte[64];

Buffer.BlockCopy(cspblobPrivateKey, offset, part, 0, part.Length);

privateKeyParameters.Add("DQ", part);

offset += part.Length;

part = new byte[64];

Buffer.BlockCopy(cspblobPrivateKey, offset, part, 0, part.Length);

privateKeyParameters.Add("DP", part);

offset += part.Length;

part = new byte[64];

Buffer.BlockCopy(cspblobPrivateKey, offset, part, 0, part.Length);

privateKeyParameters.Add("Q", part);

offset += part.Length;

part = new byte[64];

Buffer.BlockCopy(cspblobPrivateKey, offset, part, 0, part.Length);

privateKeyParameters.Add("P", part);

offset += part.Length;

part = new byte[128];

Buffer.BlockCopy(cspblobPrivateKey, offset, part, 0, part.Length);

privateKeyParameters.Add("MODULUS", part);

return privateKeyParameters;

}

}

}

运行结果:

[html] view
plaincopy

ExportCspBlobPublic:

BgIAAACkAABSU0ExAAQAAAEAAQCdsw5SKF57lm1ez9Pu1CkEwRlW+fyEAFuz/N+mYe0iNyjA2ePhZoW4ZdwnaEBx9Gonskuch6pasypJhPr5bbvNVHQjtEEJSdFG1exKQ7AxpMmmft8PyhUcYqa15XUpebQaM0Zi+V1yiOqki54kCZSeGrMwa26+vJ4JCx3y+Fngmw==

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

ExportCspBlobPrivate:

BwIAAACkAABSU0EyAAQAAAEAAQCdsw5SKF57lm1ez9Pu1CkEwRlW+fyEAFuz/N+mYe0iNyjA2ePhZoW4ZdwnaEBx9Gonskuch6pasypJhPr5bbvNVHQjtEEJSdFG1exKQ7AxpMmmft8PyhUcYqa15XUpebQaM0Zi+V1yiOqki54kCZSeGrMwa26+vJ4JCx3y+Fngm9cPox4JtkoE0KVNsA98WFkAs3bseEqlcZhGbyLwBOBq7jeXJCFv5IZ8ZxDWrpWRz2HminmQEXjj54y9/FjJYs+r+b0J5W4GmZWBFkaO+0TkKoQAqK46x/c739e74GMf5p1ZyBNjiDPDts/CPf9OruGaTRM5t2HUA6pASU6De2rAR8nGRCxODmbeKb8w4Y/Q7b7eY4Omwr9sSAwDMlylXnrk4kyuuouHuP+Mb+LWppsv5WO+KfnT16CY5ZmpbfTlTV/oNppVgMSBKgdiI+FQFHJiCZh+4awb3tkOOIsdmWKEdg03NCbev3WbH6dU3ZDZFJ27zbTNhD4BlkyGmEkIQxfx895qWFJnqTOeEUQd1M5UGSDIEfIw51ByLKS/nPq1M3aUN4nRIm8EzDOa8529ZU0wLJvoipER8qpeb6AyKKGF6dcEq2HooM54+qF2oJXVc3CPwFTjmytbeKOq1waInDZfu0eWF5m5ET7WrXRjGA1txlPOhC4tBI6yJEgzdY5eVFJcqsYl8asHyaWIM07GZbS8opP1ePIv9YybeUEUg+Y4gsWBjTnmYgF4nEhLGmXtmGFQWbAnzQVsWqvmXb3RN5Y=

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

publicKeyResolve...

m+BZ+PIdCwmevL5uazCzGp6UCSSei6TqiHJd+WJGMxq0eSl15bWmYhwVyg/ffqbJpDGwQ0rs1UbRSQlBtCN0VM27bfn6hEkqs1qqh5xLsidq9HFAaCfcZbiFZuHj2cAoNyLtYabf/LNbAIT8+VYZwQQp1O7Tz15tlnteKFIOs50=

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

privateKeyResolve...

D:

ljfRvV3mq1psBc0nsFlQYZjtZRpLSJx4AWLmOY2BxYI45oMUQXmbjPUv8nj1k6K8tGXGTjOIpckHq/ElxqpcUlRejnUzSCSyjgQtLoTOU8ZtDRhjdK3WPhG5mReWR7tfNpyIBteqo3hbK5vjVMCPcHPVlaB2ofp4zqDoYasE1+k=

INVERSEQ:

haEoMqBvXqryEZGK6JssME1lvZ3zmjPMBG8i0Yk3lHYztfqcv6QsclDnMPIRyCAZVM7UHUQRnjOpZ1JYat7z8Q==

DQ:

F0MISZiGTJYBPoTNtM27nRTZkN1Upx+bdb/eJjQ3DXaEYpkdizgO2d4brOF+mAlichRQ4SNiByqBxIBVmjboXw==

DP:

TeX0bamZ5Zig19P5Kb5j5S+bptbib4z/uIeLuq5M4uR6XqVcMgMMSGy/wqaDY96+7dCP4TC/Kd5mDk4sRMbJRw==

Q:

wGp7g05JQKoD1GG3ORNNmuGuTv89ws+2wzOIYxPIWZ3mH2Pgu9ffO/fHOq6oAIQq5ET7jkYWgZWZBm7lCb35qw==

P:

z2LJWPy9jOfjeBGQeYrmYc+Rla7WEGd8huRvISSXN+5q4ATwIm9GmHGlSnjsdrMAWVh8D7BNpdAESrYJHqMP1w==

MODULUS:

m+BZ+PIdCwmevL5uazCzGp6UCSSei6TqiHJd+WJGMxq0eSl15bWmYhwVyg/ffqbJpDGwQ0rs1UbRSQlBtCN0VM27bfn6hEkqs1qqh5xLsidq9HFAaCfcZbiFZuHj2cAoNyLtYabf/LNbAIT8+VYZwQQp1O7Tz15tlnteKFIOs50=

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

[java] view
plaincopy

import java.util.Hashtable;

public class ExportCspBlobResolve {

/**

* 解析公钥

* @param cspblobPublicKey由C# new RSACryptoServiceProvider().ExportCspBlob(false)提供

* @return RSA公钥的Modulus参数

*/

public static byte[] publicKeyResolve(byte[] cspblobPublicKey){

int length = cspblobPublicKey.length;

byte[] reversePublicKey = new byte[length];

for (int i = 0; i < length; i++) {

reversePublicKey[i] = cspblobPublicKey[length - 1 - i];

}

byte[] part = new byte[128];

for (int i = 0; i < part.length; i++)

part[i] = reversePublicKey[i];

return part;

}

/**

* 解析私钥

* @param cspblobPrivateKey由C# new RSACryptoServiceProvider().ExportCspBlob(true)提供

* @return 返回包含私钥参数的Hashtable

*/

public static Hashtable<String, byte[]> privateKeyResolve(byte[] cspblobPrivateKey) {

Hashtable<String, byte[]> privateKeyParameters = new Hashtable<String, byte[]>();

int length = cspblobPrivateKey.length;

byte[] reversePrivateKey = new byte[length];

for (int i = 0; i < length; i++) {

reversePrivateKey[i] = cspblobPrivateKey[length - 1 - i];

}

int offset = 0;

byte[] part = new byte[128];

for (int i = 0; i < part.length; i++)

part[i] = reversePrivateKey[offset + i];

privateKeyParameters.put("D", part);

offset += part.length;

part = new byte[64];

for (int i = 0; i < part.length; i++)

part[i] = reversePrivateKey[offset + i];

privateKeyParameters.put("INVERSEQ", part);

offset += part.length;

part = new byte[64];

for (int i = 0; i < part.length; i++)

part[i] = reversePrivateKey[offset + i];

privateKeyParameters.put("DQ", part);

offset += part.length;

part = new byte[64];

for (int i = 0; i < part.length; i++)

part[i] = reversePrivateKey[offset + i];

privateKeyParameters.put("DP", part);

offset += part.length;

part = new byte[64];

for (int i = 0; i < part.length; i++)

part[i] = reversePrivateKey[offset + i];

privateKeyParameters.put("Q", part);

offset += part.length;

part = new byte[64];

for (int i = 0; i < part.length; i++)

part[i] = reversePrivateKey[offset + i];

privateKeyParameters.put("P", part);

offset += part.length;

part = new byte[128];

for (int i = 0; i < part.length; i++)

part[i] = reversePrivateKey[offset + i];

privateKeyParameters.put("MODULUS", part);

return privateKeyParameters;

}

}

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

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

RSA参数在Java和C#间的对应关系

RSA for JavaRSA for C#RSA forJavaRSA for C#
PublicExPonentExponentPrimeQQ
ModulesModulusPrimeExponentPDP
PrivateExponentDPrimeExponentQDQ
PrimePPCrtCoefficientInverseQ

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: