1

My structure for the c# encrypt/decrypt is as follows:

  • Cipher: Rijndael (AES)
  • Block Size: 128 bits (16 bytes)
  • Mode: CBC (Cipher Block Chaining)
  • Key: MD5 hash passphrase
  • IV: Same as the key
  • Data Encoding: Base64 Character
  • UTF-8 Encoding

I'm using input Player for both inputs as a test, however it is not returning the correct MD5 hash output, and also there's a small issue with my Decrypt function for byte[] toEncryptArray = Convert.FromBase64String (toDecrypt);.

Incorrect hash output and Error

playerID is: Player encrypted is: ZCKgr4veKtCDrD6mL+P6Yg==
FormatException: Invalid length. System.Convert.FromBase64String (System.String s) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System/Convert.cs:146) APIConnector.Decrypt (System.String toDecrypt) (at Assets/APIConnector.cs:122)

Any ideas on what I can do to 1) fix this error and 2) get my hash output correct based on ym structure above? Thanks!

void submit(){

        Debug.Log ("playerID is: " + firstName + " encrypted is: " + Encrypt(firstName));
        Debug.Log ("password is: " + password + " decrypted is: " + Decrypt(password));

    }


    public static string Encrypt (string toEncrypt)
    {
        byte[] keyArray  = UTF8Encoding.UTF8.GetBytes ("SecretPassphrase");

        // 256-AES key
        byte[] toEncryptArray   = UTF8Encoding.UTF8.GetBytes (toEncrypt);

        RijndaelManaged rDel  = new RijndaelManaged ();
        rDel.Key              = keyArray;
        rDel.IV              = keyArray;
        rDel.Mode             = CipherMode.CBC;
        rDel.BlockSize        = 128;

        // http://msdn.microsoft.com/en-us/library/system.security.cryptography.ciphermode.aspx
        rDel.Padding   = PaddingMode.PKCS7;

        // better lang support
        ICryptoTransform cTransform  = rDel.CreateEncryptor ();

        byte[] resultArray   = cTransform.TransformFinalBlock (toEncryptArray, 0, toEncryptArray.Length);

        return Convert.ToBase64String (resultArray, 0, resultArray.Length);
    }

    // 
    public static string Decrypt (string toDecrypt)
    {
        byte[] keyArray  = UTF8Encoding.UTF8.GetBytes ("SecretPassphrase");

        // AES-256 key
        byte[] toEncryptArray   = Convert.FromBase64String (toDecrypt);

        RijndaelManaged rDel  = new RijndaelManaged ();
        rDel.Key              = keyArray;
        rDel.IV              = keyArray;
        rDel.Mode             = CipherMode.CBC;
        rDel.BlockSize        = 128;

        // http://msdn.microsoft.com/en-us/library/system.security.cryptography.ciphermode.aspx
        rDel.Padding    = PaddingMode.PKCS7;

        // better lang support
        ICryptoTransform cTransform  = rDel.CreateDecryptor ();

        byte[] resultArray   = cTransform.TransformFinalBlock (toEncryptArray, 0, toEncryptArray.Length);

        return UTF8Encoding.UTF8.GetString (resultArray);
    }
DT.DTDG
  • 765
  • 1
  • 13
  • 31

2 Answers2

0

You should pass encrypted value to Decrypt, not firstname. Base64 convertion failing because firstname is in clear.

    Debug.Log ("playerID is: " + firstName + " encrypted is: " + Encrypt(firstName));
    Debug.Log ("password is: " + password + " decrypted is: " + Decrypt(firstName));

It should be

string enc = Encrypt(firstName);
Debug.Log ("playerID is: " + firstName + " encrypted is: " + enc);
Debug.Log ("password is: " + password + " decrypted is: " + Decrypt(enc));
Oleg Gryb
  • 5,122
  • 1
  • 28
  • 40
  • awesome, resolves one issue, thanks :) Just the md5 hash isn't correct and I can't see why.. I'm using everything according to my structure, or aren't I? – DT.DTDG May 26 '14 at 04:48
  • Using MD5 in this case is a horrible idea from security point of view, because it's prone to collisions. You need to use a key stretching algorithm to reliably derive a crypto key from a passphrase. Another name PBE or password based encryption. Just Google it. – Oleg Gryb May 26 '14 at 04:55
  • 1
    More specifically, you'll need to use Rfc2898DeriveBytes, which is .NET implementation of PBKDF2. Check this link: http://stackoverflow.com/questions/5392404/key-strengthening-am-i-doing-it-right – Oleg Gryb May 26 '14 at 05:02
  • While you are at it, please use a random salt per plaintext. If you ever repeat the salt to encrypt a certain plaintext (in time), at least use a random IV as well. – Maarten Bodewes May 26 '14 at 17:31
0

Your submit method is not decrypting your encrypted string, it's trying to decrypt your un-encrypted original string. Changing your submit method to the below makes the program execut without error;

static void submit(){
    string password = Encrypt(firstName);
    Console.WriteLine ("playerID is: " + firstName + 
                       " encrypted is: " + password);
    Console.WriteLine ("password is: " + password + 
                       " decrypted is: " + Decrypt(password));
}

Also, since you're not actually MD5'ing your key, you're lucky that "SecretPassphrase " is actually 16 characters which is the exact length of key MD5 would have produced. Changing to a shorter or longer string will break the program.

Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294
  • thank you! That resolves one issue, now the other issue is that the hash (the encrypted in log) is incorrect. Can you see anything else that may be doing something to change it from what it's supposed to be? – DT.DTDG May 26 '14 at 04:47
  • Also, "SecretPassphrase" is not my actual key being used, just using that one in my example as it is 16 bits :) and my key is also 16 bits don't worry :) – DT.DTDG May 26 '14 at 04:49
  • Anything to do with the fact I must use MD5? – DT.DTDG May 26 '14 at 04:51
  • @DT.DTDG If you're not using MD5 on your key, you won't get the same result as if you are. In other words, if you have something you need to be compatible with, you'll need to MD5 your key just as the other side does. Otherwise there are (as the other answer states) better choices for key stretching in modern systems. – Joachim Isaksson May 26 '14 at 05:15