C#之RC6算法
http://www.oschina.net/code/snippet_222150_11967
[代码] [C#]代码
001 | #region |
002 | using System; |
003 | using System.Collections.Generic; |
004 | using System.Text; |
005 |
006 |
007 | namespace WindowsApplication1 |
008 | { |
009 |
010 | class RC6 |
011 | { |
012 | /// <summary> |
013 | /// 对称加解密算法RC6的C#实现 |
014 | /// 公开维普网_朱明海先生未公布的源码 |
015 | /// 程序完善设计者:四川威远_老耙子 先生 |
016 | /// 2010-11-28 |
017 | /// 本程序只提供了明文长度32的算法。 |
018 | /// 如有需要,请与本人联系。 |
019 | /// Mail:chscwyyg@163.com 电话:0832-8229211 |
020 | /// </summary> |
021 | private string m_sEncryptionKey; //密码方法通过KEY属性返回值 |
022 | public string m_sCryptedText; //加密解密字符串返回值 |
023 | private int m_nChipherlen; //密码字节数,控制加密最低为128,最好256,间192,有三种选择种16,24,32 |
024 | private const int m_nWord = 32; |
025 | private const int r = 20; |
026 | private const int c = 4; |
027 | private uint [] m_nKeyExpandBox; //系统密钥数组 |
028 | uint [] n_WordBox; //用户私有密钥 |
029 | public Encoding Enc_default = Encoding.Unicode; |
030 |
031 | /// <summary> |
032 | /// 左位移运算函数 |
033 | /// </summary> |
034 | /// <param name="x"></param> |
035 | /// <param name="y"></param> |
036 | /// <param name="w"></param> |
037 | /// <returns></returns> |
038 | /// |
039 | public uint ROTL( uint x, uint y, int w) |
040 | { return ((x << ( int )(y & (0xFF))) | (x >> ( int )(w - (y & (0xFF))))); } //或:return ((x << (int)(y & (w-1))) | (x >> (int)(w - (y & (w-1))))); |
041 |
042 | /// <summary> |
043 | /// 右位移运算函数 |
044 | /// </summary> |
045 | /// <param name="x"></param> |
046 | /// <param name="y"></param> |
047 | /// <param name="w"></param> |
048 | /// <returns></returns> |
049 | public uint ROTR( uint x, uint y, int w) |
050 | { return ((x >> ( int )(y & (0xFF))) | (x << ( int )(w - (y & (0xFF))))); } //或:return ((x >> (int)(y & (w-1))) | (x << (int)(w - (y & (w-1))))); |
051 |
052 | /// <summary> |
053 | /// 构造函数 |
054 | /// </summary> |
055 | public RC6() |
056 | { |
057 | IV = 16; //如果用户没有设置加密方式系统默认为128位加密 |
058 | // IV返回m_nChipherlen |
059 | m_nKeyExpandBox = new uint [8 * m_nChipherlen]; //密钥数组大小为加IV*8 |
060 | } |
061 | /// <summary> |
062 | /// 构造函数可输入加密向量 |
063 | /// </summary> |
064 | /// <param name="iv"></param> |
065 | public RC6( int iv) |
066 | { |
067 | IV = iv; //返顺 m_nChipherlen |
068 | this .m_nKeyExpandBox = new uint [8 * m_nChipherlen]; |
069 | } |
070 | /// <summary> |
071 | /// 定义一个属性,通过属性输入用户密钥并返回 |
072 | /// 存储到m_sEncryptionKey |
073 | /// </summary> |
074 | public string KEY |
075 | { |
076 | get { return this .m_sEncryptionKey; } |
077 | set { this .m_sEncryptionKey = value; } |
078 | } |
079 |
080 | /// <summary> |
081 | /// 加密向量选择 |
082 | /// 128方式IV=16 |
083 | /// 192方法IV=24 |
084 | /// 256方法IV=32 |
085 | /// </summary> |
086 | public int IV |
087 | { |
088 | get { return m_nChipherlen; } |
089 | set { m_nChipherlen = value; } |
090 | } |
091 |
092 | /// <summary> |
093 | /// 加密向量验证函数 |
094 | /// 有错误返回最小或最大的向量设置 |
095 | /// </summary> |
096 | /// <returns></returns> |
097 | public int _IV() |
098 | { |
099 | if (m_nChipherlen < 16) m_nChipherlen = 16; |
100 | if (m_nChipherlen > 32) m_nChipherlen = 32; |
101 | return m_nChipherlen; |
102 | } |
103 |
104 | /// <summary> |
105 | /// string类型Unicode字符集转为字节流char[]; |
106 | /// </summary> |
107 | /// <returns></returns> |
108 | private char [] String_Unicode() |
109 | { |
110 | string prssword = this .m_sEncryptionKey; |
111 | prssword = (prssword.Length % m_nChipherlen != 0 ? prssword.PadRight(prssword.Length + (m_nChipherlen - (prssword.Length % m_nChipherlen)), '/0' ) : prssword); |
112 |
113 | byte [] asciiBytes = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, Encoding.Unicode.GetBytes(prssword)); |
114 | char [] asciiChars = new char [Encoding.ASCII.GetCharCount(asciiBytes, 0, asciiBytes.Length)]; //等价=====char[] asciiChars = new char[asciiBytes.Length]; |
115 | Encoding.ASCII.GetChars(asciiBytes, 0, asciiBytes.Length, asciiChars, 0); |
116 | return asciiChars; |
117 | } |
118 |
119 |
120 | /// <summary> |
121 | /// 初始化函数用户密钥 |
122 | /// 通过KeySteup函数扩展并混合密钥 |
123 | /// </summary> |
124 | /// |
125 | private void KeySteup() |
126 | { |
127 | uint P32 = 0xb7e15163; |
128 | uint Q32 = 0x9e3779b9; |
129 | uint A, B; |
130 | A = B = 0; |
131 | int i, j; |
132 | i = j = 0; |
133 |
134 | char [] key = String_Unicode(); 密码类型转换,String型转换为char[],下面String_Unicode()函数返回值 |
135 |
136 | n_WordBox = new uint [m_nChipherlen/4]; //选择 16 or 24 or 32 128,192,256加密方式,4,6,8 |
137 | uint temp; |
138 |
139 |
140 | //密钥类型转换 string类型转换为uint |
141 | for (j = 0; j < m_nChipherlen; j++) //asciiChars[j]作0xFF运算,循环左移,如果 m_nChipherlen=32,第一轮不移位字节占位0-7,第二轮左移8位字节占位8-15, 第三轮位移16位,字节占16-23, |
142 | { //第四轮位移24位字节占位24-31.第四轮生成一个uint,共循环m_nChipherlen次生成m_nChipherlen/4个Uint, 16只生成4个,24生成6个,32生成8个,每个uint点32位, |
143 | // 所以加密的密节数==16时,4*32=加密128位,24时==6*32加密192位,32时==8*32加密256位,这里实现加密方式 |
144 | temp = ( uint )(key[j] & 0xFF) << (8 * (j % 4)); |
145 | n_WordBox[j / 4] += ( uint )temp; //循环四次生成一个uint |
146 |
147 | /* ========================================================说明位移运算方法===================================================================// |
148 | * 比方:a=97为01100001,0移位Convert.ToString(97, 2).PadLeft(8, '0'), |
149 | * b=98为01100010,左移8后变成占位0110001000000000=25088; |
150 | * c=99为01100011,左移16位变成占位011000110000000000000000=6488064 |
151 | * d=100为01100100,左移24变成占位01100100000000000000000000000000=1677721600 |
152 | * 以上abcd左移运算后是以下情况 |
153 | * abcd相加后变成了一个Uint数据占32字节等于Convert.ToString(100, 2).PadLeft(8, '0') + Convert.ToString(99, 2).PadLeft(8, '0') + |
154 | * Convert.ToString(98, 2).PadLeft(8, '0') + Convert.ToString(97, 2).PadLeft(8, '0'); |
155 | * a+b+c+d=1684234849,其字节为01100100011000110110001001100001;uint value=1684234849请验证下。 |
156 | * uint转换为字节 string x=Convert.ToString(uint value,2); |
157 | */ |
158 | } |
159 |
160 | //密钥扩展 m_nChipherLen=32 or 24 or 16 |
161 | this .m_nKeyExpandBox[0] = P32; //扩展密钥初始化,0位置赋值P32 |
162 | for (j = 1; j < 2 * m_nChipherlen + 4; j++) //m_nChipherlen是加密向量,反应加密方式128,192,256三种 |
163 | { this .m_nKeyExpandBox[j] = m_nKeyExpandBox[j - 1] + Q32; } |
164 |
165 | int k = 3 * Math.Max(n_WordBox.Length, 2 * m_nChipherlen + 4); |
166 | for (j = 0, i = 0; k > 0; k--) |
167 | { |
168 | A = ROTL(m_nKeyExpandBox[i] + A + B, 3, m_nWord); //混合密钥 |
169 | m_nKeyExpandBox[i] = ( byte )A; |
170 | B += A; |
171 | B = ROTL(n_WordBox[j] + A + B, A + B, m_nWord); //m_nKeyExpandBox[ii]的值混合到用户密钥中 |
172 | n_WordBox[j] = B; //这里是仍然是uint,生成新用户密码,32位值。提取见上面方法 [*** 1] |
173 | i = (i + 1) % (2 * m_nChipherlen + 4); //取模运算确保对应 m_nKeyExpandBox和 n_WordBox数组不越界 |
174 | j = (j + 1) % n_WordBox.Length; //n_WordBox.Length 分别代表 4,6,8 |
175 | } |
176 | } |
177 | // |
178 |
179 |
180 | /// <summary> |
181 | /// 加密函数 |
182 | /// </summary> |
183 | /// <param name="str">加密的明文</param> |
184 | /// <param name="prssword">返回的密文</param> |
185 | /// <returns></returns> |
186 | public string Encrypt( string str, string prssword) |
187 | { |
188 | str = (str.Length % 32 != 0 ? str.PadRight(str.Length + (32 - (str.Length % 32)), '/0' ) : str); //验证明文长度不能小开32,不足补空字符串 |
189 | KEY = prssword; //Key属性返回m_sEncryptionKey方法 |
190 | KeySteup(); //初始化 |
191 |
192 | uint A, B, C, D, T, U, temp; T = U = 0; //4个32位循环赋值的uint(A,B,C,D) |
193 | A = B = C = D = 0; |
194 | temp = 0; |
195 |
196 | byte [] input = Encoding.Unicode.GetBytes(str); // 输入的明文this.m_slnClearText;明文string为Unicode字符集,每个输入字符均为两字节16位 |
197 |
198 | //以Unicode转换Byte是byte[1]奇数值为0,偶数值为0,2,4,6等等为输入的字符十进制值,所以低位值才是要加密的值,高位不管它,因为它为0. |
199 | char [] chars = new char [Encoding.ASCII.GetCharCount(input, 0, input.Length)]; |
200 | Encoding.ASCII.GetChars(input, 0, input.Length, chars, 0); |
201 | byte [] output = new Byte[input.Length]; |
202 |
203 | // 加密的字符串不只128个字符情况该如何, 这需要定义byte多维数据才能实现 |
204 | for ( int k = 0; k < 4; k++) /* 输入明文要求为ASCII,将字节低位进行0xFF运算左移8*k位转换input(uint) */ |
205 | { |
206 | A += ( uint )(input[2 * k] & 0xFF) << (8 * k); //第一个元素不移位,填充uint0-7位,第二个左移8位填充8-15,第三个左移16位填充16-23位,第四个左移24位填充24-31位,这样组成一个uint |
207 | B += ( uint )(input[2 * k + 8] & 0xFF) << (8 * k); //第五个位元素填充uint32-39位,六个填充40-47位,七个填充48-55位,八个填充56-63位 |
208 | C += ( uint )(input[2 * k + 16] & 0xFF) << (8 * k); //第九个位元素填充uint64-71位,十个填充72-79位,十一个填充80-87位,十二个填充88-95位 |
209 | D += ( uint )(input[2 * k + 24] & 0xFF) << (8 * k); //第十三个位元素填充uint96-103位,十四个填充104-111位,十五个填充112-119位,十六个填充120-127位 |
210 | } |
211 |
212 | /* 扩展密钥数组n_LocExpandBox和A,B,C,D进行基本加密 |
213 | */ |
214 | //A,B,C,D变量循环赋值,第一次A,B,C,D第二次B,C,D,A,第三次C,D,A,B,以此类推,共循环m_nChipherlen-1次。 |
215 | B += m_nKeyExpandBox[0]; |
216 | D += m_nKeyExpandBox[1]; |
217 | for ( int i = 1; i <= m_nChipherlen; i++) //左移计算并位置换位,矩阵运算 |
218 | { |
219 | U = ROTL(D * (2 * D + 1), 5, m_nWord); //左移5位,这里其实m_nWord没有多少实用价值,因为本类未使用return ((x << (int)(y & (w-1))) | (x >> (int)(w - (y & (w-1))))) |
220 | T = ROTL(B * (2 * B + 1), 5, m_nWord); |
221 | A = ROTL(A ^ T, U, m_nWord) + m_nKeyExpandBox[2 * i]; |
222 | C = ROTL(C ^ U, T, m_nWord) + m_nKeyExpandBox[2 * i + 1]; |
223 | temp = A; //中间变量temp的值为A |
224 | A = B; //B的值赋值给A,就是B的位置移动到了A |
225 | B = C; //C的值赋值给B,就是C的位置移动到了B |
226 | C = D; //D的值赋值给C,就是D的位置移动到了C |
227 | D = temp; //A的值赋值给D,就是A的位置移动到了D |
228 | } |
229 |
230 | uint [] put = new uint [4]; |
231 |
232 | A += m_nKeyExpandBox[2 * r + 2]; |
233 | C += m_nKeyExpandBox[2 * r + 3]; |
234 |
235 | put[0] = A; |
236 | put[1] = B; |
237 | put[2] = C; |
238 | put[3] = D; |
239 |
240 | //转换A,B,C,D为一个字节组output,并进而转换为string型m_sCrytedText,下面是第一步的逆操作. |
241 | for ( int k = 0; k < 4; k++) |
242 | { |
243 | output[2 * k] = ( byte )((put[0] >> 8 * k) & 0xFF); |
244 | output[2 * k + 8] = ( byte )((put[1] >> 8 * k) & 0xFF); |
245 | output[2 * k + 16] = ( byte )((put[2] >> 8 * k) & 0xFF); |
246 | output[2 * k + 24] = ( byte )((put[3] >> 8 * k) & 0xFF); |
247 |
248 | } |
249 |
250 | char [] outarrchar = new char [output.Length]; |
251 | Encoding.Unicode.GetChars(output, 0, output.Length, outarrchar, 0); |
252 | this .m_sCryptedText = new string (outarrchar, 0, outarrchar.Length); |
253 | byte [] Output1 = Enc_default.GetBytes( this .m_sCryptedText); |
254 | //this.m_sEncryptionKey = ""; |
255 | return m_sCryptedText; |
256 | } |
257 | /// <summary> |
258 | /// 解密函数 |
259 | /// </summary> |
260 | /// <param name="str">解密的密文</param> |
261 | /// <param name="prssword">解密后的明文</param> |
262 | /// <returns></returns> |
263 | public string Decrypt( string str, string prssword) |
264 | { |
265 | str = (str.Length % 32 != 0 ? str.PadRight(str.Length + (32 - (str.Length % 32)), '/0' ) : str); //验证密文长度不能小开32,不足补空字符串 |
266 | KEY = prssword; //Key属性返回m_sEncryptionKey方法 |
267 | KeySteup(); //初始化 |
268 |
269 | uint A, B, C, D, T, U, temp; T = U = 0; //4个32位循环赋值的uint(A,B,C,D) |
270 | A = B = C = D = 0; |
271 | temp = 0; |
272 | byte [] input = Enc_default.GetBytes(str); // 输入的密文this.m_slnClearText;明文string为Unicode字符集,每个输入字符均为两字节16位 |
273 |
274 | byte [] output = new Byte[input.Length]; |
275 |
276 | for ( int k = 0; k < 4; k++) |
277 | { |
278 | A += (( uint )input[2 * k] & 0xFF) << (8 * k); |
279 | B += (( uint )input[2 * k + 8] & 0xFF) << (8 * k); |
280 | C += (( uint )input[2 * k + 16] & 0xFF) << (8 * k); |
281 | D += (( uint )input[2 * k + 24] & 0xFF) << (8 * k); |
282 |
283 | } |
284 |
285 | |
286 |
287 | C -= m_nKeyExpandBox[2 * r + 3]; |
288 | A -= m_nKeyExpandBox[2 * r + 2]; |
289 |
290 | for ( int i = 1; i <= m_nChipherlen; i++) |
291 | { |
292 | temp = D; |
293 | D = C; |
294 | C = B; |
295 | B = A; |
296 | A = temp; |
297 | U = ROTL(D * (2 * D + 1), 5, m_nWord); |
298 | T = ROTL(B * (2 * B + 1), 5, m_nWord); |
299 | C = ROTR(C - m_nKeyExpandBox[2 * (m_nChipherlen - i) + 3], T, m_nWord) ^ U; |
300 | A = ROTR(A - m_nKeyExpandBox[2 * (m_nChipherlen - i) + 2], U, m_nWord) ^ T; |
301 | } |
302 | D -= m_nKeyExpandBox[1]; |
303 | B -= m_nKeyExpandBox[0]; |
304 |
305 | //转换A,B,C,D为一个字节组output,并进而转换为string型m_sCrytedText,下面是第一步的逆操作. |
306 |
307 | |
308 |
309 | for ( int k = 0; k < 4; k++) |
310 | { |
311 | output[2 * k] = ( byte )((A >> (8 * k)) & 0xFF); |
312 | output[2 * k + 8] = ( byte )((B >> (8 * k)) & 0xFF); |
313 | output[2 * k + 16] = ( byte )((C >> (8 * k)) & 0xFF); |
314 | output[2 * k + 24] = ( byte )((D >> (8 * k)) & 0xFF); |
315 | } |
316 | char [] outarrchar = new char [Enc_default.GetCharCount(output, 0, output.Length)]; |
317 | Enc_default.GetChars(output, 0, output.Length, outarrchar, 0); |
318 | this .m_sCryptedText = new string (outarrchar, 0, outarrchar.Length); |
319 | byte [] Output1 = Enc_default.GetBytes( this .m_sCryptedText); |
320 | //this.m_sEncryptionKey = ""; |
321 | return m_sCryptedText; |
322 | } |
323 | } |
324 | } |
325 | #endregion |
326 |
327 | |
328 |
329 | using System; |
330 | using System.Collections.Generic; |
331 | using System.ComponentModel; |
332 | using System.Data; |
333 | using System.Drawing; |
334 | using System.Text; |
335 | using System.Windows.Forms; |
336 |
337 | namespace WindowsApplication1 |
338 | { |
339 | public partial class Form1 : Form |
340 | { |
341 | private int round; |
342 | public Form1() |
343 | { |
344 | InitializeComponent(); |
345 | } |
346 |
347 | private void button1_Click( object sender, EventArgs e) |
348 | { |
349 | if ( this .textBox1.Text == "" ) { MessageBox.Show( "请输入加密的明文" ); this .textBox1.Focus(); return ; } |
350 | if ( this .textBox3.Text == "" ) { MessageBox.Show( "请输入加密的密钥" ); this .textBox3.Focus(); return ; } |
351 | RC6 RC = new RC6(round); |
352 | //如果手动输入加密向量RC.IV = -1;请使用RC._IV():函数进行验证。 |
353 | |
354 | textBox2.Text = RC.Encrypt( this .textBox1.Text, this .textBox3.Text); |
355 | comboBox1.Enabled = false ; comboBox1.ForeColor = System.Drawing.SystemColors.WindowText; |
356 | textBox2.Enabled = false ; textBox2.ForeColor = System.Drawing.SystemColors.WindowText; |
357 | textBox3.Enabled = false ; textBox3.ForeColor = System.Drawing.SystemColors.WindowText; |
358 | } |
359 |
360 | private void comboBox1_SelectedIndexChanged( object sender, EventArgs e) |
361 | { |
362 | string str = this .comboBox1.Text; |
363 | switch (str) |
364 | { |
365 | case "128位加密" : round = 16; break ; |
366 | case "192位加密" : round = 24; break ; |
367 | case "256位加密" : round = 32; break ; |
368 | default : break ; |
369 | } |
370 | } |
371 |
372 | private void Form1_Load( object sender, EventArgs e) |
373 | { |
374 | comboBox1.SelectedIndex = 0; |
375 | } |
376 |
377 | private void button2_Click( object sender, EventArgs e) |
378 | { |
379 | RC6 RC = new RC6(round); |
380 | this .label6.Text = RC.Decrypt( this .textBox2.Text, this .textBox3.Text); |
381 | comboBox1.Enabled = true ; comboBox1.ForeColor = System.Drawing.SystemColors.WindowText; |
382 | textBox2.Enabled = true ; textBox2.ForeColor = System.Drawing.SystemColors.WindowText; |
383 | textBox3.Enabled = true ; textBox3.ForeColor = System.Drawing.SystemColors.WindowText; |
384 | } |
385 | } |
386 | } |