-3

I use Serialize function to save an object to hard disk by the following code:

using (FileStream fs = new FileStream(fileName, FileMode.Create))
                    new BinaryFormatter().Serialize(fs, myObject);

Then I reload it again when I need it:

using(FileStream fs = new FileStream(fileName, FileMode.Open))
                    myObject = (Templates)new BinaryFormatter().Deserialize(fs);

I'm searching an easy way to encrypt the file I save to protect it and also fast way because the time factor in saving and reading the file is very important.

Any suggestions please, thank you in advance!

  • https://www.google.co.uk/search?q=C%23+encrypt+file&oq=C%23+encrypt+file&aqs=chrome..69i57j69i58j0l4.2538j0j7&sourceid=chrome&ie=UTF-8 contains a lot of useful-looking results. Did you try any of them? – ADyson Sep 04 '17 at 17:51
  • @ADyson Thank you, I'm taking a look – Waleed ELerksosy Sep 04 '17 at 17:52
  • So you think your encryption and decryption will take significantly more time then your file I/O? – rene Sep 04 '17 at 17:54
  • @rene I've no idea how to do encryption and decryption for the file. – Waleed ELerksosy Sep 04 '17 at 17:57
  • You could use `CryptoStream`. See [C# Encrypt serialized file before writing to disk](https://stackoverflow.com/a/5870397/3744182) or [C# - Serializing/Deserializing a DES encrypted file from a stream](https://stackoverflow.com/q/965042/3744182). – dbc Sep 04 '17 at 17:59
  • @dbc Thank you these links helped me a lot! – Waleed ELerksosy Sep 04 '17 at 18:02

1 Answers1

1

Here I made a simple self-contained program.cs example on how to encrypt and decrypt data:

using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Text.Json;

var fileName = "testfile.txt";

if(!File.Exists(fileName)) {
    File.WriteAllText(fileName, "Hello World!");
}

// generate random key and iv
var key = new byte[32];
var iv = new byte[16];
using (var rng = RandomNumberGenerator.Create()) {
    rng.GetBytes(key);
    rng.GetBytes(iv);
}

var aes = Aes.Create();
aes.Key = key;
aes.IV = iv;

var data = File.ReadAllBytes(fileName);

// Save
using (FileStream fs = new FileStream(fileName + ".encrypted", FileMode.Create)) {
    using (CryptoStream cs = new CryptoStream(fs, aes.CreateEncryptor(), CryptoStreamMode.Write)) {
        await cs.WriteAsync(data, 0, data.Length);
    }
}

// Load
using (FileStream fs = new FileStream(fileName + ".encrypted", FileMode.Open)) {
    using (CryptoStream cs = new CryptoStream(fs, aes.CreateDecryptor(), CryptoStreamMode.Read)) {
        // get data from encrypted file and write a new file
        using (FileStream fs2 = new FileStream(fileName + ".decrypted", FileMode.Create)) {
            await cs.CopyToAsync(fs2);
        }
    }
}

You can use any other algorithm instead, as long as it can return an ICrytoTransform, like the aes.CreateEncryptor() method (which is inherited from SymmetricAlgorithm)

Also, I am editing this in 2023 (originally posted in 2017) and I would strongly recommend using JSON serialization instead of BinaryFormatter

Felype
  • 3,087
  • 2
  • 25
  • 36
  • Thank you, can you please advise me how should be aes.Key and aes.IV – Waleed ELerksosy Sep 04 '17 at 18:23
  • An array of 16 bytes. The Key is something that should be unique to your application or whatever owns this file, the IV should ideally be unique per "cryptographed thing" – Felype Sep 04 '17 at 18:30
  • I got it, thank you :) – Waleed ELerksosy Sep 04 '17 at 18:52
  • 1
    @WaleedELerksosy - For the IV maybe see [Good AES Initialization Vector practice](https://stackoverflow.com/q/8041451) – dbc Sep 04 '17 at 18:59
  • @dbc I got it, I'm reading about. Thank you – Waleed ELerksosy Sep 04 '17 at 20:13
  • Thanks. This is a really nice and simple version that works really well. – AH. Jul 12 '19 at 12:00
  • I know its an old thread but if the author can reply to the fact that i can encrypt + serialize using this code but when i try to decrypt + deserialize, it gives me the following error " The input stream is not a valid binary format. The starting contents (in bytes) are: CB-56-04-1E-BE-6E-7D-A1-26-B5-74-0D-6F-FA-D2-67-84 " Any advice will be greatly appreciated. – Tiyyob Feb 21 '23 at 08:02
  • @Tiyyob i see, this answer is indeed VERY old, I believe your problem is that your class changed and the serialized data is no longer valid, I now in retrospect strongly suggest using JSON serialization instead of `BinaryFormatter` for that reason. Change `new BinaryFormatter().Serialize` for `JsonConvert.SerializeObject` and `(Templates) new BinaryFormatter().Deserialize` for `JsonConvert.DeserializeObject` . This if you're using Json.Net, or `JsonSerializer.Serialize` and `JsonSerializer.Deserialize` respectively if using System.Text.Json. Sorry for the inconvenience – Felype Feb 25 '23 at 15:45
  • @Tiyyob I have edited that answer, I really had a particularly wrong detail in it, see if that helps – Felype Feb 25 '23 at 16:02