Asp.net程序 RC6_实现中文加解密
最近笔者对RC6加解密进行了研究,对称加解密算法RC6的C#实现程序,源码在我的博客上:http://blog.csdn.net/ExcelWord/archive/2010/11/29/6041864.aspx,这只是对明文不超远32个ASCII字符的加解密,也不支持中文方法,通过今天的反复研究,终于实现了在winform和webform上的中文加密解密程序!
其源码如下:
新建的一个类:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace MeStrBainRC6
{
public class RC6
{
/// <summary>
/// 对称加解密算法RC6的C#中文实现
/// 公开维普网_朱明海先生未公布的源码
/// 程序完善设计者:四川威远_老耙子 先生
/// 2010-11-30
/// 如有需要,请与本人联系。
/// Mail:chscwyyg@163.com 电话:0832-8229211
/// </summary>
private string m_sEncryptionKey;
private string m_sCryptedText;
public int m_nChipherlen;
private const int m_nWord = 32;
private const int r = 20;
private const int c = 4;
private uint[] m_nKeyExpandBox;
uint[] n_WordBox;
public Encoding Enc_default = Encoding.Unicode;
/// <summary>
/// 左位移运算函数
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="w"></param>
/// <returns></returns>
///
public uint ROTL(uint x, uint y, int w)
{ return ((x << (int)(y & (0xFF))) | (x >> (int)(w - (y & (0xFF))))); }//或:return ((x << (int)(y & (w-1))) | (x >> (int)(w - (y & (w-1)))));
/// <summary>
/// 右位移运算函数
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="w"></param>
/// <returns></returns>
public uint ROTR(uint x, uint y, int w)
{ return ((x >> (int)(y & (0xFF))) | (x << (int)(w - (y & (0xFF))))); }//或:return ((x >> (int)(y & (w-1))) | (x << (int)(w - (y & (w-1)))));
/// <summary>
/// 构造函数
/// </summary>
public RC6()
{
IV = 16; //如果用户没有设置加密方式系统默认为128位加密
// IV返回m_nChipherlen
m_nKeyExpandBox = new uint[8 * m_nChipherlen]; //密钥数组大小为加IV*8
}
/// <summary>
/// 构造函数可输入加密向量
/// </summary>
/// <param name="iv"></param>
public RC6(int iv)
{
IV = iv; //返回 m_nChipherlen
_IV(); //验证用户输入的iv(m_nChipherlen)是否合法!
this.m_nKeyExpandBox = new uint[8 * m_nChipherlen];
}
/// <summary>
/// 定义一个属性,通过属性输入用户密钥并返回
/// 存储到m_sEncryptionKey
/// </summary>
public string KEY
{
get { return this.m_sEncryptionKey; }
set { this.m_sEncryptionKey = value; }
}
/// <summary>
/// 加密向量选择
/// 128方式IV=16
/// 192方法IV=24
/// 256方法IV=32
/// </summary>
public int IV
{
get { return m_nChipherlen; }
set { m_nChipherlen = value; }
}
/// <summary>
/// 加密向量验证函数
/// 有错误返回最小或最大的向量设置
/// </summary>
/// <returns></returns>
public int _IV()
{
if (m_nChipherlen < 16) m_nChipherlen = 16;
if (m_nChipherlen > 32) m_nChipherlen = 32;
return m_nChipherlen;
}
/// <summary>
/// string类型Unicode字符集转为字节流char[];
/// </summary>
/// <returns></returns>
private char[] String_Unicode()
{
string prssword = this.m_sEncryptionKey;
prssword = (prssword.Length % m_nChipherlen != 0 ? prssword.PadRight(prssword.Length + (m_nChipherlen - (prssword.Length % m_nChipherlen)), '\0') : prssword);
byte[] asciiBytes = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, Encoding.Unicode.GetBytes(prssword));
char[] asciiChars = new char[Encoding.ASCII.GetCharCount(asciiBytes, 0, asciiBytes.Length)]; //等价=====char[] asciiChars = new char[asciiBytes.Length];
Encoding.ASCII.GetChars(asciiBytes, 0, asciiBytes.Length, asciiChars, 0);
return asciiChars;
}
/// <summary>
/// 初始化函数用户密钥
/// 通过KeySteup函数扩展并混合密钥
/// </summary>
///
void KeySteup()
{
uint P32 = 0xb7e15163;
uint Q32 = 0x9e3779b9;
uint A, B;
A = B = 0;
int i, j;
i = j = 0;
char[] key = String_Unicode(); //密码类型转换,String型转换为char[],下面String_Unicode()函数返回值
n_WordBox = new uint[m_nChipherlen / 4]; //选择 16 or 24 or 32 128,192,256加密方式,4,6,8
uint temp;
//密钥类型转换 string类型转换为uint
for (j = 0; j < m_nChipherlen; j++)
{
temp = (uint)(key[j] & 0xFF) << (8 * (j % 4));
n_WordBox[j / 4] += (uint)temp; //循环四次生成一个uint
// 在BinaryReader中间流中,ReadUint32() 属性取代了上属循环生成一个UInt32对象,因此BinaryReader.ReadUInt32();更简单,
//之所以RC6未获胜的原因之一
}
//密钥扩展 m_nChipherLen=32 or 24 or 16
this.m_nKeyExpandBox[0] = P32; //扩展密钥初始化,0位置赋值P32
for (j = 1; j < 2 * m_nChipherlen + 4; j++) //m_nChipherlen是加密向量,反应加密方式128,192,256三种
{ this.m_nKeyExpandBox[j] = m_nKeyExpandBox[j - 1] + Q32; }
int k = 3 * Math.Max(n_WordBox.Length, 2 * m_nChipherlen + 4);
for (j = 0, i = 0; k > 0; k--)
{
A = ROTL(m_nKeyExpandBox[i] + A + B, 3, m_nWord); //混合密钥
m_nKeyExpandBox[i] = (byte)A;
B += A;
B = ROTL(n_WordBox[j] + A + B, A + B, m_nWord); //m_nKeyExpandBox[ii]的值混合到用户密钥中
n_WordBox[j] = B; //这里是仍然是uint,生成新用户密码,32位值。提取见上面方法 [*** 1]
i = (i + 1) % (2 * m_nChipherlen + 4); //取模运算确保对应 m_nKeyExpandBox和 n_WordBox数组不越界
j = (j + 1) % n_WordBox.Length; //n_WordBox.Length 分别代表 4,6,8
}
}
/// <summary>
/// 加密UInt32数组
/// 加密前必须将明文转换为32位的uint[],r1
/// 通过该函数r1与密钥进行混合输出uint[],r2
/// </summary>
/// <param name="r1">加密前的UInt32数组</param>
/// <param name="r2">加密后的UInt32数组</param>
void Encode(uint[] r1, uint[] r2)
{
uint A, B, C, D, U, T, temp;
A = r1[0];
B = r1[1];
C = r1[2];
D = r1[3];
U = T = temp = 0;
B += m_nKeyExpandBox[0];
D += m_nKeyExpandBox[1];
for (int j = 1; j <= m_nChipherlen; j++) //左移计算并位置换位,矩阵运算
{
U = ROTL(D * (2 * D + 1), 5, m_nWord); //左移5位,这里其实m_nWord没有多少实用价值,因为本类未使用return ((x << (int)(y & (w-1))) | (x >> (int)(w - (y & (w-1)))))
T = ROTL(B * (2 * B + 1), 5, m_nWord);
A = ROTL(A ^ T, U, m_nWord) + m_nKeyExpandBox[2 * j];
C = ROTL(C ^ U, T, m_nWord) + m_nKeyExpandBox[2 * j + 1];
temp = A; //中间变量temp的值为A
A = B; //B的值赋值给A,就是B的位置移动到了A
B = C; //C的值赋值给B,就是C的位置移动到了B
C = D; //D的值赋值给C,就是D的位置移动到了C
D = temp; //A的值赋值给D,就是A的位置移动到了D
}
A += m_nKeyExpandBox[2 * r + 2];
C += m_nKeyExpandBox[2 * r + 3];
r2[0] = A;
r2[1] = B;
r2[2] = C;
r2[3] = D;
}
/// <summary>
/// 解密UInt32数组
/// 解密前必须将密文转换为32位的uint[],r1
/// 通过该函数r1与密钥混合输出解密后uint[],r2
/// </summary>
/// <param name="r1"></param>
/// <param name="r2"></param>
void Decode(uint[] r1, uint[] r2)
{
uint A, B, C, D, T, U, temp; T = U = 0; //4个32位循环赋值的uint(A,B,C,D)
A = B = C = D = 0;
temp = 0;
A = r1[0];
B = r1[1];
C = r1[2];
D = r1[3];
C -= m_nKeyExpandBox[2 * r + 3];
A -= m_nKeyExpandBox[2 * r + 2];
for (int j = 1; j <= m_nChipherlen; j++)
{
temp = D;
D = C;
C = B;
B = A;
A = temp;
U = ROTL(D * (2 * D + 1), 5, m_nWord);
T = ROTL(B * (2 * B + 1), 5, m_nWord);
C = ROTR(C - m_nKeyExpandBox[2 * (m_nChipherlen - j) + 3], T, m_nWord) ^ U;
A = ROTR(A - m_nKeyExpandBox[2 * (m_nChipherlen - j) + 2], U, m_nWord) ^ T;
}
D -= m_nKeyExpandBox[1];
B -= m_nKeyExpandBox[0];
r2[0] = A;
r2[1] = B;
r2[2] = C;
r2[3] = D;
}