rijndael encryption - only part of the string is decrypted
Asked Answered
R

3

3

Only part of the string is getting decrypted, i think it has to do with my encoding.

Here is what happens:

        string s = "The brown fox jumped over the green frog";
        string k = "urieurut";
        string enc = EncryptString(s, k);
        string dec = DecryptString(enc, k);

The RESULT is this: The brown fox juϼ㴘裴혽Ή⪻ㆉr th≸ g⟤een frog

public static string EncryptString(string stringToEncrypt, string encryptionKey)
{
    string encrypted = String.Empty;

    UnicodeEncoding UE = new UnicodeEncoding();
    byte[] key = UE.GetBytes(encryptionKey);

    RijndaelManaged RMCrypto = new RijndaelManaged();
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, RMCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write);

    byte[] encryptedString = UE.GetBytes(stringToEncrypt);
    cs.Write(encryptedString, 0, encryptedString.Length);
    cs.FlushFinalBlock();
    cs.Close();

    encrypted = UE.GetString(ms.ToArray());
    return encrypted;
}

public static string DecryptString(string stringToDecrypt, string encryptionKey)
{
    string decrypted = String.Empty;

    UnicodeEncoding UE = new UnicodeEncoding();
    byte[] key = UE.GetBytes(encryptionKey);
    byte[] data = UE.GetBytes(stringToDecrypt);

    RijndaelManaged RMCrypto = new RijndaelManaged();
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, RMCrypto.CreateDecryptor(key, key), CryptoStreamMode.Write);
    cs.Write(data, 0, data.Length);
    cs.FlushFinalBlock();
    cs.Close();

    decrypted = UE.GetString(ms.ToArray());

    return decrypted;
}
Rebba answered 4/6, 2010 at 15:19 Comment(2)
Wow cool... I see broken Korean in the result...Naivete
Yea i started to wonder if North Korea was bustin my stuff.Rebba
R
1

I solved my issue by using base64 string for the encryption - i may look at other options but i only needed these methods for a small amount of data, here is the final code:

public static string EncryptString(string stringToEncrypt, string encryptionKey)
{
    string encrypted = String.Empty;
    byte[] key = Encoding.Unicode.GetBytes(encryptionKey);

    RijndaelManaged RMCrypto = new RijndaelManaged();
    RMCrypto.Padding = PaddingMode.PKCS7;
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, RMCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write);

    byte[] encryptedString = Encoding.ASCII.GetBytes(stringToEncrypt);
    cs.Write(encryptedString, 0, encryptedString.Length);
    cs.FlushFinalBlock();
    cs.Close();

    //encrypted = Encoding.ASCII.GetString(ms.ToArray());
    return Convert.ToBase64String(ms.ToArray());
}

public static string DecryptString(string stringToDecrypt, string encryptionKey)
{
    string decrypted = String.Empty;
    byte[] key = Encoding.Unicode.GetBytes(encryptionKey);
    byte[] data = Convert.FromBase64String(stringToDecrypt);

    RijndaelManaged RMCrypto = new RijndaelManaged();
    RMCrypto.Padding = PaddingMode.PKCS7;
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, RMCrypto.CreateDecryptor(key, key), CryptoStreamMode.Write);
    cs.Write(data, 0, data.Length);
    cs.FlushFinalBlock();
    cs.Close();

    decrypted = Encoding.ASCII.GetString(ms.ToArray());

    return decrypted;
}
Rebba answered 4/6, 2010 at 15:43 Comment(5)
Note that byte[] key = Encoding.Unicode.GetBytes(encryptionKey); will use at most 6 chars from the password to form a pretty weak key. Using ASCII or UTF8 would already be a big improvement, to do it right see the Rfc2898DeriveBytes class.Goldplate
@Henk, could you explain the 'why' behind that it uses at most 6 chars when getting the unicode chars from a unicode string?Graniah
Wow. I never knew the first 16 bytes were length. Thanks for the information.Graniah
Just a correction here: UniCode.GetBytes() does not use a length-prefix, my error. But a 8 char password will give a 16 byte key in which half the bytes are 00. Also see stackoverflow.com/questions/3013368Goldplate
Huh, someone voted this one down too without explanation. Awesome.Graniah
G
3

Here you go:

    string s = "The brown fox jumped over the green frog";
    string k = "urieurut";
    byte[] enc = EncryptString(s, k);
    string dec = DecryptString(enc, k);

You can't attempt to interpret an encrypted bunch of bytes as a Unicode string. Keep them as bytes. The decrypted version can be converted back to string.

Also note the disposing of disposable objects below. You could wind up with some resources being held too long or leak if you don't release them properly with using() or Dispose().

public static byte[] EncryptString(string stringToEncrypt, string encryptionKey)
{
    UnicodeEncoding UE = new UnicodeEncoding();
    byte[] key = UE.GetBytes(encryptionKey);

    using (RijndaelManaged RMCrypto = new RijndaelManaged())
    using (MemoryStream ms = new MemoryStream())
    using (ICryptoTransform encryptor = RMCrypto.CreateEncryptor(key, key))
    using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
    {
        byte[] encryptedString = UE.GetBytes(stringToEncrypt);
        cs.Write(encryptedString, 0, encryptedString.Length);
        cs.FlushFinalBlock();
        return ms.ToArray();
    }
}

public static string DecryptString(byte[] stringToDecrypt, string encryptionKey)
{
    UnicodeEncoding UE = new UnicodeEncoding();
    byte[] key = UE.GetBytes(encryptionKey);

    using (RijndaelManaged RMCrypto = new RijndaelManaged())
    using (MemoryStream ms = new MemoryStream())
    using (ICryptoTransform decryptor = RMCrypto.CreateDecryptor(key, key))
    using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
    {
        cs.Write(stringToDecrypt, 0, stringToDecrypt.Length);
        cs.FlushFinalBlock();
        return UE.GetString(ms.ToArray());
    }
}
Graniah answered 4/6, 2010 at 16:5 Comment(3)
Or base64 encode it if you need a string. (Looks like that's what the OP ended up doing...)Commentate
Yes i am disposing of (most of) the objects, i just used the sample for clarity - but i had missed disposing of one which i would not have caught had you of not pointed it out - thank you.Rebba
Curious - why did someone downvote this? A comment would be welcome.Graniah
R
1

I solved my issue by using base64 string for the encryption - i may look at other options but i only needed these methods for a small amount of data, here is the final code:

public static string EncryptString(string stringToEncrypt, string encryptionKey)
{
    string encrypted = String.Empty;
    byte[] key = Encoding.Unicode.GetBytes(encryptionKey);

    RijndaelManaged RMCrypto = new RijndaelManaged();
    RMCrypto.Padding = PaddingMode.PKCS7;
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, RMCrypto.CreateEncryptor(key, key), CryptoStreamMode.Write);

    byte[] encryptedString = Encoding.ASCII.GetBytes(stringToEncrypt);
    cs.Write(encryptedString, 0, encryptedString.Length);
    cs.FlushFinalBlock();
    cs.Close();

    //encrypted = Encoding.ASCII.GetString(ms.ToArray());
    return Convert.ToBase64String(ms.ToArray());
}

public static string DecryptString(string stringToDecrypt, string encryptionKey)
{
    string decrypted = String.Empty;
    byte[] key = Encoding.Unicode.GetBytes(encryptionKey);
    byte[] data = Convert.FromBase64String(stringToDecrypt);

    RijndaelManaged RMCrypto = new RijndaelManaged();
    RMCrypto.Padding = PaddingMode.PKCS7;
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, RMCrypto.CreateDecryptor(key, key), CryptoStreamMode.Write);
    cs.Write(data, 0, data.Length);
    cs.FlushFinalBlock();
    cs.Close();

    decrypted = Encoding.ASCII.GetString(ms.ToArray());

    return decrypted;
}
Rebba answered 4/6, 2010 at 15:43 Comment(5)
Note that byte[] key = Encoding.Unicode.GetBytes(encryptionKey); will use at most 6 chars from the password to form a pretty weak key. Using ASCII or UTF8 would already be a big improvement, to do it right see the Rfc2898DeriveBytes class.Goldplate
@Henk, could you explain the 'why' behind that it uses at most 6 chars when getting the unicode chars from a unicode string?Graniah
Wow. I never knew the first 16 bytes were length. Thanks for the information.Graniah
Just a correction here: UniCode.GetBytes() does not use a length-prefix, my error. But a 8 char password will give a 16 byte key in which half the bytes are 00. Also see stackoverflow.com/questions/3013368Goldplate
Huh, someone voted this one down too without explanation. Awesome.Graniah
C
0

Not sure about your specific code chunk, but Jeff Atwood did a nice little library that I've used before:

http://www.codeproject.com/KB/security/SimpleEncryption.aspx

It's worth a look as it simplifies the process of encrypting things a lot, I actually had to port to C# as there wasn't a port available when I saw it. However there is now a C# port (in the comments section).

Cohette answered 4/6, 2010 at 15:36 Comment(2)
I will take a look at that, i like the different options there - thank you.Rebba
Cool, sorry I couldn't help directly.Cohette

© 2022 - 2024 — McMap. All rights reserved.