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;
}
}
}
}