2

I'm trying to make an encryption system with c#. This is the code for the encryption.

public static void EncryptFile(string inFile, string outFile, string @inkey)
    {
        try
        {
            UnicodeEncoding ue = new UnicodeEncoding();
            byte[] key = ue.GetBytes(inkey);
            FileStream fsEncrypt = new FileStream(outFile, FileMode.Create);

            RijndaelManaged rmCrypto = new RijndaelManaged();

            CryptoStream cs = new CryptoStream(fsEncrypt, rmCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write);
            FileStream fsIn = new FileStream(inFile, FileMode.Open);

            int data;
            while((data=fsIn.ReadByte()) != 1){
                cs.WriteByte((byte)data);
            }

            fsIn.Close(); cs.Close(); fsEncrypt.Close();
        }
        catch(Exception ex)
        {
            MessageBox.Show(ex.Message, "Fail to encrypt", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

Now, this code throws exception every time I run it, says

Specified initialization vector(IV) does not match the block size for this algorithm

I have read on other discussion about this, saying that there is a problem with the number of bytes (my key length passed into this function is 255). But I have tried making the key only 16 bytes and still not working.

After some troubleshooting I found out that this part:

CryptoStream cs = new CryptoStream(fsEncrypt, rmCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write);

throws the exception. I have no idea why. Anyone can help?

horgh
  • 17,918
  • 22
  • 68
  • 123
user2002495
  • 2,126
  • 8
  • 31
  • 61
  • 1
    I havn't heard about 255-bit keys. Perhaps try 256? – Grzegorz W Feb 22 '13 at 07:53
  • 1
    btw. using a password directly as key isn't a good idea. You should either use a randomly generated binary key(recommended unless you have a user entered password), or a password based key derivation function(expensive). – CodesInChaos Feb 22 '13 at 09:23

1 Answers1

6

You're passing the key twice to CreateEncryptor, but it needs a key and an IV (Initialization Vector). The second parameter should be an array with 128 random bits. 128 bits is the default block size for RijndaelManaged, but it accepts other values as well (such as 256). Read this for more info. And as Grzegorz W pointed out in the comments, you might need to choose a different key size as well.

If you're not familiar with encryption (in which case you should stop and learn more about it before implementing your own solution, or use a ready-made one instead), the function of the IV is prevent that the same message encoded twice produce the same ciphertext. It should be random for each message (and each use of the message), does not need to be kept secret, but you need to store it to be able to decipher the message later (i.e. you can not discard it after encryption).

Community
  • 1
  • 1
mgibsonbr
  • 21,755
  • 7
  • 70
  • 112
  • 1
    You mean 128 *bits*... or 16 bytes. – Duncan Jones Feb 22 '13 at 07:55
  • @mgibsonbr: so the iv is pretty much like salt used to encrypt and decrypt password used in website forms? Where the encrypt method is like sha256 that requires salt, we still need to use the same salt when we need to decrypt the password? – user2002495 Feb 22 '13 at 08:31
  • @user2002495 yes, salt and IV have a similar function (although you don't actually decrypt passwords, since hashes are a one-way operation; instead, you simply hash the password candidate - using the same salt - and then compare the result with the stored password hash). There are [modes of operation](http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation) that does not need IVs though, such as XTS (used in TrueCrypt), but I'm not experienced enough in the subject to say more about it. – mgibsonbr Feb 22 '13 at 08:39
  • 1
    While Rijndael supports block sizes other than 16 bytes, it's no longer AES if you do that. – CodesInChaos Feb 22 '13 at 09:21