因为工作需要,要在项目中使用rsa验签,所以就在在网上找了找,网上找的都不能用,就自己改了改。
这个示例中使用了BouncyCastle nuget包,最新的就行。
所有加签、加密返回结果都是base64的。
using System;
using System.Text;
using System.IO;
using System.Xml;
using System.Security.Cryptography;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
namespace RSADemo
{
public class RSAHelper
{
#region keys
const string PUBLICKEY =
@"-----BEGIN PUBLIC KEY-----
公钥
-----END PUBLIC KEY-----
";
const string PRIVATEKEY =
@"-----BEGIN RSA PRIVATE KEY-----
私钥
-----END RSA PRIVATE KEY-----
";
#endregion
/// <summary>
/// 制作签名
/// </summary>
/// <param name="encrpyData"></param>
/// <returns></returns>
public static string InvokeSign(string encrpyData)
{
RSAParameters para = ConvertFromPemPrivateKey(PRIVATEKEY);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(para);
byte[] Data = Encoding.UTF8.GetBytes(encrpyData);
byte[] signData = rsa.SignData(Data, "SHA1");//使用MD5方式算法制作签名
return Convert.ToBase64String(signData);
}
/// <summary>
/// 验证签名
/// </summary>
/// <param name="data">原始数据</param>
/// <param name="sign">签名数据</param>
/// <returns></returns>
public static bool CheckSign(string data, string sign)
{
RSAParameters para = ConvertFromPemPublicKey(PUBLICKEY);//公钥验证
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(para);
//MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
//SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
byte[] Data = Encoding.UTF8.GetBytes(data);
byte[] rgbSignature = Convert.FromBase64String(sign);
if (rsa.VerifyData(Data, "SHA1", rgbSignature))
{
return true;
}
return false;
}
public static string RsaEncrypt(string rawInput)
{
if (string.IsNullOrEmpty(rawInput))
{
return string.Empty;
}
if (string.IsNullOrWhiteSpace(PUBLICKEY))
{
throw new ArgumentException("Invalid Public Key");
}
using (var rsaProvider = new RSACryptoServiceProvider())
{
var inputBytes = Encoding.UTF8.GetBytes(rawInput);//有含义的字符串转化为字节流
string pemFileConent = PUBLICKEY.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", "");
rsaProvider.FromXmlString(pemFileConent);//载入公钥
int bufferSize = (rsaProvider.KeySize / 8) - 11;//单块最大长度
var buffer = new byte[bufferSize];
using (MemoryStream inputStream = new MemoryStream(inputBytes),
outputStream = new MemoryStream())
{
while (true)
{ //分段加密
int readSize = inputStream.Read(buffer, 0, bufferSize);
if (readSize <= 0)
{
break;
}
var temp = new byte[readSize];
Array.Copy(buffer, 0, temp, 0, readSize);
var encryptedBytes = rsaProvider.Encrypt(temp, false);
outputStream.Write(encryptedBytes, 0, encryptedBytes.Length);
}
return Convert.ToBase64String(outputStream.ToArray());//转化为字节流方便传输
}
}
}
public static string RsaDecrypt(string encryptedInput)
{
if (string.IsNullOrEmpty(encryptedInput))
{
return string.Empty;
}
if (string.IsNullOrWhiteSpace(PRIVATEKEY))
{
throw new ArgumentException("Invalid Private Key");
}
using (var rsaProvider = new RSACryptoServiceProvider())
{
var inputBytes = Convert.FromBase64String(encryptedInput);
string pemFileConent = PRIVATEKEY.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("\n", "").Replace("\r", "");
rsaProvider.FromXmlString(pemFileConent);
int bufferSize = rsaProvider.KeySize / 8;
var buffer = new byte[bufferSize];
using (MemoryStream inputStream = new MemoryStream(inputBytes),
outputStream = new MemoryStream())
{
while (true)
{
int readSize = inputStream.Read(buffer, 0, bufferSize);
if (readSize <= 0)
{
break;
}
var temp = new byte[readSize];
Array.Copy(buffer, 0, temp, 0, readSize);
var rawBytes = rsaProvider.Decrypt(temp, false);
outputStream.Write(rawBytes, 0, rawBytes.Length);
}
return Encoding.UTF8.GetString(outputStream.ToArray());
}
}
}
public static RSAParameters ConvertFromPemPrivateKey(string serializedPrivate)
{
serializedPrivate = serializedPrivate.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "").Replace("\n", "").Replace("\r", "");
RsaPrivateCrtKeyParameters privateKey = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(serializedPrivate));
RSACryptoServiceProvider rcsp = new RSACryptoServiceProvider();
RSAParameters parms = new RSAParameters();
parms.Modulus = privateKey.Modulus.ToByteArrayUnsigned();
parms.P = privateKey.P.ToByteArrayUnsigned();
parms.Q = privateKey.Q.ToByteArrayUnsigned();
parms.DP = privateKey.DP.ToByteArrayUnsigned();
parms.DQ = privateKey.DQ.ToByteArrayUnsigned();
parms.InverseQ = privateKey.QInv.ToByteArrayUnsigned();
parms.D = privateKey.Exponent.ToByteArrayUnsigned();
parms.Exponent = privateKey.PublicExponent.ToByteArrayUnsigned();
return parms;
}
/// <summary>
/// 将pem格式公钥(1024 or 2048)转换为RSAParameters
/// </summary>
/// <param name="pemFileConent">pem公钥内容</param>
/// <returns>转换得到的RSAParamenters</returns>
public static RSAParameters ConvertFromPemPublicKey(string pemFileConent)
{
if (string.IsNullOrEmpty(pemFileConent))
{
throw new ArgumentNullException("pemFileConent", "This arg cann't be empty.");
}
pemFileConent = pemFileConent.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", "");
byte[] keyData = Convert.FromBase64String(pemFileConent);
bool keySize1024 = (keyData.Length == 162);
bool keySize2048 = (keyData.Length == 294);
if (!(keySize1024 || keySize2048))
{
throw new ArgumentException("pem file content is incorrect, Only support the key size is 1024 or 2048");
}
byte[] pemModulus = (keySize1024 ? new byte[128] : new byte[256]);
byte[] pemPublicExponent = new byte[3];
Array.Copy(keyData, (keySize1024 ? 29 : 33), pemModulus, 0, (keySize1024 ? 128 : 256));
Array.Copy(keyData, (keySize1024 ? 159 : 291), pemPublicExponent, 0, 3);
RSAParameters para = new RSAParameters();
para.Modulus = pemModulus;
para.Exponent = pemPublicExponent;
return para;
}
}
}