2

i have the following utility functions to Serialize my objects to encrypted byte array and also to deserialize from decrypted byte array

//encryption key
public static byte[] Key = new byte[]{0x43, 0x72, 0x6e, 0x6d, 0x54, 0x4d, 0x65,
                                      0x94, 0x16, 0x32, 0x44, 0x84, 0x7e, 0x18,
                                      0x64, 0x76, 0x6e, 0x63, 0x64, 0x7a, 0x5f,
                                      0x84, 0x7f, 0x9a};

//Decrypt byte[]
public static byte[] Decrypt(byte[] data)
{
    MemoryStream ms = new MemoryStream();
    Rijndael alg = Rijndael.Create();
    alg.Key = Key;
    CryptoStream cs = new CryptoStream(ms,
    alg.CreateDecryptor(), CryptoStreamMode.Write);
    cs.Write(data, 0, data.Length);
    cs.Close();
    byte[] decryptedData = ms.ToArray();
    return decryptedData;
}

//Encrypt byte[]
public static byte[] Encrypt(byte[] data)
{
    MemoryStream ms = new MemoryStream();
    Rijndael alg = Rijndael.Create();
    alg.Key = Key;
    CryptoStream cs = new CryptoStream(ms,
    alg.CreateEncryptor(), CryptoStreamMode.Write);
    cs.Write(data, 0, data.Length);
    cs.Close();
    byte[] encryptedData = ms.ToArray();
    return encryptedData;
}

//serialize object to memory stream
public static MemoryStream SerializeToStream(object o)
{
    MemoryStream stream = new MemoryStream();
    IFormatter formatter = new BinaryFormatter();
    formatter.Serialize(stream, o);
    return stream;
}

//deserialize object from memory stream
public static T DerializeFromStream<T>(MemoryStream memoryStream) where T : new()
{
    if (memoryStream == null) { return new T(); }
    T o;
    BinaryFormatter binaryFormatter = new BinaryFormatter();
    using (memoryStream)
    {
        memoryStream.Seek(0, SeekOrigin.Begin);
        o = (T)binaryFormatter.Deserialize(memoryStream);
    }
    return o;
}

and here is a test using the above utility functions

//serialize to stream then to byte array
var obj = new SomeObject();
var bytes = SerializeToStream(obj).ToArray();
bytes = Encrypt(bytes);

//deserialize to decrypted byte array then to stream then to object
var memoryStream = new MemoryStream();
var Decryptedbytearray = Decrypt(bytes);
//fille the stream
memoryStream.Write(Decryptedbytearray, 0, Decryptedbytearray.Length);
//deserialize the object from the stream
//it fails here giving an exception saying the binary data is not valid
var obj2 = DerializeFromStream<SomeObject>(memoryStream);

the problem comes when deserializing the object, see the commented last line, what am i doing wrong?

chwarr
  • 6,777
  • 1
  • 30
  • 57
FPGA
  • 3,525
  • 10
  • 44
  • 73

2 Answers2

4

If you debug your code you'll see that it is not decrypting correctly. The reason is that you have to use not only the same key, but also the same IV.

From MSDN:

The IV property is automatically set to a new random value whenever you create a new instance of one of the SymmetricAlgorithm classes or when you manually call the GenerateIV method. The size of the IV property must be the same as the BlockSize property divided by 8.

Take a look at this question for details on how to create a key and a IV from a passphrase.

Community
  • 1
  • 1
Julián Urbano
  • 8,378
  • 1
  • 30
  • 52
0

There is an easy way to generate an encrypted version of a byte array.

Have a look at this code sniped that is part of a secure Baseclass , it is designed to have limited access to a array, this one encrypts at an instance level. When looking at it you will get the idea that actually when you change the "salt" you can change the scope quite easely. I catch the errors and do not propage them, this can be considered bad coding however providing an error makes it so much easyer for hackers to understand how to by pass what ever it is you are trying to protect..., here is the code:

internal class Protected
{
    private  Byte[] salt = Guid.NewGuid().ToByteArray();

    protected byte[] Protect(byte[] data)
    {
        try
        {
            return ProtectedData.Protect(data, salt, DataProtectionScope.CurrentUser);
        }
        catch (CryptographicException)//no reason for hackers to know it failed
        {
#if DEBUG
            throw;
#else
            return null;
#endif
        }
    }

    protected byte[] Unprotect(byte[] data)
    {
        try
        {
            return ProtectedData.Unprotect(data, salt, DataProtectionScope.CurrentUser);
        }
        catch (CryptographicException)//no reason for hackers to know it failed
        {
#if DEBUG
            throw;
#else
            return null;
#endif
        }
    }
}

The class ProtectedData comes from a namespace System.Security.Cryptography and can be found in NuGet package System.Security.Cryptography.ProtectedData in Core 2.0

Walter Verhoeven
  • 3,867
  • 27
  • 36