.NET中的RSA加解密

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

代码1
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算法。

代码如下: 

代码2
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



posted on 2011-08-23 19:23  程雨轩  阅读(1108)  评论(0编辑  收藏  举报

导航