views:

503

answers:

2

A lot of items I've found so far have been a bit vague or ... unspecific so I'm hoping to get an answer.

I've got two little methods - easy ones that look as such...

    private const string initVector = "1234567890123456";
    private const string SaltValue = "ThisIsMySaltValue";
    private const int KeySize = 256;

    public static string Encrypt(string textToEncrypt)
    {
        var rijndael = new RijndaelManaged {KeySize = KeySize};
        var salt = SaltValue.ToByteArray();
        var vector = initVector.ToByteArray();

        var rfcBytes = new Rfc2898DeriveBytes(vector, salt, 2);
        var key = rfcBytes.GetBytes(rijndael.KeySize/8);

        ICryptoTransform encrypt = rijndael.CreateEncryptor(key, vector);

        var stream = new MemoryStream();
        var data = Encoding.ASCII.GetBytes(textToEncrypt);
        stream.Write(data, 0, data.Length);

        var cryptoStream = new CryptoStream(stream, encrypt, CryptoStreamMode.Write);
        cryptoStream.Write(data, 0, data.Length);
        cryptoStream.FlushFinalBlock();

        cryptoStream.Close();
        return Convert.ToBase64String(stream.ToArray());
    }


    public static string Decrypt(string textToDecrypt)
    {
        var vector = initVector.ToByteArray();
        var salt = SaltValue.ToByteArray();
        var encrypted = textToDecrypt.ToByteArray();

        var rijndael = new RijndaelManaged {KeySize = KeySize};

        var rfcBytes = new Rfc2898DeriveBytes(vector, salt, 2);
        var key = rfcBytes.GetBytes(rijndael.KeySize/8);

        var decrypt = rijndael.CreateDecryptor(key, vector);

        var stream = new MemoryStream(encrypted);
        var cryptoStream = new CryptoStream(stream, decrypt, CryptoStreamMode.Read);

        byte[] plainBytes = new byte[textToDecrypt.Length];

        var decryptedLength = cryptoStream.Read(plainBytes, 0, plainBytes.Length);

        var plainText = Encoding.UTF8.GetString(plainBytes, 0, decryptedLength);
        return plainText;
    }

Unit Test looks something like this ...

    [Test]
    public void JustTestingThisOut()
    {
        var encryptMe = "SomethingToEncrypt";
        string result = encryptMe.ConvertToEncrypted();
        result.ShouldNotEqual(encryptMe);
        string backToReadAble = result.ConvertToDecrpted();
        backToReadAble.ShouldEqual(encryptMe);
    }

ToByteArray just does a return Encoding.UTF8.GetBytes(toByte); and my test string is simple - "SomethingToEncrypt". I've went down the rabbit hole of finding this thinking that might have been the problem (Convert.ToBase64String and Convert.FromBase64String) that doesn't seem to make any difference. As for the error ...

TestCase 'Tests.Encryption.EncryptionUnitTests.JustTestingThisOut' failed: System.Security.Cryptography.CryptographicException : Length of the data to decrypt is invalid. at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)

I have the FlushFinalBlock() in there, and I THOUGHT that'd do it, but ...nope, makes no difference as well. Any ideas? Things to try?

A: 

When encrypting, you first write data to stream, then you wrap stream with a CryptoStream and write data again, this time with encryption. Why? The decryption fails because the first thing it encounters is unencrypted data.

Print the value of the ciphertext before base64 encoding to verify this. You should see the plaintext followed by a bunch of gobbledygook that is the ciphertext.

Also, you are using the initialization vector as a password. They are definitely not the same thing, and using it like this will compromise security.

erickson
I've seen that at some point -- the diamond question marks after the text. Let me see if I can't get it back to that.regarding the IV -- yea, I know, I'm just trying to get it to work first. I have a private password value for testing right now that looks something like ... private const string password = "AreYouTellingMeThatAThreeOunceBirdCanCarryAOnePoundCoconut?"; :-)
jeriley
yep, yanking that one line -- stream.Write(data, 0, data.Length); and it works. Now to wire up the fun stuff.
jeriley
A: 

I cant see how this will work as jeriley suggests since in the decrypt function you do

var encrypted = textToDecrypt.ToByteArray();

Here textToDecrypt is a base64 string. You first have to convert the base64 back to ordinary bytes which you can then use to decrypt.

Henri