powered by 25175.netnet中已经有实现RSA算法的System.Security.Cryptography.RSACryptoServiceProvider
实现方法如下:

public class CryptoRSA { /// <summary> /// 生成公钥和私钥信息 /// </summary> public static void ExportKeyXml() { //ExportParameters和ToXmlString选true时表示公钥和私钥信息同时导出,选false则只导出公钥信息 System.Security.Cryptography.RSACryptoServiceProvider rsa = new System.Security.Cryptography.RSACryptoServiceProvider(); System.IO.StreamWriter swPublic = new System.IO.StreamWriter(HttpContext.Current.Server.MapPath(@"PublicKeyXml.xml")); swPublic.Write(rsa.ToXmlString(false)); swPublic.Close(); System.IO.StreamWriter swPrivate = new System.IO.StreamWriter(HttpContext.Current.Server.MapPath(@"PrivateKeyXml.xml")); swPrivate.Write(rsa.ToXmlString(true)); swPrivate.Close(); } /// <summary> /// 加密数据 /// </summary> /// <param name="encryptData">需要加密的明文</param> /// <returns>加密后的十六进制字符串,带横杠</returns> public string EncryptData(string encryptData) { //我的xp系统加密数据只支持最长117字节,如果超过了,将会报错,可以采用分段加密 if (encryptData.Length > 117) return ""; System.Security.Cryptography.RSACryptoServiceProvider rsa = new System.Security.Cryptography.RSACryptoServiceProvider(); //获取公钥信息 System.IO.StreamReader sr = new System.IO.StreamReader(@"F:\Study\myProject\test2005\PublicKeyXml.xml"); rsa.FromXmlString(sr.ReadToEnd()); sr.Close(); //加密 byte[] bytResult = rsa.Encrypt(System.Text.Encoding.Default.GetBytes(encryptData), false); return BitConverter.ToString(bytResult); } /// <summary> /// 解密数据 /// </summary> /// <param name="decryptData">加密十六进制字符串,带横杠</param> /// <returns>解密明文</returns> public string DecryptData(string decryptData) { System.Security.Cryptography.RSACryptoServiceProvider rsa = new System.Security.Cryptography.RSACryptoServiceProvider(); //获取私钥钥信息 System.IO.StreamReader sr = new System.IO.StreamReader(@"F:\Study\myProject\test2005\PrivateKeyXml.xml"); rsa.FromXmlString(sr.ReadToEnd()); sr.Close(); //解密,因为我的加密数据转换成十六进制字符串时没有去掉"-",所以这里直接通过split('-')来分数组 //不知道还有没有更好的办法处理,比如隔两位取一次等 string[] strKey = decryptData.Split('-'); byte[] bytKey = new byte[128]; for (int i = 0; i < strKey.Length; i++) { bytKey[i] = Convert.ToByte(strKey[i], 16); } byte[] bytDecryptResult = rsa.Decrypt(bytKey, false); return System.Text.Encoding.Default.GetString(bytDecryptResult); } }
但有时我们需要在项目中自己实现RSA方法这就需要用到BigInteger类,在 .net Framework 3.5 beta 时,微软曾引入了一个新的包 System.Numerics,其中包含了大整数(BigInteger)类,不过可惜在后来的接近发布时,这个包又移除了。现在 .net Framework 4.0 又重新将它请了回来。而且这次的正式版本中不会再次移除了。这对 .net 开发者算是一个好事,但如果只有使用 .net Framework 4.0 的用户才能享受到这个包,还是不太完美,毕竟现在大多数 .net 开发还停留在 2.0 或 3.5 的阶段。
KevinShan实现了基于System.Numerics.dll中BigInteger Class的RSA算法。
代码如下:

using System; using System.Security.Cryptography; using System.IO; using System.Xml; using System.Numerics; using System.Diagnostics; namespace RSAManaged { #region The RSAManaged class public class RSAManaged { #region PublicKey Encrypt -> PrivateKey Decrypt public static byte[] Encrypt(byte[] data, RSAPublicKey publicKey) { if (data == null) { throw new ArgumentNullException("data"); } if (publicKey == null) { throw new ArgumentNullException("publicKey"); } // // 1?钥?加ó密ü/解a密ü1?ê?为a£oci = mi^e ( mod n ) // // 先è将? m£¨二t进?制?±íê?£?·?3éêy据Y块é m1, m2, ..., mi £?è?oó进?DD运?算?。£ // BigInteger e = ConvertToBigInteger(publicKey.Exponent); BigInteger n = ConvertToBigInteger(publicKey.Modulus); int inputBlockMaxSize = publicKey.Modulus.Length - 1; int outputBlockSize = publicKey.Modulus.Length + 1; using (MemoryStream stream = new MemoryStream()) { int inputBlockOffset = 0; int outputBlockOffset = 0; int lastInputBlockSize = data.Length % inputBlockMaxSize; byte[] lastInputBlockSizeData = BitConverter.GetBytes(lastInputBlockSize); stream.Write(lastInputBlockSizeData, 0, lastInputBlockSizeData.Length); outputBlockOffset += lastInputBlockSizeData.Length; while (inputBlockOffset < data.Length) { int inputBlockSize = Math.Min(inputBlockMaxSize, data.Length - inputBlockOffset); byte[] inputBlockData = new byte[inputBlockSize + 1]; Buffer.BlockCopy(data, inputBlockOffset, inputBlockData, 0, inputBlockSize); inputBlockOffset += inputBlockSize; BigInteger mi = new BigInteger(inputBlockData); BigInteger ci = BigInteger.ModPow(mi, e, n);//ci = mi^e ( mod n ) byte[] outputBlockData = ci.ToByteArray(); stream.Write(outputBlockData, 0, outputBlockData.Length); outputBlockOffset += outputBlockSize; stream.Seek(outputBlockOffset, SeekOrigin.Begin); } stream.SetLength(outputBlockOffset); return stream.ToArray(); } } public static byte[] Decrypt(byte[] data, RSAPrivateKey privateKey) { if (data == null) { throw new ArgumentNullException("data"); } if (privateKey == null) { throw new ArgumentNullException("privateKey"); } // // 私?钥?加ó密ü/解a密ü1?ê?为a£omi = ci^d ( mod n ) // // 先è将? c£¨二t进?制?±íê?£?·?3éêy据Y块é c1, c2, ..., ci £?è?oó进?DD运?算?。£ // BigInteger d = ConvertToBigInteger(privateKey.D); BigInteger n = ConvertToBigInteger(privateKey.Modulus); int inputBlockSize = privateKey.Modulus.Length + 1; int outputBlockMaxSize = privateKey.Modulus.Length - 1; if (data.Length % inputBlockSize != sizeof(Int32)) { return null; } using (MemoryStream stream = new MemoryStream()) { int inputBlockOffset = 0; int outputBlockOffset = 0; int lastOutputBlockSize = BitConverter.ToInt32(data, inputBlockOffset); inputBlockOffset += sizeof(Int32); if (lastOutputBlockSize > outputBlockMaxSize) { return null; } while (inputBlockOffset < data.Length) { byte[] inputBlockData = new byte[inputBlockSize]; Buffer.BlockCopy(data, inputBlockOffset, inputBlockData, 0, inputBlockSize); inputBlockOffset += inputBlockSize; BigInteger ci = new BigInteger(inputBlockData); BigInteger mi = BigInteger.ModPow(ci, d, n);//mi = ci^d ( mod n ) byte[] outputBlockData = mi.ToByteArray(); stream.Write(outputBlockData, 0, outputBlockData.Length); outputBlockOffset += inputBlockOffset >= data.Length ? lastOutputBlockSize : outputBlockMaxSize; stream.Seek(outputBlockOffset, SeekOrigin.Begin); } stream.SetLength(outputBlockOffset); return stream.ToArray(); } } #endregion #region PublicKey Sign -> PrivateKey Verify public static byte[] Sign(byte[] data, RSAPublicKey publicKey, HashAlgorithm hash) { if (data == null) { throw new ArgumentNullException("data"); } if (publicKey == null) { throw new ArgumentNullException("publicKey"); } if (hash == null) { throw new ArgumentNullException("hash"); } byte[] hashData = hash.ComputeHash(data); byte[] signature = Encrypt(hashData, publicKey); return signature; } public static bool Verify(byte[] data, RSAPrivateKey privateKey, HashAlgorithm hash, byte[] signature) { if (data == null) { throw new ArgumentNullException("data"); } if (privateKey == null) { throw new ArgumentNullException("privateKey"); } if (hash == null) { throw new ArgumentNullException("hash"); } if (signature == null) { throw new ArgumentNullException("signature"); } byte[] hashData = hash.ComputeHash(data); byte[] signatureHashData = Decrypt(signature, privateKey); if (signatureHashData != null && signatureHashData.Length == hashData.Length) { for (int i = 0; i < signatureHashData.Length; i++) { if (signatureHashData[i] != hashData[i]) { return false; } } return true; } return false; } #endregion #region PrivateKey Encrypt -> PublicKey Decrypt public static byte[] Encrypt(byte[] data, RSAPrivateKey privateKey) { if (data == null) { throw new ArgumentNullException("data"); } if (privateKey == null) { throw new ArgumentNullException("privateKey"); } // // 私?钥?加ó密ü/解a密ü1?ê?为a£omi = ci^d ( mod n ) // // 先è将? c£¨二t进?制?±íê?£?·?3éêy据Y块é c1, c2, ..., ci £?è?oó进?DD运?算?。£ // BigInteger d = ConvertToBigInteger(privateKey.D); BigInteger n = ConvertToBigInteger(privateKey.Modulus); int inputBlockMaxSize = privateKey.Modulus.Length - 1; int outputBlockSize = privateKey.Modulus.Length + 1; using (MemoryStream stream = new MemoryStream()) { int inputBlockOffset = 0; int outputBlockOffset = 0; int lastInputBlockSize = data.Length % inputBlockMaxSize; byte[] lastInputBlockSizeData = BitConverter.GetBytes(lastInputBlockSize); stream.Write(lastInputBlockSizeData, 0, lastInputBlockSizeData.Length); outputBlockOffset += lastInputBlockSizeData.Length; while (inputBlockOffset < data.Length) { int inputBlockSize = Math.Min(inputBlockMaxSize, data.Length - inputBlockOffset); byte[] inputBlockData = new byte[inputBlockSize + 1]; Buffer.BlockCopy(data, inputBlockOffset, inputBlockData, 0, inputBlockSize); inputBlockOffset += inputBlockSize; BigInteger ci = new BigInteger(inputBlockData); BigInteger mi = BigInteger.ModPow(ci, d, n);//mi = ci^d ( mod n ) byte[] outputBlockData = ci.ToByteArray(); stream.Write(outputBlockData, 0, outputBlockData.Length); outputBlockOffset += outputBlockSize; stream.Seek(outputBlockOffset, SeekOrigin.Begin); } stream.SetLength(outputBlockOffset); return stream.ToArray(); } } public static byte[] Decrypt(byte[] data, RSAPublicKey publicKey) { if (data == null) { throw new ArgumentNullException("data"); } if (publicKey == null) { throw new ArgumentNullException("publicKey"); } // // 1?钥?加ó密ü/解a密ü1?ê?为a£oci = mi^e ( mod n ) // // 先è将? m£¨二t进?制?±íê?£?·?3éêy据Y块é m1, m2, ..., mi £?è?oó进?DD运?算?。£ // BigInteger e = ConvertToBigInteger(publicKey.Exponent); BigInteger n = ConvertToBigInteger(publicKey.Modulus); int inputBlockSize = publicKey.Modulus.Length + 1; int outputBlockMaxSize = publicKey.Modulus.Length - 1; if (data.Length % inputBlockSize != sizeof(Int32)) { return null; } using (MemoryStream stream = new MemoryStream()) { int inputBlockOffset = 0; int outputBlockOffset = 0; int lastOutputBlockSize = BitConverter.ToInt32(data, inputBlockOffset); inputBlockOffset += sizeof(Int32); if (lastOutputBlockSize > outputBlockMaxSize) { return null; } while (inputBlockOffset < data.Length) { byte[] inputBlockData = new byte[inputBlockSize]; Buffer.BlockCopy(data, inputBlockOffset, inputBlockData, 0, inputBlockSize); inputBlockOffset += inputBlockSize; BigInteger mi = new BigInteger(inputBlockData); BigInteger ci = BigInteger.ModPow(mi, e, n);//ci = mi^e ( mod n ) byte[] outputBlockData = mi.ToByteArray(); stream.Write(outputBlockData, 0, outputBlockData.Length); outputBlockOffset += inputBlockOffset >= data.Length ? lastOutputBlockSize : outputBlockMaxSize; stream.Seek(outputBlockOffset, SeekOrigin.Begin); } stream.SetLength(outputBlockOffset); return stream.ToArray(); } } #endregion #region PrivateKey Sign -> PublicKey Verify public static byte[] Sign(byte[] data, RSAPrivateKey privateKey, HashAlgorithm hash) { if (data == null) { throw new ArgumentNullException("data"); } if (privateKey == null) { throw new ArgumentNullException("privateKey"); } if (hash == null) { throw new ArgumentNullException("hash"); } byte[] hashData = hash.ComputeHash(data); byte[] signature = Encrypt(hashData, privateKey); return signature; } public static bool Verify(byte[] data, RSAPublicKey publicKey, HashAlgorithm hash, byte[] signature) { if (data == null) { throw new ArgumentNullException("data"); } if (publicKey == null) { throw new ArgumentNullException("publicKey"); } if (hash == null) { throw new ArgumentNullException("hash"); } if (signature == null) { throw new ArgumentNullException("signature"); } byte[] hashData = hash.ComputeHash(data); byte[] signatureHashData = Decrypt(signature, publicKey); if (signatureHashData != null && signatureHashData.Length == hashData.Length) { for (int i = 0; i < signatureHashData.Length; i++) { if (signatureHashData[i] != hashData[i]) { return false; } } return true; } return false; } #endregion #region Methods private static BigInteger ConvertToBigInteger(byte[] value) { Debug.Assert(value != null); byte[] temp = new byte[value.Length + 1]; for (int i = 0; i < value.Length; i++) { temp[value.Length - 1 - i] = value[i]; } return new BigInteger(temp); } #endregion } #endregion #region The RSAPublicKey class public class RSAPublicKey { public byte[] Modulus; public byte[] Exponent; public static RSAPublicKey FromXmlString(string xmlString) { if (string.IsNullOrEmpty(xmlString)) { return null; } try { using (XmlReader reader = XmlReader.Create(new StringReader(xmlString))) { if (!reader.ReadToFollowing("RSAKeyValue")) { return null; } if (reader.LocalName != "Modulus" && !reader.ReadToFollowing("Modulus")) { return null; } string modulus = reader.ReadElementContentAsString(); if (reader.LocalName != "Exponent" && !reader.ReadToFollowing("Exponent")) { return null; } string exponent = reader.ReadElementContentAsString(); RSAPublicKey publicKey = new RSAPublicKey(); publicKey.Modulus = Convert.FromBase64String(modulus); publicKey.Exponent = Convert.FromBase64String(exponent); return publicKey; } } catch { return null; } } } #endregion #region The RSAPrivateKey class public class RSAPrivateKey { public byte[] Modulus; public byte[] D; public static RSAPrivateKey FromXmlString(string xmlString) { if (string.IsNullOrEmpty(xmlString)) { return null; } try { using (XmlReader reader = XmlReader.Create(new StringReader(xmlString))) { if (!reader.ReadToFollowing("RSAKeyValue")) { return null; } if (reader.LocalName != "Modulus" && !reader.ReadToFollowing("Modulus")) { return null; } string modulus = reader.ReadElementContentAsString(); if (reader.LocalName != "D" && !reader.ReadToFollowing("D")) { return null; } string d = reader.ReadElementContentAsString(); RSAPrivateKey privateKey = new RSAPrivateKey(); privateKey.Modulus = Convert.FromBase64String(modulus); privateKey.D = Convert.FromBase64String(d); return privateKey; } } catch { return null; } } } #endregion }
本文转载自:http://www.25175.com/200609/25175/25175_html/2010-12/4124.html