Reputation: 15378
I have code function
public static void DecryptFile(string inFile, string outFile, string password)
{
// create and open the file streams
using (FileStream fin = File.OpenRead(inFile),
fout = File.OpenWrite(outFile))
{
int size = (int)fin.Length; // the size of the file for progress notification
byte[] bytes = new byte[BUFFER_SIZE]; // byte buffer
int read = -1; // the amount of bytes read from the stream
int value = 0;
int outValue = 0; // the amount of bytes written out
// read off the IV and Salt
byte[] IV = new byte[16];
fin.Read(IV, 0, 16);
byte[] salt = new byte[16];
fin.Read(salt, 0, 16);
// create the crypting stream
SymmetricAlgorithm sma = CryptoHelp.CreateRijndael(password, salt);
sma.IV = IV;
value = 32; // the value for the progress
long lSize = -1; // the size stored in the input stream
// create the hashing object, so that we can verify the file
HashAlgorithm hasher = SHA256.Create();
// create the cryptostreams that will process the file
using (CryptoStream cin = new CryptoStream(fin, sma.CreateDecryptor(), CryptoStreamMode.Read),
chash = new CryptoStream(Stream.Null, hasher, CryptoStreamMode.Write))
{
// read size from file
BinaryReader br = new BinaryReader(cin);
lSize = br.ReadInt64();
ulong tag = br.ReadUInt64();
if (FC_TAG != tag)
throw new CryptoHelpException("File Corrupted!");
//determine number of reads to process on the file
long numReads = lSize / BUFFER_SIZE;
// determine what is left of the file, after numReads
long slack = (long)lSize % BUFFER_SIZE;
// read the buffer_sized chunks
for (int i = 0; i < numReads; ++i)
{
read = cin.Read(bytes, 0, bytes.Length);
fout.Write(bytes, 0, read);
chash.Write(bytes, 0, read);
value += read;
outValue += read;
}
// now read the slack
if (slack > 0)
{
read = cin.Read(bytes, 0, (int)slack);
fout.Write(bytes, 0, read);
chash.Write(bytes, 0, read);
value += read;
outValue += read;
}
// flush and close the hashing stream
chash.Flush();
chash.Close();
// flush and close the output file
fout.Flush();
fout.Close();
// read the current hash value
byte[] curHash = hasher.Hash;
// get and compare the current and old hash values
byte[] oldHash = new byte[hasher.HashSize / 8];
read = cin.Read(oldHash, 0, oldHash.Length);
if ((oldHash.Length != read) || (!CheckByteArrays(oldHash, curHash)))
throw new CryptoHelpException("File Corrupted!");
}
// make sure the written and stored size are equal
if (outValue != lSize)
throw new CryptoHelpException("File Sizes don't match!");
}
}
I need return FileStream (fout) and fout not save to hard disk
UPDATE:
YES, MemoryStream is good. but then I will need to use the FileStream otherwise an error occurs:
not work:
using (ZipInputStream s = new ZipInputStream(fout))
{
ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null)//exception
is work:
using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipFile)))
{
ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null)
I need to decrypt the file, unzip it and then still get the text without saving
Upvotes: 3
Views: 4316
Reputation: 25834
I recommend changing your method signature to:
public static void DecryptFile(string inFile, string password, Stream outStream)
or
public static void DecryptFile(string inFile, string password, string outFile)
(The 2nd can be implemented very easily by just calling the first with a FileStream
parameter).
This leaves the responsibility of creating the Stream
with the caller, which has the advantage over Oded's solution that it does not necessarily store the entire output in memory; the user can choose to provide a Stream
that consumes the output as it is provided. This may be important if the file being decrypted is especially large.
Upvotes: 3
Reputation: 499002
Don't use a second FileStream
. You can use a MemoryStream
instead.
using (FileStream fin = File.OpenRead(inFile))
using(Stream fout = new MemoryStream())
...
Upvotes: 10