對於上上篇博客中我講的一個故事,本文引用: https://www.cnblogs.com/ButterflyEffect/p/9851403.html
故事中提到的關於加密會出現,私鑰加密,公鑰解密的情況,這種情況我們將它稱為【私鑰加簽,公鑰驗簽】
說句好理解的話:
既然是加密,那肯定是不希望別人知道我的消息,所以只有我才能解密,所以可得出【公鑰負責加密,私鑰負責解密】
同理,既然是簽名,那肯定是不希望有人冒充我發消息,只有我才能發布這個簽名,所以可得出【私鑰負責加簽,公鑰負責驗簽】
由以上得出關於安全性的問題,再舉個好例子:
現在有A(私鑰A、公鑰A),B(私鑰B、公鑰B) ,A向B發送消息,用私鑰A加簽、用公鑰B加密,發送給B,B用私鑰B解密,然后用公鑰A驗簽。
這樣的話就能保證是A發的消息,並且只有B自己才能解密。這樣是非常安全的!!!
話不多少,下面直接擼代碼,以下代碼是實現【私鑰加簽公鑰驗簽】的功能,公鑰加密私鑰解密的功能在我其它博客有講過...
#region 私鑰加密,公鑰解密
/// <summary>
/// 私鑰加密
/// </summary>
/// <param name="privateKey">RSA私鑰 base64格式</param>
/// <param name="contentData">待加密的數據</param>
/// <param name="algorithm">加密算法</param>
/// <returns></returns>
public static string EncryptWithPrivateKey(string privateKey, byte[] contentData, string algorithm = "RSA/ECB/PKCS1Padding")
{
return Convert.ToBase64String(EncryptWithPrivateKey(Convert.FromBase64String(privateKey), contentData, algorithm));
}
/// <summary>
/// 私鑰加密
/// </summary>
/// <param name="privateKey">RSA私鑰</param>
/// <param name="contentData">待加密的數據</param>
/// <param name="algorithm">加密算法</param>
/// <returns></returns>
public static byte[] EncryptWithPrivateKey(byte[] privateKey, byte[] contentData, string algorithm = "RSA/ECB/PKCS1Padding")
{
RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(privateKey);
return Transform(privateKeyParam, contentData, algorithm, true);
}
/// <summary>
/// 公鑰解密
/// </summary>
/// <param name="publicKey">RSA公鑰 base64格式</param>
/// <param name="content">待解密數據 base64格式</param>
/// <param name="encoding">解密出來的數據編碼格式,默認UTF-8</param>
/// <param name="algorithm">加密算法</param>
/// <returns></returns>
public static string DecryptWithPublicKey(string publicKey, string content, string encoding = "UTF-8", string algorithm = "RSA/ECB/PKCS1Padding")
{
return Encoding.GetEncoding("GB2312").GetString(DecryptWithPublicKey(Convert.FromBase64String(publicKey), Convert.FromBase64String(content), algorithm));
}
/// <summary>
/// 公鑰解密
/// </summary>
/// <param name="publicKey">RSA公鑰</param>
/// <param name="contentData">待解密數據</param>
/// <param name="algorithm">加密算法</param>
/// <returns></returns>
public static byte[] DecryptWithPublicKey(byte[] publicKey, byte[] contentData, string algorithm = "RSA/ECB/PKCS1Padding")
{
RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(publicKey);
return Transform(publicKeyParam, contentData, algorithm, false);
}
#endregion
private static byte[] Transform(AsymmetricKeyParameter key, byte[] contentData, string algorithm, bool forEncryption)
{
var c = CipherUtilities.GetCipher(algorithm);
c.Init(forEncryption, new ParametersWithRandom(key));
return c.DoFinal(contentData);
}
順帶提下,這里的第三方RSA引用包可以在【程序包管理器控制台】輸入命令提示
PM> Install-Package BouncyCastle
完成包的安裝
static void Main(string[] args)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
string xmlPrivateKey = rsa.ToXmlString(true);//XML密鑰
string xmlPublicKey = rsa.ToXmlString(false);//XML公鑰
string str = "測試數據";
byte[] b = System.Text.Encoding.Default.GetBytes(str);//字符串轉字節數組,byte[]
string EncryptedData = EncryptWithPrivateKey(B(xmlPrivateKey), b);//返回加密后的base64格式數據
Console.WriteLine("私鑰加密結果:" + EncryptedData);
string DecipheringData = DecryptWithPublicKey(A(xmlPublicKey), EncryptedData);//返回解密后的明文數據
Console.WriteLine("公鑰解密結果:" + DecipheringData);
Console.ReadLine();
}
//XML格式轉base64格式,公鑰
public static string A(string xml)
{
var rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xml);
var p = rsa.ExportParameters(false);
RsaKeyParameters key = new RsaKeyParameters(false, new BigInteger(1, p.Modulus), new BigInteger(1, p.Exponent));
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(key);
byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
string publicKey = Convert.ToBase64String(serializedPublicBytes);
return publicKey;
}
//XML格式轉base64格式,私鑰
public static string B(string xml)
{
var rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xml);
var p = rsa.ExportParameters(true);
var key = new RsaPrivateCrtKeyParameters(
new BigInteger(1, p.Modulus), new BigInteger(1, p.Exponent), new BigInteger(1, p.D),
new BigInteger(1, p.P), new BigInteger(1, p.Q), new BigInteger(1, p.DP), new BigInteger(1, p.DQ),
new BigInteger(1, p.InverseQ));
PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(key);
byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();
string privateKey = Convert.ToBase64String(serializedPrivateBytes);
return privateKey;
}
最后加密測試可以在這個網站去測試 http://tool.chacuo.net/cryptrsapubkey