使用对称加密
可以使用对称加密算法类DESCryptoServiceProvider的CreateDecryptor()方法和CryptoStream类实现对文件的加密和解密。
注意
(1)对称加密算法以块为单位加密数据,一次加密一个数据块,所以也称为块密码。这些算法通过加密将n字节的输入块转换为加密字节的输出块。由于n很小,因此当要加密的数据值大于n时,则必须逐块加密,且一次加密一个块。如果数据值小于n,必须将其扩展为n字节后才能进行处理。.NET类库提供的加密算法类本身会自动解决以上问题,因此编程时不需要考虑这些问题。
(2).NET类库中提供的块密码类使用密码块链(Cipher Block Chaining,CBC)的默认链模式,但可以根据需要更改此默认设置。该模式下,通过使用一个密钥Key和一个初始化向量(Initialization Vector,IV)对数据执行加密转换。通信双方都必须知道这个Key和IV才能加密和解密数据。
例子:使用对称算法实现加密和解密文件
页面如下所示:
以下代码可以运行(主界面)
using System.Windows.Forms;
using System.IO;
using System.Security.Cryptography;
namespace DiffieHellman
{
public partial class Form2 : Form
{
private AutoSizeWinformclass asc = new AutoSizeWinformclass();
public Form2()
{
InitializeComponent();
}
private void Form2_SizeChanged(object sender, EventArgs e)
{
if (asc != null)
{
asc.controlAutoSize(this);
}
}
private void btn_Encrypt_Click(object sender, EventArgs e)
{
//获取源文件路径
string strFile = tbx_File.Text;
//获取加密密钥
string strKey = tbx_Key.Text;
//获取加密后的文件路径
string strEnFile = tbx_EncryptFile.Text;
//设置向量
byte[] myIV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xDF };
//设置密钥
byte[] myKey = System.Text.Encoding.UTF8.GetBytes(strKey);
if (myKey.Length < 8)
{
// 如果密钥长度不足 8 字节,进行填充
myKey = myKey.Concat(new byte[8 - myKey.Length]).ToArray();
}
//源文件的文件流
FileStream myInStream = new FileStream(strFile, FileMode.Open, FileAccess.Read);
//加密后文件的文件流
FileStream myOutStream = new FileStream(strEnFile, FileMode.OpenOrCreate, FileAccess.Write);
//初始文件流的长度
myOutStream.SetLength(0);
//定义缓冲区
byte[] myBytes = new byte[100];
//定义不断变化的流的长度
long myInLength = 0;
//获取源文件的文件流的长度
long myLength = myInStream.Length;
//定义标准的加密算法对象
DESCryptoServiceProvider myProvider = new DESCryptoServiceProvider();
if (myKey.Length != 8)
{
throw new ArgumentException("The key must be exactly 8 bytes long for DES.");
}
//实现将数据流链接到加密转换的流
CryptoStream myCryptoStream = new CryptoStream(myOutStream,myProvider.CreateEncryptor(myKey,myIV), CryptoStreamMode.Write);
//从源文件中一次读取100个字节
while( myInLength < myLength )
{
//读取源文件流
int mylen = myInStream.Read(myBytes, 0, 100);
//写入加密转换的流
myCryptoStream.Write(myBytes, 0, mylen);
//计算写入的流长度
myInLength += mylen;
}
//关闭资源
myCryptoStream.Close();
myInStream.Close();
myOutStream.Close();
MessageBox.Show("文件加密完成");
}
private void btn_Decrypt_Click(object sender, EventArgs e)
{
//获取源文件路径
string strFile = tbx_EncryptFile.Text;
//获取解密密钥
string strKey = tbx_Key.Text;
//获取解密后的文件路径
string strEnFile = tbx_DecryptFile.Text;
//设置向量
byte[] myIV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
//设置密钥
byte[] myKey = System.Text.Encoding.UTF8.GetBytes(strKey);
if (myKey.Length < 8)
{
// 如果密钥长度不足 8 字节,进行填充
myKey = myKey.Concat(new byte[8 - myKey.Length]).ToArray();
}
//源文件的文件流
FileStream myInStream = new FileStream(strFile,FileMode.Open,FileAccess.Read);
//解密后的文件的文件流
FileStream myOutStream = new FileStream(strEnFile, FileMode.OpenOrCreate, FileAccess.Write);
//初始化文件流的长度
myOutStream.SetLength(0);
//定义缓冲区
byte[] myBytes = new byte[100];
//获取源文件流的长度
long myLength = myInStream.Length;
//定义不断变化的流的长度
long myInLength = 0;
//定义标准的加密算法实例
DESCryptoServiceProvider myProvide = new DESCryptoServiceProvider();
//实现将数据流链接到解密转换的流
CryptoStream myDetoStream = new CryptoStream(myOutStream, myProvide.CreateDecryptor(myKey, myIV), CryptoStreamMode.Write);
//从源文件流中每次读取100字节,然后写入解密转换的流
while(myInLength < myLength)
{
//读取源文件流
int mylen = myInStream.Read(myBytes, 0, 100);
if (mylen == 0) break; // 防止在文件末尾时读取0字节
//写入解密转换的流
myDetoStream.Write(myBytes, 0, mylen);
//计算写入的长度
myInLength += mylen;
}
myDetoStream.Flush();
myDetoStream.Close();
myInStream.Close();
myOutStream.Close();
MessageBox.Show("文件解密成功");
}
}
}
这里加入了控件跟随窗体自动变化的代码AutoSizeWinformclass类
using System.Windows.Forms;
using System.IO;
using System.Security.Cryptography;
namespace DiffieHellman
{
public partial class Form2 : Form
{
private AutoSizeWinformclass asc = new AutoSizeWinformclass();
public Form2()
{
InitializeComponent();
}
private void Form2_SizeChanged(object sender, EventArgs e)
{
if (asc != null)
{
asc.controlAutoSize(this);
}
}
private void btn_Encrypt_Click(object sender, EventArgs e)
{
//获取源文件路径
string strFile = tbx_File.Text;
//获取加密密钥
string strKey = tbx_Key.Text;
//获取加密后的文件路径
string strEnFile = tbx_EncryptFile.Text;
//设置向量
byte[] myIV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xDF };
//设置密钥
byte[] myKey = System.Text.Encoding.UTF8.GetBytes(strKey);
if (myKey.Length < 8)
{
// 如果密钥长度不足 8 字节,进行填充
myKey = myKey.Concat(new byte[8 - myKey.Length]).ToArray();
}
//源文件的文件流
FileStream myInStream = new FileStream(strFile, FileMode.Open, FileAccess.Read);
//加密后文件的文件流
FileStream myOutStream = new FileStream(strEnFile, FileMode.OpenOrCreate, FileAccess.Write);
//初始文件流的长度
myOutStream.SetLength(0);
//定义缓冲区
byte[] myBytes = new byte[100];
//定义不断变化的流的长度
long myInLength = 0;
//获取源文件的文件流的长度
long myLength = myInStream.Length;
//定义标准的加密算法对象
DESCryptoServiceProvider myProvider = new DESCryptoServiceProvider();
if (myKey.Length != 8)
{
throw new ArgumentException("The key must be exactly 8 bytes long for DES.");
}
//实现将数据流链接到加密转换的流
CryptoStream myCryptoStream = new CryptoStream(myOutStream,myProvider.CreateEncryptor(myKey,myIV), CryptoStreamMode.Write);
//从源文件中一次读取100个字节
while( myInLength < myLength )
{
//读取源文件流
int mylen = myInStream.Read(myBytes, 0, 100);
//写入加密转换的流
myCryptoStream.Write(myBytes, 0, mylen);
//计算写入的流长度
myInLength += mylen;
}
//关闭资源
myCryptoStream.Close();
myInStream.Close();
myOutStream.Close();
MessageBox.Show("文件加密完成");
}
private void btn_Decrypt_Click(object sender, EventArgs e)
{
//获取源文件路径
string strFile = tbx_EncryptFile.Text;
//获取解密密钥
string strKey = tbx_Key.Text;
//获取解密后的文件路径
string strEnFile = tbx_DecryptFile.Text;
//设置向量
byte[] myIV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
//设置密钥
byte[] myKey = System.Text.Encoding.UTF8.GetBytes(strKey);
if (myKey.Length < 8)
{
// 如果密钥长度不足 8 字节,进行填充
myKey = myKey.Concat(new byte[8 - myKey.Length]).ToArray();
}
//源文件的文件流
FileStream myInStream = new FileStream(strFile,FileMode.Open,FileAccess.Read);
//解密后的文件的文件流
FileStream myOutStream = new FileStream(strEnFile, FileMode.OpenOrCreate, FileAccess.Write);
//初始化文件流的长度
myOutStream.SetLength(0);
//定义缓冲区
byte[] myBytes = new byte[100];
//获取源文件流的长度
long myLength = myInStream.Length;
//定义不断变化的流的长度
long myInLength = 0;
//定义标准的加密算法实例
DESCryptoServiceProvider myProvide = new DESCryptoServiceProvider();
//实现将数据流链接到解密转换的流
CryptoStream myDetoStream = new CryptoStream(myOutStream, myProvide.CreateDecryptor(myKey, myIV), CryptoStreamMode.Write);
//从源文件流中每次读取100字节,然后写入解密转换的流
while(myInLength < myLength)
{
//读取源文件流
int mylen = myInStream.Read(myBytes, 0, 100);
if (mylen == 0) break; // 防止在文件末尾时读取0字节
//写入解密转换的流
myDetoStream.Write(myBytes, 0, mylen);
//计算写入的长度
myInLength += mylen;
}
myDetoStream.Flush();
myDetoStream.Close();
myInStream.Close();
myOutStream.Close();
MessageBox.Show("文件解密成功");
}
}
}
不需要的可以直接将主界面中的下面代码注释即可。
private AutoSizeWinformclass asc = new AutoSizeWinformclass();
private void Form2_SizeChanged(object sender, EventArgs e)
{
if (asc != null)
{
asc.controlAutoSize(this);
}
}
运行效果如下所示
运行时要提前写好所有的文件路径,加密密钥一定要保证是8位。文件路径要提前创建好,其他的可以不创建,运行时没有会字节创建文件。