0

I've had troubles using an CryptoStream for my file encryption..

Code:

public static void EncryptFile(string inputFile, string outputFile)
    {
        int num;
        string s = "PUPlr";
        byte[] bytes = new UnicodeEncoding().GetBytes(s);
        string path = outputFile;
        FileStream stream = new FileStream(path, FileMode.Create);
        RijndaelManaged managed = new RijndaelManaged();
        CryptoStream crpytStream = new CryptoStream(stream, managed.CreateEncryptor(bytes, bytes), CryptoStreamMode.Write);
        FileStream stream2 = new FileStream(inputFile, FileMode.Open);
        while ((num = stream2.ReadByte()) != -1)
        {
            crpytStream.WriteByte((byte)num);
        }
        stream2.Close();
        crpytStream.Close();
        stream.Close();
    }

Trying "managed.BlockSize = 16;" or "= 128;" doesn't seem to work, so how could I fix my error?

svick
  • 236,525
  • 50
  • 385
  • 514
Adam M
  • 113
  • 3
  • 13
  • You should copy blocks (`new byte[4096]`) at a time, not single bytes; it will be much faster. – SLaks Apr 25 '12 at 19:46
  • 6
    SLaks is correct; the fact that you are unable to determine the problem from the clear description in the exception is indicative that you do not know enough about cryptography to correctly and safely use this tool. My advice is that you hire an expert who can write your crypto code and train you how to maintain it safely. Trying to use the same bytes as the message and the initialization is *crazy dangerous*. Attackers live for mistakes like that. – Eric Lippert Apr 25 '12 at 19:53
  • I wasn't simply going for any security, just to encrypt some player data (some Colors, some strings, ints, a double, float) and I thought that using this in addition to using a BinaryWriter/reader would help a lot. – Adam M Apr 25 '12 at 20:02
  • 5
    If you don't have a security purpose then **do not use a security technology in the first place**. (Incidentally, the incorrect use of initialization vectors by a large number of people who did not understand crypto well enough is one of the factors that prevented Germany from winning the Second World War. See http://en.wikipedia.org/wiki/Enigma_machine#Indicator for details.) – Eric Lippert Apr 25 '12 at 20:18
  • 3
    Ever notice that on almost every cryptography question the majority of replies feel the need to insult the OP's lack of knowledge instead of just answering the question? Then on top of it they get up-voted for doing so.. Fairly redundant going around pointing out the lack of knowledge on every post on a Q/A site.. – TugboatCaptain Aug 12 '13 at 16:59

4 Answers4

4

Block cyphers like Rijndael require keys and IVs of length equal to the block size, typically 256 bits.

In addition, the IV must be unique for each message, or your data will not be secure.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
2

The error is:

managed.CreateEncryptor(bytes, bytes)

where the bytes needs to be either 128 bits (16 bytes), 192 bits (24 bytes) or 256 bits (32 bytes) for the first (Key) and second parameter.

Notes:

  • for AES interoperability you should use Rijndael with a BlockSize of 128 bits (16 bytes).

  • UnicodeEncoding will (often) give you weak password. Look at using PKCS#5 to create a strong key (and IV) from a password. For .NET look at RFC2898DeriveBytes;

  • avoid using the same data for both the key and IV;

poupou
  • 43,413
  • 6
  • 77
  • 174
0

This line here:

managed.CreateEncryptor(bytes, bytes)

Doesn't work. The first parameter is a key, and the second parameter is an initialization vector. If your intention was to use the string s as a "password" or key, try using Rfc2898DeriveBytes to generate a key from a password.

vcsjones
  • 138,677
  • 31
  • 291
  • 286
0
public static void EncryptFile(string input, string output)
{
    string theKey = "urKey";
    byte[] salt = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c };
    Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(theKey, salt);
    RijndaelManaged RMCrypto = new RijndaelManaged();
    using (var inputStream=new FileStream(input))
        using (var outputStream = new FileStream(output))
            using (CryptoStream cs = new CryptoStream(inputStream, RMCrypto.CreateEncryptor(pdb.GetBytes(32), pdb.GetBytes(16)), CryptoStreamMode.Read))
            {
                byte[] buffer = new byte[1024];
                int bytesRead = 0;
                do
                {
                    bytesRead = cs.Read(buffer, 0, buffer.Length);
                    outputStream.Write(buffer, 0, bytesRead);
                } while (bytesRead > 0);
            }
}