您的位置:首页 > 编程语言 > ASP

Asp.net程序实现RC6_中文加解密

2010-11-30 18:16 357 查看
  

最近笔者对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; //密码方法通过KEY属性返回值
private string m_sCryptedText; //加密解密字符串返回值
public int m_nChipherlen; //密码字节数,控制加密最低为128,最好256,间192,有三种选择种16,24,32
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;

}
/// <summary>
/// 加密方法
/// </summary>
/// <param name="str">加密的明文</param>
/// <param name="prssword">用户加密的密码</param>
/// <returns></returns>
public string Encrypt(string str, string prssword)
{
KEY = prssword; //用户密码,通过KEY属性写入
KeySteup(); //密码输入后与系统混合后成密钥

long len;
byte[] input;
using (MemoryStream obj = new MemoryStream(Encoding.Default.GetBytes(str))) //临时的MemoryStream流变量obj,完成循环后自行销毁
{
long temp = obj.Length;
temp = (temp % 16 != 0 ? temp + (16 - (obj.Length % 16)) : temp); obj.Close();//验证字符转换成字节byte其长度是否满足被16整除,不足长度补足长度,
/* 满足16个字节用ReadUInt32()方法转换为4个uint变量要求,以用于加密 */
len = temp; input = new byte[len];
byte[] Obj = obj.ToArray();
for (int i = 0; i < Obj.Length; i++) { input[i] = Obj[i]; }
}

MemoryStream Stream = new MemoryStream(input); //输入流容器
BinaryReader Br = new BinaryReader(Stream); //该对象是Stream的中间容器,俱有Read属性,及读取属性

uint[] r1 = new uint[Stream.Length / 4]; // //为什么这是input.Length/4;因为是从Br流中取出4个字节组成一个Uint的32位值
long UintLen = Stream.Length; //
int Len1 = 0;
while (UintLen > 0)
{ // //从流中读取字节转换Uint32
r1[Len1] = Br.ReadUInt32(); //从Br流中取出byte的四个字节值组成新Uint,并且1字节不移位,2字节左移位8位,3字节左移16位,4字节左移位24(所以这里简化了位移计算)
Len1++;
UintLen -= 4; //每次取4个字节后,总长度减4
} Br.Close(); Stream.Close();

MemoryStream bw = new MemoryStream(); //输出流容器
BinaryWriter Bw = new BinaryWriter(bw);//为bw的中间容器,俱有Write属性,及写入流属性

for (int i = 0; i < r1.Length; i += 4)
{
uint[] R1 = new uint[4];
uint[] R2 = new uint[4];

for (int z = 0; z < 4; z++) { R1[z] = r1[i+z];}

Encode(R1, R2);

for (int z = 0; z < 4; z++){ Bw.Write(R2[z]); }
} Bw.Close(); bw.Close();

return Convert.ToBase64String(bw.ToArray());// 从流bw转换成byte字节,以Base64String字符串的形式输出
}
/// <summary>
/// 解密函数返回解密的字符串
/// </summary>
/// <param name="str">待解密的密文</param>
/// <param name="prssword">用户解密的密码</param>
/// <returns></returns>
public string Decrypt(string str, string prssword)
{

KEY = prssword; //用户密码,通过KEY属性写入
KeySteup(); //密码输入后与系统混合后成密钥

long len;
byte[] input;
using (MemoryStream obj = new MemoryStream(Convert.FromBase64String(str))) //定义一个临时的MemoryStream流变量obj,与流输出的字符串还原为byte字节
{
long temp = obj.Length;
temp = (temp % 16 != 0 ? temp + (16 - (obj.Length % 16)) : temp); obj.Close();//验证字符转换成字节byte其长度是否满足被16整除,不足长度补足长度,
/* 满足16个字节用ReadUInt32()方法转换为4个uint变量要求,以用于解密 */
len = temp; input = new byte[len];
byte[] Obj = obj.ToArray();
for (int i = 0; i < Obj.Length; i++) { input[i] = Obj[i]; }
}

MemoryStream Stream = new MemoryStream(input); //输入流容器
BinaryReader Br = new BinaryReader(Stream); //该对象是Stream的中间容器,俱有Read属性,及读取属性

uint[] r1 = new uint[Stream.Length / 4]; // //从Br取出4个字节组成一个Uint的32位值
long UintLen = Stream.Length; // 字节总长度;
int Len1 = 0;
while (UintLen > 0)
{ // //从流中读取字节转换Uint32
r1[Len1] = Br.ReadUInt32(); //从Br流中取出byte的四个字节值组成新Uint,并且1字节不移位,2字节左移位8位,3字节左移16位,4字节左移位24(所以这里简化了位移计算)
Len1++; //自加1后再循环
UintLen -= 4; //每次取4个字节后,总长度减4
} Br.Close(); Stream.Close();

MemoryStream bw = new MemoryStream(); //输出流容器
BinaryWriter Bw = new BinaryWriter(bw);//为bw的中间容器,俱有Write属性,及写入流属性

for (int i = 0; i < r1.Length; i += 4)
{
uint[] R1 = new uint[4];
uint[] R2 = new uint[4];
for (int z = 0; z < 4; z++)
{ R1[z] = r1[i + z]; }

Decode(R1, R2);
for (int z = 0; z < 4; z++)
{ Bw.Write(R2[z]); }
} Bw.Close(); bw.Close();

return Encoding.Default.GetString(bw.ToArray()); ;

}

static void Main(string[] agrs)
{
RC6 obj = new RC6(32);
string str = "支持中文的RC6加密解程序abcdefghijklmnopqrstuvwxyz"; //明文
Console.WriteLine("加密前的明文是: {0}", str);
string pwd="*&^*&^%$@!$~`:;'///"; //用户密码
string str1=obj.Encrypt(str, pwd); //加密后的密文
Console.WriteLine("加密后的密后的密文是:{0}",str1);
string str2 = obj.Decrypt(str1, pwd); //解密后明文
Console.WriteLine("解密后的生成字符串是:{0}", str2);
Console.ReadKey();
}
}
}

第二: 在Asp运用:

前台程序:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="RC6_Web_Form._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>无标题页</title>
</head>
<body style="font-size:12px;">
<form id="form1" runat="server">
<div>
<table border="0" cellpadding="0" cellspacing="0" style="font-size:12px;">
<tr>
<td>明文区<br /><asp:TextBox ID="TextBox1" runat="server" Height="72px" TextMode="MultiLine"></asp:TextBox></td>
<td>选择加密方式<br /><asp:DropDownList ID="DropDownList1" runat="server" Width="156px" AutoPostBack="true">
<asp:ListItem>128位加密解密</asp:ListItem>
<asp:ListItem>192位加密解密</asp:ListItem>
<asp:ListItem>256位加密解密</asp:ListItem>
</asp:DropDownList><br /><br /><br />用户密码<br /><asp:TextBox ID="TextBox2" runat="server"></asp:TextBox></td>
<td><asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="加密" /><br /></td>
</tr>
</table>
</div>
<div>密文区<br />
<asp:TextBox ID="TextBox3" runat="server" Height="64px" TextMode="MultiLine" Width="336px"></asp:TextBox>
<asp:Button ID="Button2" runat="server" Text="解密" OnClick="Button2_Click" /><br />
解密结果:<br />
<asp:TextBox ID="TextBox4" runat="server" Height="80px" TextMode="MultiLine" Width="336px"></asp:TextBox></div>
</form>
</body>
</html>

后台程序:
添加类的引用,

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using MeStrBainRC6; //添加类引用
namespace RC6_Web_Form
{
public partial class _Default : System.Web.UI.Page
{
public int round;
protected void Page_Load(object sender, EventArgs e)
{

}

protected void Button1_Click(object sender, EventArgs e)
{
round=Return(this.DropDownList1);
MeStrBainRC6.RC6 obj = new MeStrBainRC6.RC6(round);

if (TextBox1.Text != null || TextBox2.Text != null)
{ TextBox3.Text = ""; TextBox3.Text = obj.Encrypt(TextBox1.Text, TextBox2.Text); }
TextBox2.Enabled = false; DropDownList1.Enabled = false;
TextBox4.Text = "";
}

protected void Button2_Click(object sender, EventArgs e)
{
round = Return(this.DropDownList1);
MeStrBainRC6.RC6 obj = new MeStrBainRC6.RC6(round);
if (TextBox3.Text != null || TextBox2.Text != null)
{ TextBox4.Text = ""; TextBox4.Text = obj.Decrypt(TextBox3.Text, TextBox2.Text); }
TextBox2.Enabled = true; DropDownList1.Enabled = true;
}
private int Return(DropDownList ojb)
{
string str = ojb.SelectedItem.Text;
switch (str)
{
case "128位加密解密": round = 16; break;
case "192位加密解密": round = 24; break;
case "256位加密解密": round = 32; break;
default: break;
}
return round;
}
}
}

以下程序运行情况:



以上程序在winform和webform上测试通过。

有什么好的建议和方法请大家提出来!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: