Introduction
In this article, I'll talk about how to protect a file with a password (any file type) - without using ZIP or any other archivers. The file will be encrypted and then 'attached' to an executable, which will be later used to decrypt it using the password provided.
Starting Information
Initially, there'll be 2 files: the file we want to encrypt, and the decryptor (which is a C# executable). These files will be 'merged' together, and when needed, the decryptor will retrieve from its own file the content of the original file.
How to 'pack' the file (steps)
- Get the content (bytes) of the file we want to protect by password
- Encrypt it using a good algorithm (I'm using AES)
- Put everything at the end of the generic decryptor *
* the executable file won't be affected by what we add.
How to decrypt the file
- The file is appended at the end of the decryptor, so we need to skip as many bytes as the original decryptor's size (when it has no file attached)
- Load the file's content into memory -> decrypt it with the password provided
- Save the content as a new file
1. Creating the Decryptor
This part explains how to write the decryptor application: the resulting executable is, what I like to call, the 'original decryptor'. Its size is exactly 10240 bytes, so after we attach the encrypted file, we need to skip those bytes when we want to decrypt the content.
I made it as a Forms project only for the sake of design - anyway there's only 1 method that does all the work so it can be easily modified.
using System;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;
namespace decryptor
{
public partial class DecryptorWnd : Form
{
public DecryptorWnd()
{
InitializeComponent();
}
int decryptorSize = 10240;
private void decryptButton_Click(object sender, EventArgs e)
{
decrypt(Process.GetCurrentProcess().ProcessName, passwordTextBox.Text);
}
private void decrypt(string file, string password)
{
byte[] key = new byte[32];
Encoding.Default.GetBytes(password).CopyTo(key, 0);
RijndaelManaged aes = new RijndaelManaged();
aes.Mode = CipherMode.CBC;
aes.KeySize = 256;
aes.BlockSize = 256;
aes.Padding = PaddingMode.Zeros;
using (FileStream outputStream =
new FileStream("decrypted_" + file, FileMode.Create))
{
using (CryptoStream cryptoStream = new CryptoStream
(outputStream, aes.CreateDecryptor(key, key), CryptoStreamMode.Write))
{
byte[] buffer = File.ReadAllBytes(file + ".exe");
cryptoStream.Write(buffer, decryptorSize, buffer.Length - decryptorSize);
}
}
}
}
}
2. Attaching the File to the Decryptor
This requires another executable file that will handle encryption and file attachment. I used a Console Application for this - to be honest, I never intended to publish this as a program. I was just testing - and for testing, the console was enough.
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace FileAppender
{
class Program
{
static MemoryStream mStream = new MemoryStream();
public static void Main()
{
encrypt("SomeFile.txt", "myPassword");
}
private static void encrypt(string fileName, string password)
{
byte[] key = new byte[32];
Encoding.Default.GetBytes(password).CopyTo(key, 0);
RijndaelManaged aes = new RijndaelManaged();
aes.Mode = CipherMode.CBC;
aes.KeySize = 256;
aes.BlockSize = 256;
aes.Padding = PaddingMode.Zeros;
using (CryptoStream cStream = new CryptoStream(mStream,
aes.CreateEncryptor(key, key), CryptoStreamMode.Write))
{
byte[] buffer = File.ReadAllBytes(fileName);
cStream.Write(buffer, 0, buffer.Length);
}
append(fileName);
}
private static void append(string file)
{
byte[] exeBuffer = File.ReadAllBytes("decryptor.exe");
byte[] appendBuffer = mStream.ToArray() ;
byte[] finalBuffer = new byte[exeBuffer.Length + appendBuffer.Length];
exeBuffer.CopyTo(finalBuffer, 0);
appendBuffer.CopyTo(finalBuffer, exeBuffer.Length);
File.WriteAllBytes(file + ".exe", finalBuffer);
}
}
}
Note
This code is provided to give you an idea on how to write such a program. This means it's not optimized, so it can be improved - writing an optimized code would produce a source code harder to comprehend...