Encrypting a ZipPackage Stream in Memory - c#

I am using .NET 4.0 and trying to do the following:
Create a System.IO.Packaging.Package in Memory
Add Items to the package
encrypt package before it is written to file.
I tried to create a MemoryStream and add the files to it by:
using (var memoryZip = Package.Open(_memoryStream, FileMode.Open))
{
var partUri = PackUriHelper.CreatePartUri(_fileUri);
var part = memoryZip.CreatePart(
partUri,
String.Empty,
CompressionOption.NotCompressed);
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
fileStream.CopyTo(packagePart.GetStream());
}
}
Then I tried to encrypt it and saved it to a file:
_key = new DESCryptoServiceProvider
{
Key = Encoding.ASCII.GetBytes(_password);
IV = Encoding.ASCII.GetBytes(_password);
}
var fileStream = File.Open(_fileName, FileMode.Create, FileAccess.Write);
var cryptoStream = new CryptoStream(streamToFile, _key.CreateEncryptor(), CryptoStreamMode.Write);
//Convert filestream to byte[]
var streamAsBytes = new byte[(_memoryStream.Length)];
_memoryStream.Read(streamAsBytes, 0, streamAsBytes.Length);
//Encrypt
cryptoStream.Write(streamAsBytes, 0, streamAsBytes.Length);
fileStream.Close();
cryptoStream.Flush();
cryptoStream.Close();
However, when I go to decrypt it:
var fileStream = new FileStream(_zipFileName, FileMode.Open, FileAccess.Read);
var cryptoStream = new CryptoStream(fileStream, _key.CreateDecryptor(), CryptoStreamMode.Read);
using(var zipPackage = Package.Open(cryptoStream, FileMode.Open))
I get a FileFormatException: "File contains corrupted data."
This isn't the same message you would get if decryption failed. I would expect that the stream that went in during encryption is the same one as the one that came out so any idea why the package would be corrupted?

Related

Encryption of file using algorithm Salsa20

I'm doing my homework. It's connected with encryption of file.
I use algorithm Salsa20
Here's my code:
using (var salsa = new Salsa20.Salsa20())
{
using (var fstream_out = new FileStream(filePath, FileMode.Truncate, FileAccess.ReadWrite, FileShare.Write))
{
salsa.Key = key;
salsa.IV = iv;
using (var cstream = new CryptoStream(fstream_out, salsa.CreateEncryptor(), CryptoStreamMode.Write))
{
var bytes = File.ReadAllBytes(filePath);
cstream.Write(bytes, 0, 1000000);
}
}
}
When I try to encrypt file, there's exception "The process cannot access the file because it is being used by another process."
What's wrong?

Encrypt and compress FileStream and save to same file

I have a method to compress and encrypt a stream.
private static void CompressThenEncrypt(string inputFileName, ICryptoTransform encryptor)
{
using (var inputFileStream = new FileStream(inputFileName, FileMode.Open, FileAccess.ReadWrite))
using (var cryptoStream = new CryptoStream(inputFileStream, encryptor, CryptoStreamMode.Write))
using (var zipStream = new GZipStream(cryptoStream, CompressionMode.Compress))
{
inputFileStream.CopyTo(zipStream);
}
}
Which does work, but it appends compressed and encrypted data to raw one I have in that file.
So if my file contains:
kkk
Then after compression and encryption it does look for example like that:
kkkㆆ鬁⠕⟶ꏙᇚ셑襜㷡ꕢ束৘㺝娥☪
Do anyone have any idea how to overwrite new data?
I suggest:
Write to a new file
Delete the old file
Rename the new file to the old file.
Write to a temporary MemoryStream. Something like:
private static void CompressThenEncrypt(string inputFileName, ICryptoTransform encryptor)
{
using (var fileStream = new FileStream(inputFileName,FileMode.Open, FileAccess.ReadWrite))
using (var memoryStream = new MemoryStream())
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
using (var zipStream = new GZipStream(cryptoStream, CompressionMode.Compress))
{
fileStream.CopyTo(zipStream);
cryptoStream.FlushFinalBlock();
fileStream.SetLength(0);
memoryStream.Position = 0;
memoryStream.CopyTo(fileStream);
}
}
I think that should work, from the top of my head. Not sure you would have to set the length, and I'm not sure you can get away with not resetting the position of the MemoryStream. I haven't tested this code. If you are concerned about memory usage, you can always buffer the usage, but that would require more complicated code.

Error about padding occurs during my attempt to decrypt string data from a FileStream using Rijndael

I'm trying to encrypt some strings (actually a walkaround for encrypt an XElement object) into a file using Rijndael. However when decrypting, a CryptographicException will be thrown with the message "Padding is invalid and cannot be removed".
I've been searching several posts for possible solutions, in which someone mentions the PaddingMode, the FlushFinalBlock() method, and others.
Also someone has mentioned that it's because reading directly from a FileStream will set the length of the stream to that of the file, thus leaving no room for padding, but I don't know how to resolve the issue. Please kindly give your suggestions.
var root = new XElement("Users",
new XElement("User", new XAttribute("id", "1"), "User1"),
new XElement("User", new XAttribute("id", "2"), "User2"));
var r = Rijndael.Create();
r.Padding = PaddingMode.PKCS7;
using (var fs = File.Open(#"D:\user.xml", FileMode.Create))
using (var cs = new CryptoStream(fs, r.CreateEncryptor(r.Key, r.IV), CryptoStreamMode.Write))
using (var sw = new StreamWriter(cs, Encoding.Unicode))
{
sw.Write(root.ToString());
cs.FlushFinalBlock();
}
var r = Rijndael.Create();
r.Padding = PaddingMode.PKCS7;
using(var fs = File.Open(#"D:\user.xml", FileMode.Open, FileAccess.ReadWrite))
using(var cs = new CryptoStream(fs, r.CreateDecryptor(r.Key, r.IV), CryptoStreamMode.Read))
using (var sr = new StreamReader(cs, Encoding.Unicode))
{
var root = sr.ReadToEnd();
}
I believe you need to flush the stream writer as well.
As a note, make sure you actually use a random IV ( which you are doing here). Sometimes people write code like this and then when the go to use it to decrypt the file later, the realize they don't have the IV and so they just hard code it. Just prepend it to the file.
{
sw.Write(root.ToString());
cs.FlushFinalBlock();
sw.flush();
}

how to encrypt/Decrypt .xlsx/.doc files with C#

I'm writing an application to Encrtpt/Decrypt files and using DESCryptoServiceProvider for this purpose. This seems to work for text files but when I use the same application for .xlsx file, the resulting encrypted file and the decrypted file get corrupted and I'm not able to open that any more. is there any way I can encryt / decrypt different kinds of file like .doc..xls etc.
update : added code for encryption/decryption
public static void EncryptFile(string filepath,string fileOutput, string key)
{
FileStream fsInput = new FileStream(filepath, FileMode.Open, FileAccess.Read);
FileStream fsEncrypted = new FileStream(fileOutput, FileMode.Create, FileAccess.Write);
DESCryptoServiceProvider DESc = new DESCryptoServiceProvider();
DESc.Key = ASCIIEncoding.ASCII.GetBytes(key);
DESc.IV = ASCIIEncoding.ASCII.GetBytes(key);
ICryptoTransform desEncrypt = DESc.CreateEncryptor();
CryptoStream cryptoStream = new CryptoStream(fsEncrypted, desEncrypt, CryptoStreamMode.Write);
byte[] byteArrayInput = new byte[fsInput.Length - 1];
fsInput.Read(byteArrayInput, 0, byteArrayInput.Length);
cryptoStream.Write(byteArrayInput, 0, byteArrayInput.Length);
cryptoStream.Close();
fsInput.Close();
fsEncrypted.Close();
}
public static void DecryptFile(string filepath, string fileOutput, string key)
{
DESCryptoServiceProvider DESc = new DESCryptoServiceProvider();
DESc.Key = ASCIIEncoding.ASCII.GetBytes(key);
DESc.IV = ASCIIEncoding.ASCII.GetBytes(key);
FileStream fsread = new FileStream(filepath, FileMode.Open, FileAccess.Read);
ICryptoTransform desDecrypt = DESc.CreateDecryptor();
CryptoStream cryptoStreamDcr = new CryptoStream(fsread, desDecrypt, CryptoStreamMode.Read);
StreamWriter fsDecrypted = new StreamWriter(fileOutput);
fsDecrypted.Write(new StreamReader(cryptoStreamDcr).ReadToEnd());
fsDecrypted.Flush();
fsDecrypted.Close();
}
static void Main(string[] args)
{
EncryptFile(#"C:\test1.xlsx", #"c:\test2.xlsx", "ABCDEFGH");
DecryptFile(#"C:\test2.xlsx", #"c:\test3.xlsx", "ABCDEFGH");
}
You are not encrypting or decrypting correctly. Encrypt -> Decrypt will always give a file identical to the input. If you post your code we may be able to assist in finding the bug in it.
You should use FileStreama as suggested in one of the comments by Kieren Johnstone. Also, you're not flushing the streams when encrypting - this may not be done automatically, so you should try and flush the streams, too.

Is there a .NET encryption library that implements AES 256 encryption as a Stream?

I'd like to be able to encrypt / decrypt data as it's streamed to/from disk.
I know I could write my own Stream and implement the encryption there, but I'd rather not risk doing it wrong. Is there a library that works in a similar way to the following code?
byte[] encryptionKey = ;
byte[] initVector = ;
var fileStream = new FileStream(filePath, FileMode.CreateNew, FileAccess.Write);
var encryptionStream = new AesEncryptionStream(fileStream, initVector, encryptionKey);
var gzStream = new GZipStream(encryptionStream, CompressionMode.Compress);
var writer = new BinaryWriter(gzStream);
You're looking for the RijndaelManaged and CryptoStream classes:
var aes = new RijndaelManaged { Key = ..., IV = ... };
using (var encryptor = aes.CreateEncryptor())
using (var cryptoStream = new CryptoStream(gzStream, encryptor, CryptoStreamMode.Write))
using (var writer = new BinaryWriter(cryptoStream)) {
...
}

Categories