binary file encryption
-
Hello, I'm trying to determine why this encryption won't work for binary files. (specifically docx) I can't use a filestream which is what I've read on a few boards and examples because I'm pulling the files from word and posting to a cloud service. Any Ideas? Am I just going about it wrong? TIA, foster public static byte[] Cipher(byte[] PlainText, string InitialVector, string Salt, int KeySize, string PassPhrase, int PasswordIterations, string HashAlgorithm) { byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector); byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt); System.Security.Cryptography.PasswordDeriveBytes DerivedPassword = new System.Security.Cryptography.PasswordDeriveBytes(PassPhrase, SaltValueBytes, HashAlgorithm, PasswordIterations); byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8); System.Security.Cryptography.RijndaelManaged SymmetricKey = new System.Security.Cryptography.RijndaelManaged(); SymmetricKey.Mode = System.Security.Cryptography.CipherMode.CBC; System.Security.Cryptography.ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes); System.IO.MemoryStream MemStream = new System.IO.MemoryStream(); System.Security.Cryptography.CryptoStream CryptoStream = new System.Security.Cryptography.CryptoStream(MemStream, Encryptor, System.Security.Cryptography.CryptoStreamMode.Write); CryptoStream.Write(PlainText, 0, PlainText.Length); CryptoStream.FlushFinalBlock(); byte[] CipherTextBytes = MemStream.ToArray(); MemStream.Close(); CryptoStream.Close(); return CipherTextBytes; } public static byte[] Decipher(byte[] CipherText, string InitialVector, string Salt, int KeySize, string PassPhrase, int PasswordIterations, string HashAlgorithm) { byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector); byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt); System.Security.Cryptography.PasswordDeriveBytes DerivedPassword = new System.Security.Cryptography.PasswordDeriveBytes(PassPhrase, SaltValueBytes, HashAlgorithm, PasswordIterations); byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8); System.Security.Cryptography.RijndaelManaged SymmetricKey = new System.Security.Cryptography.RijndaelManaged(); SymmetricKey.Mode =
-
Hello, I'm trying to determine why this encryption won't work for binary files. (specifically docx) I can't use a filestream which is what I've read on a few boards and examples because I'm pulling the files from word and posting to a cloud service. Any Ideas? Am I just going about it wrong? TIA, foster public static byte[] Cipher(byte[] PlainText, string InitialVector, string Salt, int KeySize, string PassPhrase, int PasswordIterations, string HashAlgorithm) { byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector); byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt); System.Security.Cryptography.PasswordDeriveBytes DerivedPassword = new System.Security.Cryptography.PasswordDeriveBytes(PassPhrase, SaltValueBytes, HashAlgorithm, PasswordIterations); byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8); System.Security.Cryptography.RijndaelManaged SymmetricKey = new System.Security.Cryptography.RijndaelManaged(); SymmetricKey.Mode = System.Security.Cryptography.CipherMode.CBC; System.Security.Cryptography.ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes); System.IO.MemoryStream MemStream = new System.IO.MemoryStream(); System.Security.Cryptography.CryptoStream CryptoStream = new System.Security.Cryptography.CryptoStream(MemStream, Encryptor, System.Security.Cryptography.CryptoStreamMode.Write); CryptoStream.Write(PlainText, 0, PlainText.Length); CryptoStream.FlushFinalBlock(); byte[] CipherTextBytes = MemStream.ToArray(); MemStream.Close(); CryptoStream.Close(); return CipherTextBytes; } public static byte[] Decipher(byte[] CipherText, string InitialVector, string Salt, int KeySize, string PassPhrase, int PasswordIterations, string HashAlgorithm) { byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector); byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt); System.Security.Cryptography.PasswordDeriveBytes DerivedPassword = new System.Security.Cryptography.PasswordDeriveBytes(PassPhrase, SaltValueBytes, HashAlgorithm, PasswordIterations); byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8); System.Security.Cryptography.RijndaelManaged SymmetricKey = new System.Security.Cryptography.RijndaelManaged(); SymmetricKey.Mode =
The problem may be these two lines in the Decipher function:
byte[] PlainTextBytes = new byte[CipherText.Length];
int ByteCount = cryptoStream.Read(PlainTextBytes, 0, PlainTextBytes.Length);The
Read()
will fillPlainTextBytes
up through the number of bytes read, the rest will be 0's. I find that very often the encrypted data is longer than the decrypted data. So it's very possible thatPlainTextBytes
will be created as abyte[]
larger than the actual decrypted data. I've also come across code like this on the internet and won't use it myself; it just doesn't look right to me. For what arbitrary reason would you determine that the length of the decrypted data is exactly the same as the length of the encrypted data? Which is essentially what the code is assuming. I prefer to play it safe and not make that assumption. I find it easier to use theCryptoStream
inWrite
mode for both encrypting and decrypting, I find it helps avoid the aforementioned assumption. If you supply theCryptoStream
an emptyMemoryStream
and the properICryptoTransform
(encrypt or decrypt), then all you have to do is write thebyte[]
to theCryptoStream
and when youRead
from theMemoryStream
you will get the transformed data. Doing that in theDecipher
function would look like this:MemoryStream memStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memStream, Decryptor, CryptoStreamMode.Write);
cryptoStream.Write(CipherText, 0, CipherText.Length);
PlainTextBytes = memStream.ToArray();This is pretty much how you did the encryption in the
Cipher
function. The cool thing about this is that the actions for encrypting and decrypted are exactly the same, the only thing different is the data and theICryptoTransform
used. So, you can put this functionality in a single function in which you only need to pass the properICryptoTransform
and the properbyte[]
. When you are encrypting pass in the unencrypted data as abyte[]
and the EncryptorICryptoTransform
and when decrypting pass in the encrypted data as abyte[]
and the DecryptorICryptoTransform
, and you'd have this (which is almost the same as code I've used):private byte[] PerformTransform(byte[] data, ICryptoTransform tran)
{