RSA加解密笔记
前文介绍了SM国产的对称加密算法介绍,这里记录一下RSA 非对称加密情况, 不太情况贸然上手还是有一些坑,密钥位数分为512,1024,2048, 4096 之类,
公钥,私钥成对出现,一般文本之类,如请求参数而言,公钥加密,私钥解密, 如果是证书,情况会稍微不同,这里不展开记录,
比如:双方对接数据的时候,各自掌握一对密钥,只需要提供给对方公钥即可,发送数据时对公钥进行加密,收到数据时用私钥进行解密,不用担心数据泄露,毕竟只有公钥是无法进行解密
RSA密钥分为 PKCS1 ,PKCS8 格式, 两种格式的公钥都是以 -----BEGIN PUBLIC KEY----- 开头,-----END PUBLIC KEY----- 结尾,
不同的是私钥,PKCS1 格式的开头和结束都会多一个 RSA ,PKCS8更通用一些
实际交互的时候,可能会将PEM模式的的密钥转换成XML 格式的进行处理,使用 RsaKeyParameters,PublicKeyFactory 这两个对象即可
public static string RSAPrivateKeyToXml(string privateKey) { privateKey = privateKey.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "").Replace("\n", "").Replace("\r", ""); RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey)); return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>", Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()), Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned())); } public static string RSAPublicToXml(string pem) { pem = pem.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", ""); RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(pem)); string xmlPub = string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>", Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); return xmlPub; }
此外加密,解密如下
/// <summary> /// RSA 加密 /// </summary> /// <param name="encryptString" >明文</param> /// <param name="publicKey" >公钥</param> public static string RSAEncrypt(string encryptString, string publicKey) { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(publicKey); byte[] encryptByte = Encoding.UTF8.GetBytes(encryptString); int maxSize = rsa.KeySize / 8 - 11; if (encryptByte.Length <= maxSize) { byte[] cipherbytes = rsa.Encrypt(encryptByte, false); return Convert.ToBase64String(cipherbytes); } else { using (MemoryStream plaiStream = new MemoryStream(encryptByte)) using (MemoryStream crypStream = new MemoryStream()) { byte[] buffer = new byte[maxSize]; int blockSize = plaiStream.Read(buffer, 0, maxSize); while (blockSize > 0) { byte[] ToEncrypt = new byte[blockSize]; Array.Copy(buffer, 0, ToEncrypt, 0, blockSize); byte[] Cryptograph = rsa.Encrypt(ToEncrypt, false); crypStream.Write(Cryptograph, 0, Cryptograph.Length); blockSize = plaiStream.Read(buffer, 0, maxSize); } return Convert.ToBase64String(crypStream.ToArray(), Base64FormattingOptions.None); } } } /// <summary> /// RSA 解密 /// </summary> /// <param name="decryptString">密文</param> /// <param name="privateKey">私钥</param> public static string RSADecrypt(string decryptString, string privateKey) { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); rsa.FromXmlString(privateKey); int maxSize = rsa.KeySize / 8; byte[] decryptByte = Convert.FromBase64String(decryptString); if (decryptByte.Length <= maxSize) { byte[] cipherbytes = rsa.Decrypt(decryptByte, false); return Encoding.UTF8.GetString(cipherbytes); } else { using (MemoryStream crypStream = new MemoryStream(decryptByte)) using (MemoryStream plaiStream = new MemoryStream()) { byte[] buffer = new byte[maxSize]; int blockSize = crypStream.Read(buffer, 0, maxSize); while (blockSize > 0) { byte[] toDecrypt = new byte[blockSize]; Array.Copy(buffer, 0, toDecrypt, 0, blockSize); byte[] plaintext = rsa.Decrypt(toDecrypt, false); plaiStream.Write(plaintext, 0, plaintext.Length); blockSize = crypStream.Read(buffer, 0, maxSize); } return Encoding.UTF8.GetString(plaiStream.ToArray()); } } }
调用结果:
大家好,我是新来的小白,文未佳,却已创。转载请声明(博客园-郎中令)出处,谢谢
---市人皆大笑,举手揶揄之(手动链接博客园)