We encrypt all types of files using Rijndael encryption. Newer .xlsx and .docx files are throwing errors when trying to open (after encrypting and trying to decrypt). Error when Excel 2003 tries to open file: "The converter failed to open the file". I have Excel add on installed and when not using encryption/decryption I am able to open xlsx files in Excel 2003.
I have changed out the code to use AES, with same type of issue (but in this case the file will not download, just sits there in the Firefox download list). I've read suggestions here to pay attention to byte size/lengths of encrypted/decrypted files but am at a loss as to how to fix this, I see that if I upload a xls file the length of the encrypted file going in is different from the decrypted file coming out and xls save and open fine, so I don't know how to test if this is the issue since these lenghts differ on files that do work. I am including the code to see if anyone can spot any issues that could be contributing to xlsx/docx file encryption errors. I've minimized the code, so if any syntax errors, is probably due to that.
I have installed Excel 2007 to see if the .xlsx files that are encrypted and decrypted will open in Excel 2007. When I attempt to open the file, I get a prompt:"Excel found unreadable content in 'myfile.xlsx'. Do you want to recover the contents of this workbook?". Excel 2007 is able to recover/repair the file with message: "Excel completed the file level validation and repair. Some parts of this workbook may have been repaired or discarded". So, the encryption/decryption creates invalid file but Excel 2007 is able to repair this; Excel 2003 converter cannot do anything with the file.
public byte [] Encrypt(byte [] bytes)
{
if (myRijndael == null)
myRijndael = new RijndaelManaged();
ICryptoTransform encryptor = myRijndael.CreateEncryptor(key, IV);
MemoryStream msEncrypt = new MemoryStream();
CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
csEncrypt.Write(bytes, 0, bytes.Length);
csEncrypt.FlushFinalBlock();
return msEncrypt.ToArray();
}
public byte [] Decrypt(byte [] encrypted, string text)
{
if (myRijndael == null)
{
myRijndael = new RijndaelManaged();
}
ICryptoTransform decryptor = myRijndael.CreateDecryptor(key, IV);
MemoryStream msDecrypt = new MemoryStream(encrypted);
CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
byte [] fromEncrypt = new byte[encrypted.Length];
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
return fromEncrypt;
}
Usage:
ENCRYPT:
ClcCrypto crypt; // Our class for saving keys etc.
ClcCrypto(CLC.WebUtil.ClcCrypto.GetDecryptionKey(), Group.IV);
BinaryReader br = new BinaryReader(NewFile);// NewFile is Stream from filMyFile.PostedFile.InputStream
byte[] EncryptedContents = crypt.Encrypt(br.ReadBytes((int)NewFile.Length));
FileStream fs = File.Create(DestFileName);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(EncryptedContents);
bw.Close();
fs.Close();
br.Close();
DECRYPT (file download):
byte[] baOut = null;
baOut = fiOut.GetFileData(out lLength); // See below for method
Response.AddHeader("content-disposition", "attachment; filename=" + FileName));
Response.ContentType = fiOut.MimeType;
Response.AddHeader("content-length", lLength.ToString());
Response.BinaryWrite(baOut);
Response.End();
public byte[] GetFileData(out long intFileSize)
{
FileStream fsOut = new FileStream(FilePath, FileMode.Open, FileAccess.Read);
intFileSize = fsOut.Length;
byte[] Buffer = null;
ClcCrypto crypt;
crypt = new CLC.WebUtil.ClcCrypto(CLC.WebUtil.ClcCrypto.GetDecryptionKey(), IV);
BinaryReader br = new BinaryReader(fsOut);
Buffer = crypt.Decrypt(br.ReadBytes((int)fsOut.Length), null);
br.Close();
fsOut.Close();
return Buffer;
}
If the padding is of concern, here is something for you:
How do I encrypt a string in vb.net using RijndaelManaged, and using PKCS5 padding?
Sounds like a truncation issue; possibly because of the way you're creating the memory stream; when I decrypt it looks like the following
MemoryStream msDecrypt = new MemoryStream();
CryptoStream csDecrypt = new CryptoStream(
msDecrypt,
decryptor,
CryptoStreamMode.Write);
csStream.Write(encrypted, 0, encrypted.Length);
csStream.Flush();
return csDecrypt.ToArray();
I'd guess that there are extra null bytes being appended, and using the alternate approach may alleviate this.
Related
I'm trying to encrypt/decrypt a string with AES, using streams. I'm using the following code for encryption:
var provider = Aes.Create();
provider.Mode = CipherMode.CBC;
provider.Padding = PaddingMode.PKCS7;
using var encryptor = provider.CreateEncryptor();
using var memoryStream = new MemoryStream();
using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
using var streamWriter = new StreamWriter(cryptoStream, Encoding.UTF8);
streamWriter.Write(plainText);
cryptoStream.FlushFinalBlock();
var cipher = memoryStream.ToArray();
This successfully produces a byte array, though no matter the plaintext length, the cipher is always 16 bytes. From my understanding, with a block size of 16, a plaintext string with a length of 16 or more should result in a cipher that is larger than 16 bytes. Also, even for plaintext that is less than 16 bytes, decryption always results in an empty string.
var provider = Aes.Create();
provider.Mode = CipherMode.CBC;
provider.Padding = PaddingMode.PKCS7;
using var decryptor = _provider.CreateDecryptor(key, iv);
using var memoryStream = new MemoryStream(cipher);
using var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
using var streamReader = new StreamReader(cryptoStream, Encoding.UTF8);
var plainText = streamReader.ReadToEnd();
My code is based on this sample in the Microsoft docs, though I'm calling cryptoStream.FlushFinalBlock(), after writing to the stream, although this isn't working as desired.
Calling FlushFinalBlock is not really necessary if you correctly close the stream. It might be useful if you want to write the last block (including padding) without closing it.
However, using the generic streaming API, preferably with the using statement and closing the stream should write any bytes left in the buffer + any padding that could be required.
Of course you should include any stream that writes to the CryptoStream in that using statement, otherwise they may have leftover data. Of course the receiving stream should only be closed after the data has been retrieved, for instance in case a MemoryStream is used.
I am compressing a file using GZip and then encrypting using AES.
When I step through the code, I see that the magic number (1f 8b) is present in the intermediate compressed unencrypted data and then the file is encrypted. When I go to decrypt the file, the intermediate decrypted compressed data does not contain the magic number and the GZipStream fails when decompressing it.
Here is the main code:
private static void CompressThenEncrypt(string inputFileName, string outputFileName, ICryptoTransform encryptor)
{
using (var inputFileStream = new FileStream(inputFileName, FileMode.Open, FileAccess.Read))
{
using (var outputFileStream = new FileStream(outputFileName, FileMode.Create, FileAccess.Write))
using (var cryptoStream = new CryptoStream(outputFileStream, encryptor, CryptoStreamMode.Write))
{
using (var gZipStream = new GZipStream(cryptoStream, CompressionMode.Compress))
{
inputFileStream.CopyTo(gZipStream);
}
}
}
}
private static void DecryptThenDecompress(string inputFileName, string outputFileName, ICryptoTransform decryptor)
{
using (var inputFileStream = new FileStream(inputFileName, FileMode.Open, FileAccess.Read))
{
using (var cryptoStream = new CryptoStream(inputFileStream, decryptor, CryptoStreamMode.Read))
using (var gZipStream = new GZipStream(cryptoStream, CompressionMode.Decompress))
using (var outputFileStream = new FileStream(outputFileName, FileMode.Create, FileAccess.Write))
{
gZipStream.CopyTo(outputFileStream);
}
}
}
Source file is 19000 bytes. When compressed it becomes 603 bytes (with magic number), then encrypted it becomes 608 bytes (due to padding). When decrypted it becomes 603 bytes (no magic number) and I simply can not get beyond this point.
Here is the calling code:
using (var aes = new AesCryptoServiceProvider())
{
ICryptoTransform encryptor = aes.CreateEncryptor();
ICryptoTransform decryptor = aes.CreateDecryptor();
CompressThenEncrypt(OriginalFileName, CompressThenEncryptFileName, encryptor);
DecryptThenDecompress(CompressThenEncryptFileName, DecryptThenDecompressFileName, decryptor);
}
Edit: More Info
Compressed Data (603 bytes):
1F-8B-08-00-00-00-00-00-04-00-ED-CA-B1-0D-00-20-08-00-C1-DE-C4-21-51-64-FF-11-DC-80-84-FE-9A-6F-FE-E2-DC-7C-15-6D-F7-EA-3F-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-D4-44-7D-3F-A6-A4-8A-30-E6-02-00
Encrypted Data (608 bytes):
C3-02-64-A9-15-15-52-A9-9F-2A-62-EF-89-B2-9A-E0-72-9A-BA-E2-A2-C8-35-BA-3C-CF-D7-07-8B-DC-D4-63-65-AF-A8-62-22-E5-CC-C6-7D-6F-9B-64-57-9F-C0-94-75-E7-6C-A9-DB-B3-57-29-01-95-F5-B9-E5-3D-FD-AB-EC-E3-AC-AF-EB-A6-C0-81-B3-47-4A-EB-F6-DD-03-DF-92-0A-82-D9-DD-4E-46-DF-55-2E-EB-34-AC-98-1A-7E-A9-25-94-2D-E8-32-4B-F9-2A-61-64-CB-09-9C-D5-8C-A2-0A-C1-22-90-98-93-26-A6-9F-69-F8-EE-6E-95-96-56-28-71-3B-94-1E-5F-50-DB-15-DF-C6-46-3F-04-57-5E-0B-47-44-BB-13-9F-14-08-FB-87-E6-97-65-1B-CA-50-52-7F-10-5D-AF-CC-2F-5E-D0-39-A6-C4-70-3B-90-5F-63-EA-F0-59-46-9E-99-2D-31-34-66-5D-72-E5-85-D5-00-1E-E7-B2-1C-3B-E0-E8-F8-35-BF-90-24-00-DC-47-09-66-92-2F-43-92-48-CB-42-4C-3C-86-CC-67-33-62-A1-1E-76-D1-D6-AD-5F-50-DC-D9-C7-31-F2-33-FE-77-CB-4C-EE-2A-AE-54-63-46-48-B4-FA-6F-0A-E0-1B-F2-F6-C2-D0-E0-24-A1-79-B8-29-FB-04-F3-D5-4E-CC-64-E8-FA-67-55-7B-E6-CD-FD-D2-13-3D-F0-C4-10-A9-5C-BB-34-66-54-A4-6E-B7-AC-54-7A-21-5F-C3-01-7B-97-AD-71-C5-2A-E9-39-B1-27-C7-F8-AC-BF-76-EA-D6-C8-05-22-54-4B-71-73-F2-FD-8E-6E-D7-D2-F2-F7-83-B3-9F-75-3C-CA-BA-BD-F3-C2-E6-16-37-9E-C1-88-C4-69-F5-95-E8-A5-81-C9-FC-22-73-1D-09-AB-A8-6D-A3-BA-CB-0F-27-4E-C7-8C-7A-6C-9D-9B-9D-1F-45-F2-7C-B7-7B-F6-DF-24-50-71-A7-BA-F7-F2-8C-AC-19-A3-86-77-4A-EC-5A-06-12-1F-00-AD-5D-EE-E0-61-D0-80-B7-2C-72-2E-77-6A-32-24-0C-64-78-63-37-A9-08-A2-90-9D-21-5E-E4-5E-E6-1D-66-7D-F5-E1-FC-3C-F1-DE-76-68-D7-1D-46-70-A5-32-31-2B-F5-02-6A-E4-95-CD-8E-B8-76-8D-6E-0B-98-E9-4A-DD-8D-C3-6F-D8-0C-BE-C7-32-3F-99-26-94-26-41-80-E4-E6-E7-D3-26-E9-2F-C0-5D-7B-98-24-BD-6E-9B-E8-9D-F6-DF-51-90-FE-EE-86-DE-9E-31-9F-1C-BA-1A-C4-5B-DD-5A-84-43-02-B9-99-01-6A-95-7C-FF-86-28-C2-4C-EF-4D-D6-36-BD-08-0F-30-25-E7-FF-D9-BC-DA-A7-87-65-1A-1E-83-55-D2-60-38-EC-51-97-FA-FD-11-70-83-70-66-39-78-47-93-7C-B7-FB-48-96-2F-C6-1E-6E-7D-29-38-F6-AB-06-45-C5-F7-50-D6-C7-44-5C-AB-96-A0-60-7D-0E-63-4E-B2-EA
Decrypted Data (603 Bytes):
66-90-D0-0F-8B-67-60-9B-AC-39-FC-45-04-3F-9D-C5-08-00-C1-DE-C4-21-51-64-FF-11-DC-80-84-FE-9A-6F-FE-E2-DC-7C-15-6D-F7-EA-3F-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-14-45-51-D4-44-7D-3F-A6-A4-8A-30-E6-02-00
As you can see, all data is the same in the compressed format except for the first 16 bytes:
Before Encryption: 1F-8B-08-00-00-00-00-00-04-00-ED-CA-B1-0D-00-20
After Decryption: 66-90-D0-0F-8B-67-60-9B-AC-39-FC-45-04-3F-9D-C5
The magic number is gone and I do not know why.
The file that I am encrypting is a text file with the line abcdefabcdefabcdefabcdefabcdefabcdef repeated 5000 times.
Having just the first 16 bytes (default block size of AES) being incorrect is the signature of another problem which is the fact that the AesCryptoServiceProvider decryptor object cannot be reused as it stores state information from the last decryption which causes the such bizarre results in subsequent decryptions.
The full original calling code included the fatal reuse of the decryptor object.
Full original calling code:
using (var aes = new AesCryptoServiceProvider())
{
ICryptoTransform encryptor = aes.CreateEncryptor();
ICryptoTransform decryptor = aes.CreateDecryptor(); // <-- Decryptor fails on second usage
// Compress/ Encrypt
CompressThenEncrypt(OriginalFileName, CompressThenEncryptFileName, encryptor);
EncryptThenCompress(OriginalFileName, EncryptThenCompressFileName, encryptor);
// Decrypt/ Decompress
DecompressThenDecrypt(EncryptThenCompressFileName, DecompressThenDecryptFileName, decryptor);
DecryptThenDecompress(CompressThenEncryptFileName, DecryptThenDecompressFileName, decryptor);
}
This was a personal exercise I developed to showcase the importance of compressing then encrypting data. I had two scenarios "Compress Then Encrypt" and "Encrypt Then Compress" and I also wrote out the code to perform the reverse operations.
The issue occurred when I reused the ICryptoTransform decryptor object. Despite the fact that the CanReuseTransform property is true - it is false advertisement. According to this answer it appears that there is a bug where the input buffer is not cleared correctly after decryption. The linked answer describes a few workarounds and simply creating a separate decryptor object works.
Revised working calling code:
using (var aes = new AesCryptoServiceProvider())
{
ICryptoTransform encryptor = aes.CreateEncryptor();
ICryptoTransform decryptor = aes.CreateDecryptor();
ICryptoTransform decryptor2 = aes.CreateDecryptor();
// Compress/ Encrypt
CompressThenEncrypt(OriginalFileName, CompressThenEncryptFileName, encryptor);
EncryptThenCompress(OriginalFileName, EncryptThenCompressFileName, encryptor);
// Decrypt/ Decompress
DecompressThenDecrypt(EncryptThenCompressFileName, DecompressThenDecryptFileName, decryptor);
DecryptThenDecompress(CompressThenEncryptFileName, DecryptThenDecompressFileName, decryptor2);
}
I am encrypting a pdf file using the Rijndael algorithm. Encryption and decryption works fine. Encryption will convert the pdf file to a file with a .key extension.
The problem is that I am able to open this file in notepad(it shows some Unicode characters) and corrupt it. Consider the scenario that:
I have opened the file and delete some characters/add Some characters and save the notepad file. If I Passed this file to the Decryption method, I will get the corrupted file as output. I know this is happening because the byteStream gets varied(padding changed)while adding or deleting the characters in the file.
Here is my question:
Is there any way to overcome this issue? In other words, disable Editing to the encrypted file?**
Following is method am using for encryption,
VB code
Dim plainFile As String = basePath & "\cryptoText.pdf"
Dim password As String = "somePass"
Dim UE As New UnicodeEncoding()
Dim key As Byte() = UE.GetBytes(password)
Dim cryptFile As String = basePath & "\cryptoText.key"
Dim fsCrypt As New FileStream(cryptFile, FileMode.Create)
Dim RMCrypto As New RijndaelManaged()
Using csKey As New CryptoStream(fsCrypt, RMCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write)
Dim FsIn As New FileStream(plainFile, FileMode.Open)
Dim data As Integer
While (data = FsIn.ReadByte()) <> -1
csKey.WriteByte(CByte(data))
End While
FsIn.Close()
End Using
fsCrypt.Close()
C# code
string plainFile = basePath + "\\cryptoText.pdf";
string password = "somePass";
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password);
string cryptFile = basePath + "\\cryptoText.key";
FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
RijndaelManaged RMCrypto = new RijndaelManaged();
using (CryptoStream csKey = new CryptoStream(fsCrypt, RMCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write)) {
FileStream FsIn = new FileStream(plainFile, FileMode.Open);
int data = 0;
while ((data == FsIn.ReadByte()) != -1) {
csKey.WriteByte(Convert.ToByte(data));
}
FsIn.Close();
}
fsCrypt.Close();
note: i have tried it both in c# and vb.net so that am tagging my question to both.
The answer is do two things,
Encrypt,
Add an HMAC to it (like SHA256 using same key), on the encrypted data, and tack it to the end of the cryptostream
https://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha256%28v=vs.110%29.aspx
Then when you decrypt, you
Verify that HMAC is valid,
IFF #1 verifies, then and only then decrypt
Furthermore, if this is not local files but some sort of network stream, then you have to do verification in constant time - you can't use normal byte comparison functions. This is because of timing attacks. But for local files, you can do whatever comparison you like since there is no timing attacks.
You can't really prevent anyone from opening the file in whatever editor they please and modifying it. Marking the file as read only might help a little but will not solve the problem.
What you should do instead is generate a hash of the encrypted file and then before decrypting it check to make sure that the file still generates the same hash. If it does not, you know that the file has been tampered with.
I am in the process of writing a small encoding class which takes a byte[] array, and cyphers it. As the IV can be made public, I wish to prepend it to the ciphertext to use for decryption.
Following the MSDN Documentation and some SO Post source (Cant find link), I started the stream with the raw IV;
//Start encryption process
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
using (var swWriter = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swWriter.Write(encryptor.IV);
swWriter.Write(plainTextRaw);
}
}
Console.WriteLine("Encrypted Value: {0}", BitConverter.ToString(msEncrypt.ToArray()).Replace("-", String.Empty));
return msEncrypt.ToArray();
}
However, upon writing a simple unit test extracting the first 16 bytes, they do not seem to match.
I am certain the IV is being encrypted within the stream, so where is the best place to inject it?
Just write the IV tot the initial memory stream msEncrypt, not to the stream that is being encrypted swWriter.
I am trying to encrypt some data with the following code:
public static byte[] EncryptString(byte[] input, string password)
{
PasswordDeriveBytes pderiver = new PasswordDeriveBytes(password, null);
byte[] ivZeros = new byte[8];
byte[] pbeKey = pderiver.CryptDeriveKey("RC2", "MD5", 128, ivZeros);
RC2CryptoServiceProvider RC2 = new RC2CryptoServiceProvider();
byte[] IV = new byte[8];
ICryptoTransform encryptor = RC2.CreateEncryptor(pbeKey, IV);
MemoryStream msEncrypt = new MemoryStream();
CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
csEncrypt.Write(input, 0, input.Length);
csEncrypt.FlushFinalBlock();
return msEncrypt.ToArray();
}
However, when it reaches initializing my CryptoStream object, it throws the following error:
"Stream does not support seeking."
To clarify, there is no error handling in the above code, so just running this will not "break", persay. But stepping through the code, the CryptoStream object will show this error in its properties once it's been initialized.
Why is this? And how can I avoid it?
So the code actually runs without an exception, but the problem is when you're looking at the properties in the debugger? If so, that's easy - some properties (Position, for example) rely on being able to seek within the stream. You can't do that with a CryptoStream - so the property evaluation fails.
You don't need to avoid this - it's perfectly fine.
Can you use one of the constructors on the MemoryStream where you pass 'true' to the writable parameter?
To avoid this problem, its much easier to use:
using (var reader = new StreamReader(csEncrypt))
{
return reader.ReadToEnd();
}