65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.42/5 (10投票s)

2004年7月5日

1分钟阅读

viewsIcon

39852

downloadIcon

877

有很多关于 .NET 密码学的文章,但使用它的示例应用程序却不多。本文(Part 2)介绍了一个用于加密硬盘上文件的应用程序,以确保它们对他人保密且不可读。

CryptoSafe main window

引言

您是否需要让一些文件对他人不可读?您是否希望在离开工作场所时确保您的文件安全?

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();                   
    }
}
© . All rights reserved.