using system;
using system.security.cryptography;
using system.text;
using system.io;
using system.windows.forms;
namespace curllion
{
public class crypt
{
private byte[] key;
private byte[] iv;
private system.text.asciiencoding asciiencoding;
private system.text.unicodeencoding textconverter;
private rc2cryptoserviceprovider rc2csp;
public crypt()
{
initializecomponent();
}
private void initializecomponent()
{
key = new byte[]{106,51,25,141,157,142,23,111,234,159,187,154,215,34,37,204};
iv = new byte[]{135,186,133,136,184,149,153,144};
asciiencoding = new system.text.asciiencoding();
textconverter = new system.text.unicodeencoding();
rc2csp = new rc2cryptoserviceprovider();
}
/// <summary>
/// 新建一个大小为10261b的文件,以便将加密数据写入固定大小的文件。
/// </summary>
/// <param name="filepath">文件保存的地址,包含文件名</param>
public void initbinfile(string filepath)
{
byte[] tmp = new byte[10261];
try //创建文件流,将其内容全部写入0
{
system.io.filestream writefilestream = new filestream(filepath,
system.io.filemode.create,
system.io.fileaccess.write,
system.io.fileshare.none,512,false);
for(int i = 0 ;i< 10261;i++)
tmp[i] = 0;
writefilestream.write(tmp,0,10261);
writefilestream.flush();
writefilestream.close();
}
catch(system.io.ioexception)
{
messagebox.show("文件操作错误!","错误!",messageboxbuttons.ok,messageboxicon.error);
}
}
/// <summary>
/// 将文本数据加密后写入一个文件,其中,这个文件是用initbinfile建立的,这个文件将被分成十块,
/// 用来分别保存10组不同的数据,第一个byte位保留,第2位到第21位分别用来存放每块数据的长度,但
/// 一个byte的取值为0-127,所以,用两个byte来存放一个长度。
/// </summary>
/// <param name="toencrypttext">要加密的文本数据</param>
/// <param name="filepath">要写入的文件</param>
/// <param name="dataindex">写入第几块,取值为1–10</param>
/// <returns>是否操作成功</returns>
public bool encrypttofile(string toencrypttext,string filepath,int dataindex)
{
bool r = false;
if(dataindex > 10 && dataindex < 1)
{
messagebox.show("数据索引的取值范围在1至10之间!","错误!",
messageboxbuttons.ok,messageboxicon.error);
return r;
}
byte[] encrypted;
//打开要写入的文件,主要是为了保持原文件的内容不丢失
system.io.filestream tmpfilestream= new filestream(filepath,
system.io.filemode.open,
system.io.fileaccess.read,
system.io.fileshare.none,1024,true);
byte[] index = new byte[10261];
//将读取的内容写到byte数组
tmpfilestream.read(index,0,10261);
tmpfilestream.close();
//定义基本的加密转换运算
system.security.cryptography.icryptotransform encryptor = rc2csp.createencryptor(this.key,this.iv);
system.io.memorystream msencrypt = new memorystream();
//在此加密转换流中,加密将从csencrypt,加密后,结果在msencrypt流中。
system.security.cryptography.cryptostream csencrypt = new cryptostream(msencrypt,
encryptor,cryptostreammode.write);
//将要加密的文本转换成utf-16 编码,保存在tmp数组。
byte[] tmp = textconverter.getbytes(toencrypttext);
//将tmp输入csencrypt,将通过encryptor来加密。
csencrypt.write(tmp,0,tmp.length);
//输出到msenctypt
csencrypt.flushfinalblock();
//将流转成byte[]
encrypted = msencrypt.toarray();
if(encrypted.length>1024)
{
messagebox.show("加密后,数据长度大于1kb,无法保存");
return false;
}
//得到加密后数据的大小,将结果存在指定的位置。
index[dataindex*2 – 1] = convert.tobyte(convert.tostring(encrypted.length/128));
index[dataindex*2] = convert.tobyte(convert.tostring(encrypted.length%128));
//将加密后的结果写入index(覆盖)
for(int i=0;i<encrypted.length;i++)
index[1024*(dataindex-1)+21+i]=encrypted[i];
//建立文件流
tmpfilestream = new filestream(filepath,
system.io.filemode.truncate,
system.io.fileaccess.write,
system.io.fileshare.none,1024,true);
//写文件
tmpfilestream.write(index,0,10261);
tmpfilestream.flush();
r = true;
tmpfilestream.close();
return r;
}
/// <summary>
/// 从一个文件中解密出一段文本,其中,这个文件是由initbinfile建立的,并且由 encrypttofile加密的
/// </summary>
/// <param name="filepath">要解密的文件</param>
/// <param name="dataindex">要从哪一个块中解密</param>
/// <returns>解密后的文本</returns>
public string decryptfromfile(string filepath,int dataindex)
{
string r = "";
if(dataindex > 10 && dataindex < 1)
{
messagebox.show("数据索引的取值范围在1至10之间!","错误!",
messageboxbuttons.ok,messageboxicon.error);
return r;
}
byte[] decrypted;
system.io.filestream tmpfilestream = new filestream(filepath,
system.io.filemode.open,
system.io.fileaccess.read,
system.io.fileshare.none,1024,true);
system.security.cryptography.icryptotransform decryptor = rc2csp.createdecryptor(this.key,this.iv);
system.io.memorystream msdecrypt = new memorystream();
system.security.cryptography.cryptostream csdecrypt = new cryptostream(msdecrypt,
decryptor,cryptostreammode.write);
byte[] index = new byte[10261];
tmpfilestream.read(index,0,10261);
int startindex = 1024*(dataindex-1)+21;
int count = index[dataindex*2 – 1]*128 + index[dataindex*2];
byte[] tmp = new byte[count];
array.copy(index,1024*(dataindex-1)+21,tmp,0,count);
csdecrypt.write(tmp,0,count);
csdecrypt.flushfinalblock();
decrypted = msdecrypt.toarray();
r = textconverter.getstring(decrypted,0,decrypted.length);
tmpfilestream.close();
return r;
}
/// <summary>
/// 将一段文本加密后保存到一个文件
/// </summary>
/// <param name="toencrypttext">要加密的文本数据</param>
/// <param name="filepath">要保存的文件</param>
/// <returns>是否加密成功</returns>
public bool encrypttofile(string toencrypttext,string filepath)
{
bool r = false;
byte[] encrypted;
system.io.filestream tmpfilestream = new filestream(filepath,
system.io.filemode.openorcreate,
system.io.fileaccess.write,
system.io.fileshare.none,1024,true);
system.security.cryptography.icryptotransform encryptor = rc2csp.createencryptor(this.key,this.iv);
system.io.memorystream msencrypt = new memorystream();
system.security.cryptography.cryptostream csencrypt = new cryptostream(msencrypt,
encryptor,cryptostreammode.write);
byte[] tmp = textconverter.getbytes(toencrypttext);
csencrypt.write(tmp,0,tmp.length);
csencrypt.flushfinalblock();
encrypted = msencrypt.toarray();
tmpfilestream.write(encrypted,0,encrypted.length);
tmpfilestream.flush();
r = true;
tmpfilestream.close();
return r;
}
/// <summary>
/// 将一个被加密的文件解密
/// </summary>
/// <param name="filepath">要解密的文件</param>
/// <returns>解密后的文本</returns>
public string decryptfromfile(string filepath)
{
string r = "";
byte[] decrypted;
system.io.filestream tmpfilestream = new filestream(filepath,
system.io.filemode.open,
system.io.fileaccess.read,
system.io.fileshare.none,1024,true);
system.security.cryptography.icryptotransform decryptor = rc2csp.createdecryptor(this.key,this.iv);
system.io.memorystream msdecrypt = new memorystream();
system.security.cryptography.cryptostream csdecrypt = new cryptostream(msdecrypt,
decryptor,cryptostreammode.write);
byte[] tmp = new byte[tmpfilestream.length];
tmpfilestream.read(tmp,0,tmp.length);
csdecrypt.write(tmp,0,tmp.length);
csdecrypt.flushfinalblock();
decrypted = msdecrypt.toarray();
r = textconverter.getstring(decrypted,0,decrypted.length);
tmpfilestream.close();
return r;
}
//————————————————————-
/// <summary>
/// 将文本数据加密后写入一个文件,其中,这个文件是用initbinfile建立的,这个文件将被分成十块,
/// 用来分别保存10组不同的数据,第一个byte位保留,第2位到第21位分别用来存放每块数据的长度,但
/// 一个byte的取值为0-127,所以,用两个byte来存放一个长度。
/// </summary>
/// <param name="toencrypttext">要加密的文本数据</param>
/// <param name="filepath">要写入的文件</param>
/// <param name="dataindex">写入第几块,取值为1–10</param>
/// <param name="iv">初始化向量</param>
/// <param name="key">加密密匙</param>
/// <returns>是否操作成功</returns>
public bool encrypttofile(string toencrypttext,string filepath,int dataindex,byte[] iv,byte[] key)
{
bool r = false;
if(dataindex > 10 && dataindex < 1)
{
messagebox.show("数据索引的取值范围在1至10之间!","错误!",
messageboxbuttons.ok,messageboxicon.error);
return r;
}
byte[] encrypted;
//打开要写入的文件,主要是为了保持原文件的内容不丢失
system.io.filestream tmpfilestream= new filestream(filepath,
system.io.filemode.open,
system.io.fileaccess.read,
system.io.fileshare.none,1024,true);
byte[] index = new byte[10261];
//将读取的内容写到byte数组
tmpfilestream.read(index,0,10261);
tmpfilestream.close();
//定义基本的加密转换运算
system.security.cryptography.icryptotransform encryptor = rc2csp.createencryptor(key,iv);
system.io.memorystream msencrypt = new memorystream();
//在此加密转换流中,加密将从csencrypt,加密后,结果在msencrypt流中。
system.security.cryptography.cryptostream csencrypt = new cryptostream(msencrypt,
encryptor,cryptostreammode.write);
//将要加密的文本转换成utf-16 编码,保存在tmp数组。
byte[] tmp = textconverter.getbytes(toencrypttext);
//将tmp输入csencrypt,将通过encryptor来加密。
csencrypt.write(tmp,0,tmp.length);
//输出到msenctypt
csencrypt.flushfinalblock();
//将流转成byte[]
encrypted = msencrypt.toarray();
if(encrypted.length>1024)
{
messagebox.show("加密后,数据长度大于1kb,无法保存");
return false;
}
//得到加密后数据的大小,将结果存在指定的位置。
index[dataindex*2 – 1] = convert.tobyte(convert.tostring(encrypted.length/128));
index[dataindex*2] = convert.tobyte(convert.tostring(encrypted.length%128));
//将加密后的结果写入index(覆盖)
for(int i=0;i<encrypted.length;i++)
index[1024*(dataindex-1)+21+i]=encrypted[i];
//建立文件流
tmpfilestream = new filestream(filepath,
system.io.filemode.truncate,
system.io.fileaccess.write,
system.io.fileshare.none,1024,true);
//写文件
tmpfilestream.write(index,0,10261);
tmpfilestream.flush();
r = true;
tmpfilestream.close();
return r;
}
/// <summary>
/// 从一个文件中解密出一段文本,其中,这个文件是由initbinfile建立的,并且由 encrypttofile加密的
/// </summary>
/// <param name="filepath">要解密的文件</param>
/// <param name="dataindex">要从哪一个块中解密</param>
/// <param name="iv">初始化向量</param>
/// <param name="key">解密密匙</param>
/// <returns>解密后的文本</returns>
public string decryptfromfile(string filepath,int dataindex,byte[] iv,byte[] key)
{
string r = "";
if(dataindex > 10 && dataindex < 1)
{
messagebox.show("数据索引的取值范围在1至10之间!","错误!",
messageboxbuttons.ok,messageboxicon.error);
return r;
}
byte[] decrypted;
system.io.filestream tmpfilestream = new filestream(filepath,
system.io.filemode.open,
system.io.fileaccess.read,
system.io.fileshare.none,1024,true);
system.security.cryptography.icryptotransform decryptor = rc2csp.createdecryptor(key,iv);
system.io.memorystream msdecrypt = new memorystream();
system.security.cryptography.cryptostream csdecrypt = new cryptostream(msdecrypt,
decryptor,cryptostreammode.write);
byte[] index = new byte[10261];
tmpfilestream.read(index,0,10261);
int startindex = 1024*(dataindex-1)+21;
int count = index[dataindex*2 – 1]*128 + index[dataindex*2];
byte[] tmp = new byte[count];
array.copy(index,1024*(dataindex-1)+21,tmp,0,count);
csdecrypt.write(tmp,0,count);
csdecrypt.flushfinalblock();
decrypted = msdecrypt.toarray();
r = textconverter.getstring(decrypted,0,decrypted.length);
tmpfilestream.close();
return r;
}
/// <summary>
/// 将一段文本加密后保存到一个文件
/// </summary>
/// <param name="toencrypttext">要加密的文本数据</param>
/// <param name="filepath">要保存的文件</param>
/// <param name="iv">初始化向量</param>
/// <param name="key">加密密匙</param>
/// <returns>是否加密成功</returns>
public bool encrypttofile(string toencrypttext,string filepath,byte[] iv,byte[] key)
{
bool r = false;
byte[] encrypted;
system.io.filestream tmpfilestream = new filestream(filepath,
system.io.filemode.openorcreate,
system.io.fileaccess.write,
system.io.fileshare.none,1024,true);
system.security.cryptography.icryptotransform encryptor = rc2csp.createencryptor(key,iv);
system.io.memorystream msencrypt = new memorystream();
system.security.cryptography.cryptostream csencrypt = new cryptostream(msencrypt,
encryptor,cryptostreammode.write);
byte[] tmp = textconverter.getbytes(toencrypttext);
csencrypt.write(tmp,0,tmp.length);
csencrypt.flushfinalblock();
encrypted = msencrypt.toarray();
tmpfilestream.write(encrypted,0,encrypted.length);
tmpfilestream.flush();
r = true;
tmpfilestream.close();
return r;
}
/// <summary>
/// 将一个被加密的文件解密
/// </summary>
/// <param name="filepath">要解密的文件</param>
/// <param name="iv">初始化向量</param>
/// <param name="key">解密密匙</param>
/// <returns>解密后的文本</returns>
public string decryptfromfile(string filepath,byte[] iv,byte[] key)
{
string r = "";
byte[] decrypted;
system.io.filestream tmpfilestream = new filestream(filepath,
system.io.filemode.open,
system.io.fileaccess.read,
system.io.fileshare.none,1024,true);
system.security.cryptography.icryptotransform decryptor = rc2csp.createdecryptor(key,iv);
system.io.memorystream msdecrypt = new memorystream();
system.security.cryptography.cryptostream csdecrypt = new cryptostream(msdecrypt,
decryptor,cryptostreammode.write);
byte[] tmp = new byte[tmpfilestream.length];
tmpfilestream.read(tmp,0,tmp.length);
csdecrypt.write(tmp,0,tmp.length);
csdecrypt.flushfinalblock();
decrypted = msdecrypt.toarray();
r = textconverter.getstring(decrypted,0,decrypted.length);
tmpfilestream.close();
return r;
}
/// <summary>
/// 设置加密或解密的初始化向量
/// </summary>
/// <param name="s">长度等于8的ascii字符集的字符串</param>
public void setiv(string s)
{
if(s.length != 8)
{
messagebox.show("输入的字符串必须为长度为8的且属于ascii字符集的字符串");
this.iv =null;
return;
}
try
{
this.iv = this.asciiencoding.getbytes(s);
}
catch(system.exception)
{
messagebox.show("输入的字符串必须为长度为8的且属于ascii字符集的字符串");
this.iv = null;
}
}
/// <summary>
/// 设置加密或解密的密匙
/// </summary>
/// <param name="s">长度等于16的ascii字符集的字符串</param>
public void setkey(string s)
{
if(s.length != 16)
{
messagebox.show("输入的字符串必须为长度为16的且属于ascii字符集的字符串");
this.key = null;
return;
}
try
{
this.key = this.asciiencoding.getbytes(s);
}
catch(system.exception)
{
messagebox.show("输入的字符串必须为长度为16的且属于ascii字符集的字符串");
this.key = null;
}
}
}
}