C# RSACryptoServiceProvider类实现RSA(非对称加密)算法(RSAHelper)

分类:.Net知识问答| 发布:llmaomi| 查看:767 | 发表时间:2015/3/7

1.首先介绍下什么是RSA算法,让大家对RSA算法有个简要的理解.
   RSA算法非常简单,概述如下:
找两素数p和q
取n=p*q  如:n=3*7=21
取t=(p-1)*(q-1) 如:t = 2*6 = 12
   取任何一个数e,要求满足e 
取d*e%t==1  如:d=7,e=7,则7*7/12刚好等于1满足要求
这样最终得到三个数: n d e,即 n=21,d=7,e=7
设消息为数M 
设c=(M**d)%n就得到了加密后的消息c
设m=(c**e)%n则 m == M,从而完成对c的解密。
注:**表示次方,上面两式中的d和e可以互换。
 
在对称加密中:
n d两个数构成公钥,可以告诉别人;
n e两个数构成私钥,e自己保留,不让任何人知道。
给别人发送的信息使用e加密,只要别人能用d解开就证明信息是由你发送的,构成了签名机制。
别人给你发送信息时使用d加密,这样只有拥有e的你能够对其解密。
rsa的安全性在于对于一个大数n,没有有效的方法能够将其分解从而在已知n d的情况无法获得e;同样在已知n e的情况下无法求得d。
 
2.上面就是对RSA算法的一个简要概括,该描述在很多书本上都有介绍,这里也就不做过多解释了,下面我们看下在.net 里面如何实现该算法.
   在.net 里面,有一个叫RSACryptoServiceProvider的类,在MSDN中,我们可以了解到该类使用加密服务提供程序 (CSP) 提供的rsa算法的实现,执行不对称加密和解密,从继承关系上我们了解到该类继承自RSA类.通过该类,我们可以导出加密解密所需要的XML信息,并且能够根据我们提供的XML信息进行加密解密计算,下面是对该类的一些具体操作,主要包括如何导出密钥,如何用形成的密钥进行加密和解密,完成我们一般的操作.

001   public class Cyh_RSA
002    {
003        public Cyh_RSA()
004        
005             
006        }
007  
008        /// <summary>
009        /// 加密
010        /// </summary>
011        /// <param name="p_inputString">需要加密的字符串信息</param>
012        /// <param name="p_strKeyPath">加密用的密钥所在的路径(*.cyh_publickey)</param>
013        /// <returns>加密以后的字符串信息</returns>
014        public string Encrypt(string p_inputString, string p_strKeyPath)
015        {
016            string fileString = null;
017            string outString = null;
018            if (File.Exists(p_strKeyPath))
019            {
020                StreamReader streamReader = new StreamReader(p_strKeyPath, true);
021                fileString = streamReader.ReadToEnd();
022                streamReader.Close();
023  
024            }
025  
026            if (fileString != null)
027            {
028                string bitStrengthString = fileString.Substring(0, fileString.IndexOf("</BitStrength>") + 14);
029                fileString = fileString.Replace(bitStrengthString, "");
030                int bitStrength = Convert.ToInt32(bitStrengthString.Replace("<BitStrength>", "").Replace("</BitStrength>", ""));
031                try
032                {
033                    outString = EncryptString(p_inputString, bitStrength, fileString);
034                }
035                catch (Exception Ex)
036                {
037                    MessageBox.Show("出错: \n" + Ex.Message);
038                }
039  
040            }
041  
042            return outString;
043        }
044        /// <summary>
045        /// 解密
046        /// </summary>
047        /// <param name="p_inputString">需要解密的字符串信息</param>
048        /// <param name="p_strKeyPath">解密用的密钥所在的路径(*.cyh_primarykey)</param>
049        /// <returns>解密以后的字符串信息</returns>
050        public string Decrypt(string p_inputString, string p_strKeyPath)
051        {
052            string fileString = null;
053            string outString = null;
054            if (File.Exists(p_strKeyPath))
055            {
056                StreamReader streamReader = new StreamReader(p_strKeyPath, true);
057                fileString = streamReader.ReadToEnd();
058                streamReader.Close();
059  
060            }
061  
062            if (fileString != null)
063            {
064                string bitStrengthString = fileString.Substring(0, fileString.IndexOf("</BitStrength>") + 14);
065                fileString = fileString.Replace(bitStrengthString, "");
066                int bitStrength = Convert.ToInt32(bitStrengthString.Replace("<BitStrength>", "").Replace("</BitStrength>", ""));
067                try
068                {
069                    outString = DecryptString(p_inputString, bitStrength, fileString);
070                }
071                catch (Exception Ex)
072                {
073                    MessageBox.Show("出错: \n" + Ex.Message);
074                }
075  
076            }
077  
078            return outString;
079  
080        }
081  
082        /// <summary>
083        /// 加密
084        /// </summary>
085        /// <param name="p_inputString">需要加密的字符串</param>
086        /// <param name="p_dwKeySize">密钥的大小</param>
087        /// <param name="p_xmlString">包含密钥的XML文本信息</param>
088        /// <returns>加密后的文本信息</returns>
089        private string EncryptString(string p_inputString, int p_dwKeySize, string p_xmlString)
090        {
091            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider(p_dwKeySize);
092            rsaCryptoServiceProvider.FromXmlString(p_xmlString);
093            int keySize = p_dwKeySize / 8;
094            byte[] bytes = Encoding.UTF32.GetBytes(p_inputString);
095            int maxLength = keySize - 42;
096            int dataLength = bytes.Length;
097            int iterations = dataLength / maxLength;
098            StringBuilder stringBuilder = new StringBuilder();
099            for (int i = 0; i <= iterations; i++)
100            {
101                byte[] tempBytes = new byte[(dataLength - maxLength * i > maxLength) ? maxLength : dataLength - maxLength * i];
102                Buffer.BlockCopy(bytes, maxLength * i, tempBytes, 0, tempBytes.Length);
103                byte[] encryptedBytes = rsaCryptoServiceProvider.Encrypt(tempBytes, true);
104                Array.Reverse(encryptedBytes);
105                stringBuilder.Append(Convert.ToBase64String(encryptedBytes));
106            }
107            return stringBuilder.ToString();
108        }
109  
110        /// <summary>
111        /// 解密
112        /// </summary>
113        /// <param name="p_inputString">需要解密的字符串信息</param>
114        /// <param name="p_dwKeySize">密钥的大小</param>
115        /// <param name="p_xmlString">包含密钥的文本信息</param>
116        /// <returns>解密后的文本信息</returns>
117        private string DecryptString(string inputString, int dwKeySize, string xmlString)
118        {
119            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider(dwKeySize);
120            rsaCryptoServiceProvider.FromXmlString(xmlString);
121            int base64BlockSize = ((dwKeySize / 8) % 3 != 0) ? (((dwKeySize / 8) / 3) * 4) + 4 : ((dwKeySize / 8) / 3) * 4;
122            int iterations = inputString.Length / base64BlockSize;
123            ArrayList arrayList = new ArrayList();
124            for (int i = 0; i < iterations; i++)
125            {
126                byte[] encryptedBytes = Convert.FromBase64String(inputString.Substring(base64BlockSize * i, base64BlockSize));
127                Array.Reverse(encryptedBytes);
128                arrayList.AddRange(rsaCryptoServiceProvider.Decrypt(encryptedBytes, true));
129            }
130            return Encoding.UTF32.GetString(arrayList.ToArray(Type.GetType("System.Byte")) as byte[]);
131        }
132  
133        /// <summary>
134        /// 形成并保存公开密钥和私有密钥
135        /// </summary>
136        /// <param name="p_currentBitStrength">密钥大小</param>
137        public void SaveKey(int p_currentBitStrength)
138        {
139            RSACryptoServiceProvider RSAProvider = new RSACryptoServiceProvider(p_currentBitStrength);
140            string publicAndPrivateKeys = "<BitStrength>" + p_currentBitStrength.ToString() + "</BitStrength>" + RSAProvider.ToXmlString(true);
141            string justPublicKey = "<BitStrength>" + p_currentBitStrength.ToString() + "</BitStrength>" + RSAProvider.ToXmlString(false);
142            if (saveFile("Save Public/Private Keys As", "Public/Private Keys Document( *.cyh_primarykey )|*.cyh_primarykey", publicAndPrivateKeys))
143            { while (!saveFile("Save Public Key As", "Public Key Document( *.cyh_publickey )|*.cyh_publickey", justPublicKey)) { ; } }
144        }
145  
146        /// <summary>
147        /// 保存信息
148        /// </summary>
149        /// <param name="p_title">标题</param>
150        /// <param name="p_filterString">过滤条件</param>
151        /// <param name="p_outputString">输出内容</param>
152        /// <returns>是否成功</returns>
153        private bool saveFile(string p_title, string p_filterString, string p_outputString)
154        {
155            SaveFileDialog saveFileDialog = new SaveFileDialog();
156            saveFileDialog.Title = p_title;
157            saveFileDialog.Filter = p_filterString;
158            saveFileDialog.FileName = "";
159            if (saveFileDialog.ShowDialog() == DialogResult.OK)
160            {
161                try
162                {
163                    StreamWriter streamWriter = new StreamWriter(saveFileDialog.FileName, false);
164                    if (p_outputString != null)
165                    { streamWriter.Write(p_outputString); }
166                    streamWriter.Close();
167                    return true;
168                }
169                catch (Exception Ex)
170                {
171                    Console.WriteLine(Ex.Message);
172                    return false;
173                }
174            }
175            return false;
176        }
177    }


这样,您在任何地方都可以使用该类对数据进行加密和解密,并且操作相当方便,如:
生成密钥:

1 Cyh_RSA rsa = new Cyh_RSA();
2 rsa.SaveKey(1024);


加密:

1Cyh_RSA rsa = new Cyh_RSA();
2rsa.Encrypt("需要加密的内容", "包含密钥的路径");


解密:

1Cyh_RSA rsa = new Cyh_RSA();
2rsa.Decrypt("需要解密的内容", "包含密钥的路径");
365据说看到好文章不转的人,服务器容易宕机
原创文章如转载,请注明:转载自郑州网建-前端开发 http://camnpr.com/
本文链接:http://camnpr.com/net-wiki/1938.html