locked
File encryption using RijndaelManaged. Only 8 char password limitation RRS feed

  • Question

  • Hi. Im using RijndaelManaged to encrypt/decrypt files. It only works if the password is 8 characters long. Is there a way or method to use longer password to add more security?
    Friday, April 20, 2012 10:11 PM

Answers

  • The key size is not the problem here, except for the fact that you are attempting to use the same key also for the initialization vector (IV).

    The block size of the algorithm does not need to match the key size, but it must match the size of the IV, which is why you are getting the error. A quick solution that would allow you to use a 256 key (i.e. a 16 character string) would require a very small change in your code:

          RijndaelManaged RMCrypto = new RijndaelManaged {
            BlockSize = 256
          };

    This would leave a number of open issues, though:

    - you would still be forced to a provide string with an exact number of characters;

    - you are wasting several bits of your keys as using latin characters for the password leaves you with lots of 0x00 bytes in the key;

    - I also suspect that using the very same bytes for the key and the IV would weaken the algorithm as it might provide hints for the cracker. I don't have the hard math for that, but I would rather be on the safe side here.

    As I mentioned in my earlier post, I would suggest something like this instead:

          string password = "a string of arbitrary length";
          string keySalt = "KEYSALT"; // an arbitrary constant string to randomize the hash
          string ivSalt = "IVSALT"; // another arbitrary constant string to generate a different hash
          byte [] key = SHA256.Create ().ComputeHash (Encoding.Unicode.GetBytes (keySalt + password));
          byte [] iv = SHA256.Create ().ComputeHash (Encoding.Unicode.GetBytes (ivSalt + password)).Take (16).ToArray ();
          FileStream cryptedFileStream = new FileStream ("EncryptedFile", FileMode.Create);
          RijndaelManaged RMCrypto = new RijndaelManaged ();
          CryptoStream cryptoStream = new CryptoStream (cryptedFileStream, RMCrypto.CreateEncryptor (key, iv), CryptoStreamMode.Write);

    This would address all the points above: the password can now have an arbitrary length; we create a 256 bit hash from the salted password to use as the key, using the full strength of 256 bits, and a separate 128 bit hash from a (differently) salted password to use as the IV.

    HTH
    --mc


    • Edited by Mario Cossi Saturday, April 21, 2012 1:06 AM
    • Marked as answer by GaiusBaltar Saturday, April 21, 2012 6:31 AM
    Saturday, April 21, 2012 1:03 AM

All replies

  • Hi, I don't know why you are experiencing that limitation; the key used in RijndaelManaged is not expressed in characters, but even assuming you are using Unicode (UTF-16) to convert the characters to bytes, that would give a 16 byte (128 bit) key, while RijndaelManaged also supports 256 bit keys. I suspect the limit derives from the code you are using for the encoding. Try posting that code, if possible.

    At any rate, I would advise against using a password directly as the key: aside of the cumbersome length limitation, a password is usually easier to crack using dictionary attacks and the like, which is far weaker than the number of bits would suggest.

    A possible solution would be to compute a hash of the password and use those bytes as the key of your encoder. SHA256 can be effectively used to create a 32 byte hash of any string, for instance.

    HTH
    --mc

    Friday, April 20, 2012 11:20 PM
  • Here is beginning of my code:

    UnicodeEncoding UE = new UnicodeEncoding();

                    string password = „12345678“;

                    byte[] key = UE.GetBytes(password);

                    FileStream cryptedFileStream = new FileStream(„EncryptedFile“, FileMode.Create);

                    RijndaelManaged RMCrypto = new RijndaelManaged();

                    CryptoStream cryptoStream = new CryptoStream(cryptedFileStream, RMCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write);

    If the password is shorter or longer than 8 characters i get an error: "Specifier initialization vector (VI) does not match the block size for this algorithm"

    I have tried to use password like "1234567812345678" thats 32 byte (256 bits) and I still get this error message

    Friday, April 20, 2012 11:58 PM
  • The key size is not the problem here, except for the fact that you are attempting to use the same key also for the initialization vector (IV).

    The block size of the algorithm does not need to match the key size, but it must match the size of the IV, which is why you are getting the error. A quick solution that would allow you to use a 256 key (i.e. a 16 character string) would require a very small change in your code:

          RijndaelManaged RMCrypto = new RijndaelManaged {
            BlockSize = 256
          };

    This would leave a number of open issues, though:

    - you would still be forced to a provide string with an exact number of characters;

    - you are wasting several bits of your keys as using latin characters for the password leaves you with lots of 0x00 bytes in the key;

    - I also suspect that using the very same bytes for the key and the IV would weaken the algorithm as it might provide hints for the cracker. I don't have the hard math for that, but I would rather be on the safe side here.

    As I mentioned in my earlier post, I would suggest something like this instead:

          string password = "a string of arbitrary length";
          string keySalt = "KEYSALT"; // an arbitrary constant string to randomize the hash
          string ivSalt = "IVSALT"; // another arbitrary constant string to generate a different hash
          byte [] key = SHA256.Create ().ComputeHash (Encoding.Unicode.GetBytes (keySalt + password));
          byte [] iv = SHA256.Create ().ComputeHash (Encoding.Unicode.GetBytes (ivSalt + password)).Take (16).ToArray ();
          FileStream cryptedFileStream = new FileStream ("EncryptedFile", FileMode.Create);
          RijndaelManaged RMCrypto = new RijndaelManaged ();
          CryptoStream cryptoStream = new CryptoStream (cryptedFileStream, RMCrypto.CreateEncryptor (key, iv), CryptoStreamMode.Write);

    This would address all the points above: the password can now have an arbitrary length; we create a 256 bit hash from the salted password to use as the key, using the full strength of 256 bits, and a separate 128 bit hash from a (differently) salted password to use as the IV.

    HTH
    --mc


    • Edited by Mario Cossi Saturday, April 21, 2012 1:06 AM
    • Marked as answer by GaiusBaltar Saturday, April 21, 2012 6:31 AM
    Saturday, April 21, 2012 1:03 AM
  • Try posting both the encryption and decryption code.

    Thanks
    --mc

    Saturday, April 21, 2012 6:56 PM