应用密码学 第 2 部分: 加密硬盘上文件的工具






4.42/5 (10投票s)
2004年7月5日
1分钟阅读

39852

877
有很多关于 .NET 密码学的文章,但使用它的示例应用程序却不多。本文(Part 2)介绍了一个用于加密硬盘上文件的应用程序,以确保它们对他人保密且不可读。
引言
您是否需要让一些文件对他人不可读?您是否希望在离开工作场所时确保您的文件安全?
CryptoSafe 是一款工具,可让您加密您的私有文件,以便其他人无法读取它们。
CryptoSafe 的主要功能
- Rijndael 加密算法。
- 使用
PasswordDeriveBytes
方法从给定的密码创建安全密钥。 - 使用隔离存储来存储每个用户的配置。
- 使用 Win32 shell 提取与文件关联的图标。
算法 - RijndaelManaged
为什么选择 RijndaelManaged? 正如 Part 1 中所写:因为它强大、快速且受管理,这确保了它可以在安装了 .NET framework 的任何机器上运行。
应用程序
您只需要执行几个步骤即可使用 CryptoSafe
- 输入加密密码。
- 定义您要保护的文件夹(在文件夹选项卡中)。
- 选择要使用的活动文件夹。
- 通过单击“右移”按钮加密左侧列表框中选择的文件。
- 通过单击“左移”(或双击)右侧列表框中加密的文件来解密文件。
如果需要(当文件夹内容发生更改时),可以通过单击“刷新”按钮来刷新文件列表。
代码
使用正确的图标创建文件列表
void refreshFileList()
{
listView1.Items.Clear();
listView2.Items.Clear();
if (workingDirectory == null || workingDirectory.Length == 0)
return;
this.Cursor = Cursors.WaitCursor;
try
{
string[] files = Directory.GetFiles(workingDirectory);
int imageIndex = 0;
imageList1.Images.Clear();
SHFILEINFO shinfo = new SHFILEINFO();
listView1.BeginUpdate();
listView2.BeginUpdate();
foreach (string s in files)
{
FileInfo fi = new FileInfo(s);
if (fi.Extension.ToLower() == ".enc")
{
ListViewItem lvi = new ListViewItem(fi.Name);
lvi.SubItems.Add(fi.Length.ToString());
lvi.Tag = fi.FullName;
lvi.ImageIndex = 0;
listView2.Items.Add(lvi);
}
else
{
//extract file icon
IntPtr hImgSmall = MyShell.SHGetFileInfo(s, 0,
ref shinfo,(uint)Marshal.SizeOf(shinfo),
MyShell.SHGFI_ICON |
MyShell.SHGFI_SMALLICON);
//The icon is returned in the hIcon member of the shinfo
//struct
System.Drawing.Icon myIcon =
System.Drawing.Icon.FromHandle(shinfo.hIcon);
imageList1.Images.Add(myIcon);
ListViewItem lvi = new ListViewItem(fi.Name);
lvi.ImageIndex = imageIndex++;
lvi.SubItems.Add(fi.Length.ToString());
lvi.Tag = fi.FullName;
listView1.Items.Add(lvi);
}
}
listView1.EndUpdate();
listView2.EndUpdate();
}
catch(IOException ex)
{
MessageBox.Show("refreshFileList IOexception: "+ex.Message);
}
finally
{
this.Cursor = Cursors.Arrow;
}}
在隔离存储中保存设置
void saveSettings()
{
// Retrieve an IsolatedStorageFile
// for the current Domain and Assembly.
try
{
IsolatedStorageFile isoFile =
IsolatedStorageFile.GetStore(IsolatedStorageScope.User |
IsolatedStorageScope.Assembly |
IsolatedStorageScope.Domain , null,null);
IsolatedStorageFileStream fs = new
IsolatedStorageFileStream("cryptoSettings.txt",
FileMode.Create,FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
foreach (string fname in lbFolders.Items)
sw.WriteLine(fname);
sw.Close();
isoFile.Close();
}
catch (IsolatedStorageException ex)
{
MessageBox.Show(ex.Message);
}
catch (IOException ex)
{
MessageBox.Show(ex.Message);
}
}
从隔离存储加载设置
void loadSettings()
{
// Retrieve an IsolatedStorageFile for the current Domain and Assembly.
try
{
lbFolders.Items.Clear();
IsolatedStorageFile isoFile =
IsolatedStorageFile.GetStore(IsolatedStorageScope.User |
IsolatedStorageScope.Assembly |
IsolatedStorageScope.Domain , null,null);
IsolatedStorageFileStream fs = new
IsolatedStorageFileStream("cryptoSettings.txt",
FileMode.Open,FileAccess.Read);
StreamReader sr = new StreamReader(fs);
while (true)
{
string l = sr.ReadLine();
if (l == null)
break;
lbFolders.Items.Add(l);
}
sr.Close();
isoFile.Close();
}
catch (FileNotFoundException)
{
MessageBox.Show("application settings" +
" file not found - please set working folders");
}
catch (IsolatedStorageException ex)
{
MessageBox.Show(ex.Message);
}
catch (IOException ex)
{
MessageBox.Show(ex.Message);
}
}
文件加密
public void EncryptData(String inName,
String outName, byte[] rijnKey, byte[] rijnIV)
{
FileStream fin = null;
FileStream fout = null;
CryptoStream encStream = null;
try
{
//Create the file streams to handle the input and output files.
fin = new FileStream(inName, FileMode.Open, FileAccess.Read);
fout = new FileStream(outName, FileMode.Create, FileAccess.Write);
//fout.SetLength(0);
//Create variables to help with read and write.
//This is intermediate storage for the encryption.
byte[] bin = new byte[bufLen];
//This is the total number of bytes written.
long rdlen = 0;
//This is the total length of the input file.
long totlen = fin.Length;
//This is the number of bytes to be written at a time.
int len;
RijndaelManaged rijn = new RijndaelManaged();
encStream = new CryptoStream(fout,
rijn.CreateEncryptor(rijnKey, rijnIV),
CryptoStreamMode.Write);
fireMessage("Rijndael encrypting...");
//encrypt test header
encStream.Write(testHeader,0,testHeader.Length);
//Read from the input file, then encrypt
//and write to the output file.
while(true)
{
len = fin.Read(bin, 0, bufLen);
if (len == 0)
break;
encStream.Write(bin, 0, len);
rdlen += len;
fireMessage(inName,(int)totlen,(int)rdlen);
}
fireMessage(string.Format("{0} - {1} bytes processed",
inName ,rdlen));
}
finally
{
if (encStream != null)
encStream.Close();
if (fout != null)
fout.Close();
if (fin != null)
fin.Close();
}
}
文件解密
public bool DecryptData(String inName,
String outName, byte[] rijnKey, byte[] rijnIV)
{
//Create the file streams to handle the input and output files.
FileStream fin = null;
FileStream fout = null;
CryptoStream decStream = null;
try
{
fin = new FileStream(inName, FileMode.Open, FileAccess.Read);
//Create variables to help with read and write.
//This is intermediate storage for the encryption.
byte[] bin = new byte[bufLen];
//This is the total number of bytes written.
long rdlen = 0;
//This is the total length of the input file.
long totlen = fin.Length;
//This is the number of bytes to be written at a time.
int len;
RijndaelManaged rijn = new RijndaelManaged();
decStream = new CryptoStream(fin,
rijn.CreateDecryptor(rijnKey, rijnIV),
CryptoStreamMode.Read);
fireMessage("Rijndael decrypting...");
//decrypt test header
byte[]test = new byte[testHeader.Length];
decStream.Read(test,0,testHeader.Length);
if (BitConverter.ToString(test) != testHeaderString)
{
decStream.Clear();
decStream = null;
fireMessage("error while decrypting file "+inName);
return false;
}
//create output file
fout = new FileStream(outName,
FileMode.Create, FileAccess.Write);
//Read from the encrypted file and write dercypted data
while(true)
{
len = decStream.Read(bin,0,bufLen);
if (len == 0)
break;
fout.Write(bin,0,len);
rdlen += len;
fireMessage(inName,(int)totlen,(int)rdlen);
}
fireMessage(string.Format("{0} - {1} bytes processed",
inName ,rdlen));
return true;
}
finally
{
if (decStream != null)
decStream.Close();
if (fout != null)
fout.Close();
if (fin != null)
fin.Close();
}
}