diff --git a/Crypto Notepad/AES.cs b/Crypto Notepad/AES.cs index 53d3fc9..b9e191a 100644 --- a/Crypto Notepad/AES.cs +++ b/Crypto Notepad/AES.cs @@ -5,17 +5,95 @@ namespace Crypto_Notepad { + /// + /// This class extracts information needed for decryption from a .cnp file + /// + class AESMetadata + { + /// + /// Offset to actual AES data; size of metadata + /// + private int _offsetToData; + public int offsetToData + { + get + { + return this._offsetToData; + } + } + private byte[] _initialVector; + public byte[] initialVector + { + get + { + return this._initialVector; + } + } + private byte[] _salt; + public byte[] salt + { + get + { + return this._salt; + } + } + + public AESMetadata() + { + this._initialVector = new byte[16]; + this._salt = null; + } + + public void DeleteMetadataFromBuffer(ref byte[] rawData) + { + // Possibly unsafe + byte[] buffer = new byte[rawData.Length - this.offsetToData]; + System.Buffer.BlockCopy(rawData, this.offsetToData, buffer, 0, rawData.Length - this.offsetToData); + rawData = buffer; + } + + public void GetMetadata(byte[] rawData) + { + int index = 0; + // Read initialVector + for (int i = 0; index < rawData.Length; index++, i++) + { + if (rawData[index] == '\0') // Null terminator + { + index++; + break; + } + this.initialVector[i] = rawData[index]; + } + // This is kind of a dirty fix, but it gets the job done + // Get length of salt + int length = 0; + for (int i = index; i < rawData.Length; i++) + { + if (rawData[i] == '\0') // Null terminator + { + index++; + break; + } + length++; + } + // Copy bytes into this.salt + this._salt = new byte[length]; + System.Buffer.BlockCopy(rawData, index - 1, this.salt, 0, length); + + this._offsetToData = this.salt.Length + 1 + this.initialVector.Length + 1; + } + } + class AES { - public static string Encrypt(string plainText, string password, + public static string Encrypt(string plainText, string password, byte[] initialVectorBytes, string salt = "Kosher", string hashAlgorithm = "SHA1", - int passwordIterations = 2, string initialVector = "OFRna73m*aze01xY", - int keySize = 256) + int passwordIterations = 2, int keySize = 256) { if (string.IsNullOrEmpty(plainText)) return ""; - byte[] initialVectorBytes = Encoding.ASCII.GetBytes(initialVector); byte[] saltValueBytes = Encoding.ASCII.GetBytes(salt); byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); @@ -28,10 +106,16 @@ public static string Encrypt(string plainText, string password, byte[] cipherTextBytes = null; - using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor - (keyBytes, initialVectorBytes)) + using (MemoryStream memStream = new MemoryStream()) { - using (MemoryStream memStream = new MemoryStream()) + byte[] nullByte = { 0 }; + memStream.Write(initialVectorBytes, 0, initialVectorBytes.Length); + memStream.Write(nullByte, 0, 1); + memStream.Write(saltValueBytes, 0, saltValueBytes.Length); + memStream.Write(nullByte, 0, 1); + + using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor + (keyBytes, initialVectorBytes)) { using (CryptoStream cryptoStream = new CryptoStream (memStream, encryptor, CryptoStreamMode.Write)) @@ -45,24 +129,31 @@ public static string Encrypt(string plainText, string password, } } - symmetricKey.Clear(); + symmetricKey.Dispose(); return Convert.ToBase64String(cipherTextBytes); } public static string Decrypt(string cipherText, string password, - string salt = "Kosher", string hashAlgorithm = "SHA1", - int passwordIterations = 2, string initialVector = "OFRna73m*aze01xY", + string hashAlgorithm = "SHA1", + int passwordIterations = 2, int keySize = 256) { if (string.IsNullOrEmpty(cipherText)) return ""; - byte[] initialVectorBytes = Encoding.ASCII.GetBytes(initialVector); - byte[] saltValueBytes = Encoding.ASCII.GetBytes(salt); + byte[] initialVectorBytes; + byte[] saltValueBytes; byte[] cipherTextBytes = Convert.FromBase64String(cipherText); + // Extract metadata from file + AESMetadata metadata = new AESMetadata(); + metadata.GetMetadata(cipherTextBytes); + saltValueBytes = metadata.salt; + initialVectorBytes = metadata.initialVector; + metadata.DeleteMetadataFromBuffer(ref cipherTextBytes); + PasswordDeriveBytes derivedPassword = new PasswordDeriveBytes - (password, saltValueBytes, hashAlgorithm, passwordIterations); + (password, saltValueBytes, hashAlgorithm, passwordIterations); byte[] keyBytes = derivedPassword.GetBytes(keySize / 8); RijndaelManaged symmetricKey = new RijndaelManaged(); @@ -71,10 +162,10 @@ public static string Decrypt(string cipherText, string password, byte[] plainTextBytes = new byte[cipherTextBytes.Length]; int byteCount = 0; - using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor - (keyBytes, initialVectorBytes)) + using (MemoryStream memStream = new MemoryStream(cipherTextBytes)) { - using (MemoryStream memStream = new MemoryStream(cipherTextBytes)) + using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor + (keyBytes, initialVectorBytes)) { using (CryptoStream cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read)) @@ -84,9 +175,10 @@ public static string Decrypt(string cipherText, string password, cryptoStream.Close(); } } - } - symmetricKey.Clear(); + symmetricKey.Dispose(); + } + return Encoding.UTF8.GetString(plainTextBytes, 0, byteCount); } } diff --git a/Crypto Notepad/Form1.cs b/Crypto Notepad/Form1.cs index d7bb490..00cd740 100644 --- a/Crypto Notepad/Form1.cs +++ b/Crypto Notepad/Form1.cs @@ -51,7 +51,7 @@ void SaltMAC() DialogResult res = new DialogResult(); using (new CenterWinDialog(this)) { - res = MessageBox.Show("Get The Salt from mac address? (You can edit it by himself in Settings)", "Crypto Notepad", + res = MessageBox.Show("Get The Salt from mac address? (You can change it yourself in Settings)", "Crypto Notepad", MessageBoxButtons.YesNo, MessageBoxIcon.Question); } @@ -88,7 +88,7 @@ void DecryptAES() { string opnfile = File.ReadAllText(OpenFile.FileName); string NameWithotPath = Path.GetFileName(OpenFile.FileName); - string de = AES.Decrypt(opnfile, publicVar.encryptionKey, ps.TheSalt, ps.HashAlgorithm, ps.PasswordIterations, "16CHARSLONG12345", ps.KeySize); + string de = AES.Decrypt(opnfile, publicVar.encryptionKey, ps.HashAlgorithm, ps.PasswordIterations, ps.KeySize); customRTB.Text = de; this.Text = appName + NameWithotPath; @@ -165,7 +165,7 @@ private void openAsotiations() } publicVar.okPressed = false; - string de = AES.Decrypt(opnfile, publicVar.encryptionKey, ps.TheSalt, ps.HashAlgorithm, ps.PasswordIterations, "16CHARSLONG12345", ps.KeySize); + string de = AES.Decrypt(opnfile, publicVar.encryptionKey, ps.HashAlgorithm, ps.PasswordIterations, ps.KeySize); customRTB.Text = de; this.Text = appName + NameWithotPath; @@ -234,8 +234,15 @@ private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) filename = SaveFile.FileName; + // Generate random initialization vector + RandomNumberGenerator RandNumGen = RNGCryptoServiceProvider.Create(); + byte[] RandInitVector = new byte[16]; + RandNumGen.GetNonZeroBytes(RandInitVector); + string noenc = customRTB.Text; - string en = AES.Encrypt(customRTB.Text, publicVar.encryptionKey, ps.TheSalt, ps.HashAlgorithm, ps.PasswordIterations, "16CHARSLONG12345", ps.KeySize); + string en = AES.Encrypt(customRTB.Text, publicVar.encryptionKey, RandInitVector, ps.TheSalt, ps.HashAlgorithm, ps.PasswordIterations, ps.KeySize); + RandNumGen.Dispose(); + customRTB.Text = en; StreamWriter sw = new StreamWriter(filename); int i = customRTB.Lines.Count(); @@ -374,8 +381,15 @@ private void saveToolStripMenuItem1_Click_1(object sender, EventArgs e) publicVar.okPressed = false; } + // Generate random initialization vector + RandomNumberGenerator RandNumGen = RNGCryptoServiceProvider.Create(); + byte[] RandInitVector = new byte[16]; + RandNumGen.GetNonZeroBytes(RandInitVector); + string noenc = customRTB.Text; - string en = AES.Encrypt(customRTB.Text, publicVar.encryptionKey, ps.TheSalt, ps.HashAlgorithm, ps.PasswordIterations, "16CHARSLONG12345", ps.KeySize); + string en = AES.Encrypt(customRTB.Text, publicVar.encryptionKey, RandInitVector, ps.TheSalt, ps.HashAlgorithm, ps.PasswordIterations, ps.KeySize); + RandNumGen.Dispose(); + customRTB.Text = en; StreamWriter sw = new StreamWriter(filename); int i = customRTB.Lines.Count(); @@ -936,7 +950,7 @@ void AutoLock(bool minimize) OpenFile.FileName = filename; string opnfile = File.ReadAllText(OpenFile.FileName); string NameWithotPath = Path.GetFileName(OpenFile.FileName); - string de = AES.Decrypt(opnfile, publicVar.encryptionKey, ps.TheSalt, ps.HashAlgorithm, ps.PasswordIterations, "16CHARSLONG12345", ps.KeySize); + string de = AES.Decrypt(opnfile, publicVar.encryptionKey, ps.HashAlgorithm, ps.PasswordIterations, ps.KeySize); this.Text = appName + NameWithotPath; filename = OpenFile.FileName; diff --git a/Crypto Notepad/Form2.cs b/Crypto Notepad/Form2.cs index 872b9d4..8b1bfaa 100644 --- a/Crypto Notepad/Form2.cs +++ b/Crypto Notepad/Form2.cs @@ -7,6 +7,8 @@ public partial class Form2 : Form { public Form2() { + // Initialize to false in case user presses the exit button + publicVar.okPressed = false; InitializeComponent(); }