C#之RC6算法

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 stringm_sEncryptionKey;                                             //密码方法通过KEY属性返回值
022         public stringm_sCryptedText;                                                //加密解密字符串返回值
023         private intm_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 = newchar[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                 defaultbreak;
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 }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值