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?
Related
My problem is that the created encrypted zip file is unable to open after decrypting it. It says the compressed file is invalid. File it self almost doubled it's initial space after decrypting from 15 KB to 27 KB. The problem occours on zip files, when I encrypted and decryped a xml file it worked just fine. Below my whole code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace EDI
{
public class EncryptionHelper
{
public void Main()
{
var file = #"C:\Temp\test.zip";
AesCryptoServiceProvider AES = new AesCryptoServiceProvider();
AES.Padding = PaddingMode.PKCS7;
AES.Mode = CipherMode.CBC;
AES.BlockSize = 128;
AES.KeySize = 128;
AES.GenerateKey();
AES.GenerateIV();
var key = AES.Key;
var iv = AES.IV;
encryptAES(AES, file, key, iv);
decryptAES(AES, file + ".encrypted", key, iv);
}
public void encryptAES(SymmetricAlgorithm algo, string filePath, byte[] key, byte[] IV)
{
using (FileStream fin = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (FileStream fout = new FileStream(filePath + ".encrypted", FileMode.OpenOrCreate, FileAccess.Write))
{
using (ICryptoTransform crypt = algo.CreateEncryptor(key, IV))
{
using (CryptoStream crStream = new CryptoStream(fout, crypt, CryptoStreamMode.Write))
{
fin.CopyTo(crStream);
}
}
}
}
}
public void decryptAES(SymmetricAlgorithm algo, string filePath, byte[] key, byte[] IV)
{
using (FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (ICryptoTransform crypt = algo.CreateDecryptor(key, IV))
{
using (CryptoStream crStream = new CryptoStream(fStream, crypt, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(crStream))
{
string data = reader.ReadToEnd();
File.WriteAllText(filePath.Replace(".encrypted", ".restored"), data);
}
}
}
}
}
}
}
Edit to show the fix.
using (FileStream writer = new FileStream(filePath + ".decrypted", FileMode.Create, FileAccess.Write))
// using (Read reader = new StreamReader(crStream))
{
// string data = reader.ReadToEnd();
// File.WriteAllText(filePath.Replace(".encrypted", ".restored"), data);
crStream.CopyTo(writer);
}
Hey all I am trying to serialize a list of strings to a file, and then encrypt it.
Currently its just not working.
An unhandled exception of type 'System.Runtime.Serialization.SerializationException' occurred in mscorlib.dll
Additional information: Binary stream '199' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.
Then I need to decrypt and deseralize it. Heres what I have so far:
Encrypting and seralizing:
public void EncryptFile(FileInfo targetFile, string password, List<string> lines)
{
int SaltSize = 8;
var keyGenerator = new Rfc2898DeriveBytes(password, SaltSize);
var rijndael = Rijndael.Create();
// BlockSize, KeySize in bit --> divide by 8
rijndael.IV = keyGenerator.GetBytes(rijndael.BlockSize / 8);
rijndael.Key = keyGenerator.GetBytes(rijndael.KeySize / 8);
using (var fileStream = targetFile.Create())
{
// write random salt
fileStream.Write(keyGenerator.Salt, 0, SaltSize);
using (var cryptoStream = new CryptoStream(fileStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write))
{
var bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
bformatter.Serialize(fileStream, lines);
}
}
}
And un-seralizing and decrypting:
int SaltSize = 8;
Dictionary<string, string> settings = new Dictionary<string, string>();
var fileStream = File.Open(SettingsFile, FileMode.Open);
var salt = new byte[SaltSize];
fileStream.Read(salt, 0, SaltSize);
// initialize algorithm with salt
var keyGenerator = new Rfc2898DeriveBytes("Y8LwUKQVJkqRz2ZAKsAMtFWY", salt);
var rijndael = Rijndael.Create();
rijndael.IV = keyGenerator.GetBytes(rijndael.BlockSize / 8);
rijndael.Key = keyGenerator.GetBytes(rijndael.KeySize / 8);
// decrypt
using (var cryptoStream = new CryptoStream(fileStream, rijndael.CreateDecryptor(), CryptoStreamMode.Read))
{
var bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
List<string> settingsList = (List<string>)bformatter.Deserialize(cryptoStream);
foreach (string setting in settingsList)
{
string[] bothWords = setting.Split(',');
settings.Add(bothWords[0], bothWords[1]);
}
}
The problem I see is that you aren't actually encrypting your data. The way I like to picture the encryption process is imagining a CryptoStream as a magical "portal" that encrypts/decrypts data. In order to encrypt or decrypt, you need to push or pull data through the "portal" from one side to the other.
A simple change to your encrypting code should do the trick:
Before
using (var fileStream = targetFile.Create())
{
// write random salt
fileStream.Write(keyGenerator.Salt, 0, SaltSize);
using (var cryptoStream = new CryptoStream(fileStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write))
{
var bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
bformatter.Serialize(fileStream, lines);
}
}
After
using (var fileStream = targetFile.Create())
{
// write random salt
fileStream.Write(keyGenerator.Salt, 0, SaltSize);
using (var cryptoStream = new CryptoStream(fileStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write))
{
var bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
bformatter.Serialize(cryptoStream, lines); //changed the input stream to 'cryptoStream'
cryptoStream.FlushFinalBlock(); //added a call to FlushFinalBlock
}
}
You can kinda imagine the relationships here between everything. The fileStream is behind the cryptoStream. The Serialize method is "pushing" the data from lines, through the cryptoStream (the "portal"), and into the fileStream.
As an aside, disposing of your IDisposable objects is fairly important. Make sure to either call Dispose() on them or (better yet) put them into a using statement. The Rfc2898DeriveBytes and Rijndael objects you are using aren't being disposed of.
I have these two methods which are pretty much copy+pastes from http://support.microsoft.com/kb/307010.
When I decrypt the files, if they are any type of text file such as .txt, .xml, .html, etc. I can open them up and everything is fine. Any type of file not just text, such as .exe, .jpg, .pdf, etc. all break when decrypted. Is there anything I am doing wrong? Are these methods using binary to encrypt/decrypt the files? If not is there a way I can make it binary?
Any help is greatly appreciated!
public static void EncryptFile(string sInputFilename,
string sOutputFilename,
string sKey)
{
FileStream fsInput = new FileStream(sInputFilename,
FileMode.Open,
FileAccess.Read);
FileStream fsEncrypted = new FileStream(sOutputFilename,
FileMode.Create,
FileAccess.Write);
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
ICryptoTransform desencrypt = DES.CreateEncryptor();
CryptoStream cryptostream = new CryptoStream(fsEncrypted,
desencrypt,
CryptoStreamMode.Write);
byte[] bytearrayinput = new byte[fsInput.Length];
fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);
cryptostream.Close();
fsInput.Close();
fsEncrypted.Close();
}
public static void DecryptFile(string sInputFilename,
string sOutputFilename,
string sKey)
{
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
//A 64 bit key and IV is required for this provider.
//Set secret key For DES algorithm.
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
//Set initialization vector.
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
//Create a file stream to read the encrypted file back.
FileStream fsread = new FileStream(sInputFilename,
FileMode.Open,
FileAccess.Read);
//Create a DES decryptor from the DES instance.
ICryptoTransform desdecrypt = DES.CreateDecryptor();
//Create crypto stream set to read and do a
//DES decryption transform on incoming bytes.
CryptoStream cryptostreamDecr = new CryptoStream(fsread,
desdecrypt,
CryptoStreamMode.Read);
//Print the contents of the decrypted file.
StreamWriter fsDecrypted = new StreamWriter(sOutputFilename);
fsDecrypted.Write(new StreamReader(cryptostreamDecr).ReadToEnd());
fsDecrypted.Flush();
fsDecrypted.Close();
fsread.Close();
cryptostreamDecr.Close();
}
I don't know what the guy that wrote that article was smoking, but:
DESCryptoServiceProvider desCrypto =
(DESCryptoServiceProvider)DESCryptoServiceProvider.Create();
return ASCIIEncoding.ASCII.GetString(desCrypto.Key);
will not get you a valid key. At least one problem is the fact that the key you use to encrypt is not the same key that you're using to decrypt, because you can't convert bytes to ASCII and back like that.
If you want to treat the key as a string, what you probably want is:
string keyAsString = Convert.ToBase64String(desCrypto.Key);
Then when you want to turn it back into bytes, instead of ASCIIEncoding.ASCII.GetBytes, you'll do:
byte[] key = Convert.FromBase64String(keyAsString);
EDIT
There's a ton more wrong with that article too. I'd say ignore that one and find a better example.
EDIT
Here's a very clean basic AES working example that I use for my standard encryption needs. Some of the major improvements over the article are:
Proper creation of a key
Current algorithm (AES 256-bit key)
Random IV
Buffered file access instead of reading/writing the entire file in one chunk
Wrapping all the disposable objects in using
Aside from that, it's the same basic idea.
using System;
using System.IO;
using System.Security.Cryptography;
namespace ConsoleApplication12
{
class Program
{
private const int KEY_SIZE_BYTES = 32;
private const int IV_SIZE_BYTES = 16;
static void Main(string[] args)
{
var rand = new Random();
using (var fs = File.Open(#"C:\temp\input.bin", FileMode.Create, FileAccess.Write, FileShare.None))
{
byte[] buffer = new byte[10000];
for (int i = 0; i < 100; ++i)
{
rand.NextBytes(buffer);
fs.Write(buffer, 0, buffer.Length);
}
}
string key = GenerateRandomKey();
Encrypt(#"C:\temp\input.bin", #"C:\temp\encrypted.bin", key);
Decrypt(#"C:\temp\encrypted.bin", #"C:\temp\decyrypted.bin", key);
}
static string GenerateRandomKey()
{
byte[] key = new byte[KEY_SIZE_BYTES];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(key);
}
return Convert.ToBase64String(key);
}
static void Encrypt(string inputFile, string outputFile, string key)
{
const int BUFFER_SIZE = 8192;
byte[] buffer = new byte[BUFFER_SIZE];
byte[] keyBytes = Convert.FromBase64String(key);
byte[] ivBytes = new byte[IV_SIZE_BYTES];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(ivBytes);
}
using (var inputStream = File.Open(inputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var outputStream = File.Open(outputFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
outputStream.Write(ivBytes, 0, ivBytes.Length);
using (var cryptoAlgo = Aes.Create())
{
using (var encryptor = cryptoAlgo.CreateEncryptor(keyBytes, ivBytes))
{
using (var cryptoStream = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write))
{
int count;
while ((count = inputStream.Read(buffer, 0, buffer.Length)) > 0)
{
cryptoStream.Write(buffer, 0, count);
}
}
}
}
}
}
}
static void Decrypt(string inputFile, string outputFile, string key)
{
const int BUFFER_SIZE = 8192;
byte[] buffer = new byte[BUFFER_SIZE];
byte[] keyBytes = Convert.FromBase64String(key);
byte[] ivBytes = new byte[IV_SIZE_BYTES];
using (var inputStream = File.Open(inputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
inputStream.Read(ivBytes, 0, ivBytes.Length);
using (var outputStream = File.Open(outputFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (var cryptoAlgo = Aes.Create())
{
using (var decryptor = cryptoAlgo.CreateDecryptor(keyBytes, ivBytes))
{
using (var cryptoStream = new CryptoStream(inputStream, decryptor, CryptoStreamMode.Read))
{
int count;
while ((count = cryptoStream.Read(buffer, 0, buffer.Length)) > 0)
{
outputStream.Write(buffer, 0, count);
}
}
}
}
}
}
}
}
}
Because the IV is random, you'll see another small difference in technique. When encrypting the file, you first write the IV to the encrypted file (it's not a secret, so you just write it straight out). When decrypting the file, you read the first few bytes to retrieve the IV, then the rest of the file contains the actual encrypted data. The purpose of a random IV is so the same plaintext file will encrypt into a different encrypted file every time you run it.
The Main method here demonstrates encryption with a random key. If you want to use a password, it's a little more work, but you can implement PBKDF2 with maybe a dozen or so extra lines of code.
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?
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)) {
...
}