
正文
[WP8.1]RSA 使用BouncyCastle 公钥解密
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
写应用的时候遇到个服务器返回私钥加密过的数据 ,然后要在客户端用公钥解密的需求 ,一直没找到方法,应用搁置了一个学期,多方搜索,结论就是.net没有实现公钥解密的方法,要自己实现,于是硬着头皮开始看 portable.bouncycastle
关于RSA的原理,这是我从MSDN盗的图,链接在这https://msdn.microsoft.com/zh-cn/library/system.security.cryptography.rsaparameters.aspx

简单说就是
密文 = (明文 ^privateExponent) mod modulus
明文 = (密文 ^publicExponent) mod modulus
公钥中含有两个参数 一个是modulus ,另一个是publicExponent,私钥中有 modulus和privateExponent两个参数(当然私钥中不止这两个参数,但方法里只用到这两个,其他不管)
由于拿到的公钥和私钥都是PEM格式的,所以要先从PEM格式的公钥和私钥中提取这些参数 ,然后进行大数运算就能得出结果
这里要感谢前辈的努力,详细的解析了PEM文件格式

现在假设假设公钥和私钥分别为
const string PUBLICKEY =
@"-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpsDr+W45aFHIkvotZaGK/THlF
FpuZfUtghhWkHAm3H7yvL42J4xHrTr6IeUDCl4eKe6qiIgvYSNoL3u4SERGOeYmV
1F+cocu9IMGnNoicbh1zVW6e8/iGT3xaYQizJoVuWA/TC/zdds2ihCJfHDBDsouO
CXecPapyWCGQNsH5sQIDAQAB
-----END PUBLIC KEY-----";
const string PRIVATEKEY =
@"-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDpsDr+W45aFHIkvotZaGK/THlFFpuZfUtghhWkHAm3H7yvL42J
4xHrTr6IeUDCl4eKe6qiIgvYSNoL3u4SERGOeYmV1F+cocu9IMGnNoicbh1zVW6e
8/iGT3xaYQizJoVuWA/TC/zdds2ihCJfHDBDsouOCXecPapyWCGQNsH5sQIDAQAB
AoGBAM/JbFs4y5WbMncrmjpQj+UrOXVOCeLrvrc/4kQ+zgCvTpWywbaGWiuRo+cz
cXrVQ6bGGU362e9hr8f4XFViKemDL4SmJbgSDa1K71i+/LnnzF6sjiDBFQ/jA9SK
4PYrY7a3IkeBQnJmknanykugyQ1xmCjbuh556fOeRPaHnhx1AkEA/flrxJSy1Z+n
Y1RPgDOeDqyG6MhwU1Jl0yJ1sw3Or4qGRXhjTeGsCrKqV0/ajqdkDEM7FNkqnmsB
+vPd116J6wJBAOuNY3oOWvy2fQ32mj6XV+S2vcG1osEUaEuWvEgkGqJ9co6100Qp
j15036AQEEDqbjdqS0ShfeRSwevTJZIap9MCQCeMGDDjKrnDA5CfB0YiQ4FrchJ7
a6o90WdAHW3FP6LsAh59MZFmC6Ea0xWHdLPz8stKCMAlVNKYPRWztZ6ctQMCQQC8
iWbeAy+ApvBhhMjg4HJRdpNbwO6MbLEuD3CUrZFEDfTrlU2MeVdv20xC6ZiY3Qtq
/4FPZZNGdZcSEuc3km5RAkApGkZmWetNwDJMcUJbSBrQMFfrQObqMPBPe+gEniQq
Ttwu1OULHlmUg9eW31wRI2uiXcFCJMHuro6iOQ1VJ4Qs
-----END RSA PRIVATE KEY-----";
于是获取公钥参数的方法为
// 获取modulus和publicExponent
string publicKey = PUBLICKEY.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", "");
byte[] btPem = Convert.FromBase64String(publicKey);
int pemModulus = , pemPublicExponent = ;
byte[] btPemModulus = new byte[];
byte[] btPemPublicExponent = new byte[];
for (int i = ; i < pemModulus; i++)
{
btPemModulus[i] = btPem[ + i];
}
for (int i = ; i < pemPublicExponent; i++)
{
btPemPublicExponent[i] = btPem[ + i];
}
公钥解密的方法为
BigInteger biModulus = new BigInteger(, btPemModulus);
BigInteger biExponent = new BigInteger(, btPemPublicExponent);
RsaKeyParameters publicParameters = new RsaKeyParameters(false, biModulus, biExponent);
IAsymmetricBlockCipher eng = new Pkcs1Encoding(new RsaEngine());
eng.Init(false, publicParameters);
// 解密已加密的数据
byte[] encryptedData = Convert.FromBase64String(rawData);
encryptedData = eng.ProcessBlock(encryptedData, , encryptedData.Length);
string result = Encoding.UTF8.GetString(encryptedData, , encryptedData.Length);
公钥加密的方法为
BigInteger biModulus = new BigInteger(, btPemModulus);
BigInteger biExponent = new BigInteger(, btPemPublicExponent);
RsaKeyParameters publicParameters = new RsaKeyParameters(false, biModulus, biExponent);
IAsymmetricBlockCipher eng = new Pkcs1Encoding(new RsaEngine());
eng.Init(true, publicParameters);
// 加密数据
byte[] encryptData = Encoding.UTF8.GetBytes(rawData);
encryptData = eng.ProcessBlock(encryptData, , encryptData.Length);
string result = Convert.ToBase64String(encryptData);
私钥的通过PEM文件格式详细解析里的图也可以方便的写出来,mark下以后写……( ̄o ̄) . z Z
顺便贴上WP 8.1里自带的RSA公钥加密 私钥解密
/// <summary>
/// WPRT的RSA公钥加密
/// </summary>
/// <param name="rawData">源数据</param>
/// <returns>加密后的数据</returns>
public static string PublicEncrypt(string rawData)
{
try
{
/*将文本转换成IBuffer*/
IBuffer bufferRawData = CryptographicBuffer.ConvertStringToBinary(rawData, BinaryStringEncoding.Utf8); /*加密算法提供程序*/
AsymmetricKeyAlgorithmProvider provider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm
(AsymmetricAlgorithmNames.RsaPkcs1); /*导入公钥*/
string PUBLIC_KEY = PUBLICKEY.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "");
CryptographicKey publicKey = provider.ImportPublicKey(CryptographicBuffer.DecodeFromBase64String(PUBLIC_KEY)); //加密
IBuffer result = CryptographicEngine.Encrypt(publicKey, bufferRawData, null);
byte[] res;
CryptographicBuffer.CopyToByteArray(result, out res);
Debug.WriteLine("WinRT公钥加密后:" + Convert.ToBase64String(res));
return Convert.ToBase64String(res);
}
catch (Exception e)
{
Debug.WriteLine("Encrypt Exception:" + e.StackTrace);
return rawData;
}
} /// <summary>
/// WPRT的RSA私钥解密
/// </summary>
/// <param name="rawData"></param>
/// <returns></returns>
public static string PrivateDecrypt(string rawData)
{
try
{
/*将文本转换成IBuffer*/
IBuffer bufferRawData = CryptographicBuffer.ConvertStringToBinary(rawData, BinaryStringEncoding.Utf8); /*加密算法提供程序*/
AsymmetricKeyAlgorithmProvider provider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm
(AsymmetricAlgorithmNames.RsaPkcs1); /*导入私钥*/
string PRIVATE_KEY = PRIVATEKEY.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "");
CryptographicKey privateKey = provider.ImportKeyPair(CryptographicBuffer.DecodeFromBase64String(PRIVATE_KEY)); //解密
IBuffer result = CryptographicEngine.Decrypt(privateKey, bufferRawData, null);
byte[] res;
CryptographicBuffer.CopyToByteArray(result, out res);
Debug.WriteLine("WinRT私钥解密后:" + Encoding.UTF8.GetString(res,,res.Length));
return Encoding.UTF8.GetString(res,,res.Length);
}
catch (Exception e)
{
Debug.WriteLine("Decrypt Exception:" + e.StackTrace);
return rawData;
}
}
参考链接
PEM文件格式详细解析
BouncyCastle






