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信息进行加密解密计算,下面是对该类的一些具体操作,主要包括如何导出密钥,如何用形成的密钥进行加密和解密,完成我们一般的操作.
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) |
016 | string fileString = null ; |
017 | string outString = null ; |
018 | if (File.Exists(p_strKeyPath)) |
020 | StreamReader streamReader = new StreamReader(p_strKeyPath, true ); |
021 | fileString = streamReader.ReadToEnd(); |
022 | streamReader.Close(); |
026 | if (fileString != null ) |
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>" , "" )); |
033 | outString = EncryptString(p_inputString, bitStrength, fileString); |
037 | MessageBox.Show( "出错: \n" + Ex.Message); |
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) |
052 | string fileString = null ; |
053 | string outString = null ; |
054 | if (File.Exists(p_strKeyPath)) |
056 | StreamReader streamReader = new StreamReader(p_strKeyPath, true ); |
057 | fileString = streamReader.ReadToEnd(); |
058 | streamReader.Close(); |
062 | if (fileString != null ) |
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>" , "" )); |
069 | outString = DecryptString(p_inputString, bitStrength, fileString); |
073 | MessageBox.Show( "出错: \n" + Ex.Message); |
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) |
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++) |
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)); |
107 | return stringBuilder.ToString(); |
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) |
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++) |
126 | byte [] encryptedBytes = Convert.FromBase64String(inputString.Substring(base64BlockSize * i, base64BlockSize)); |
127 | Array.Reverse(encryptedBytes); |
128 | arrayList.AddRange(rsaCryptoServiceProvider.Decrypt(encryptedBytes, true )); |
130 | return Encoding.UTF32.GetString(arrayList.ToArray(Type.GetType( "System.Byte" )) as byte []); |
136 | /// <param name="p_currentBitStrength">密钥大小</param> |
137 | public void SaveKey( int p_currentBitStrength) |
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)) { ; } } |
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) |
155 | SaveFileDialog saveFileDialog = new SaveFileDialog(); |
156 | saveFileDialog.Title = p_title; |
157 | saveFileDialog.Filter = p_filterString; |
158 | saveFileDialog.FileName = "" ; |
159 | if (saveFileDialog.ShowDialog() == DialogResult.OK) |
163 | StreamWriter streamWriter = new StreamWriter(saveFileDialog.FileName, false ); |
164 | if (p_outputString != null ) |
165 | { streamWriter.Write(p_outputString); } |
166 | streamWriter.Close(); |
171 | Console.WriteLine(Ex.Message); |
这样,您在任何地方都可以使用该类对数据进行加密和解密,并且操作相当方便,如:
生成密钥:
1 | Cyh_RSA rsa = new Cyh_RSA(); |
加密:
1 | Cyh_RSA rsa = new Cyh_RSA(); |
2 | rsa.Encrypt( "需要加密的内容" , "包含密钥的路径" ); |
解密:
1 | Cyh_RSA rsa = new Cyh_RSA(); |
2 | rsa.Decrypt( "需要解密的内容" , "包含密钥的路径" ); |