Introduction
Do you need to keep some of your files unreadable to others? Do you want to be sure that when you leave your workplace your files are secure?
CryptoSafe is a tool that enables you to encrypt your private files so that no one else can read them.
Key features of CryptoSafe:
- Rijndael encryption algorithm.
- Secure key creation from given password using
PasswordDeriveBytes
method.
- Using Isolated Storage for storing per-user configuration.
- Extracting icons associated with files, using Win32 shell.
The algorithm - RijndaelManaged
Why RijndaelManaged? As written in part 1: because it is strong, fast, and managed, what ensures to run on every machine with .NET framework installed.
The Application
There are very few steps you have to do for using CryptoSafe:
- Enter password for encryption.
- Define folders you want to protect (in Folders tab).
- Select active folder to work with.
- Encrypt files selected in left listbox by clicking "move right" button.
- Decrypt files by clicking "move left" (or double clicking) encrypted files in right listbox.
You can refresh file list by clicking "re" button if necessary (when folder contents change).
The Code
Creating file list with proper icons
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
{
IntPtr hImgSmall = MyShell.SHGetFileInfo(s, 0,
ref shinfo,(uint)Marshal.SizeOf(shinfo),
MyShell.SHGFI_ICON |
MyShell.SHGFI_SMALLICON);
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;
}}
Save settings in isolated storage
void saveSettings()
{
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);
}
}
Load settings from isolated storage
void loadSettings()
{
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);
}
}
File encryption
public void EncryptData(String inName,
String outName, byte[] rijnKey, byte[] rijnIV)
{
FileStream fin = null;
FileStream fout = null;
CryptoStream encStream = null;
try
{
fin = new FileStream(inName, FileMode.Open, FileAccess.Read);
fout = new FileStream(outName, FileMode.Create, FileAccess.Write);
byte[] bin = new byte;
long rdlen = 0;
long totlen = fin.Length;
int len;
RijndaelManaged rijn = new RijndaelManaged();
encStream = new CryptoStream(fout,
rijn.CreateEncryptor(rijnKey, rijnIV),
CryptoStreamMode.Write);
fireMessage("Rijndael encrypting...");
encStream.Write(testHeader,0,testHeader.Length);
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();
}
}
File decryption
public bool DecryptData(String inName,
String outName, byte[] rijnKey, byte[] rijnIV)
{
FileStream fin = null;
FileStream fout = null;
CryptoStream decStream = null;
try
{
fin = new FileStream(inName, FileMode.Open, FileAccess.Read);
byte[] bin = new byte;
long rdlen = 0;
long totlen = fin.Length;
int len;
RijndaelManaged rijn = new RijndaelManaged();
decStream = new CryptoStream(fin,
rijn.CreateDecryptor(rijnKey, rijnIV),
CryptoStreamMode.Read);
fireMessage("Rijndael decrypting...");
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;
}
fout = new FileStream(outName,
FileMode.Create, FileAccess.Write);
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();
}
}