1

I got my encryption algorithm working fine and left it alone for a few months. Today I needed to use it again and somehow it broke. I have poked at it for a while and have been unable to spot what the problem is. There are no errors, it just returns junk data.

The Setup: A PHP script(that has worked in production for a long time) encrypts some string using:

function hexstr($hexstr) 
{
  // return pack('H*', $hexstr); also works but it's much harder to understand.
  $return = '';
  for ($i = 0; $i < strlen($hexstr); $i+=2) {
    $return .= chr(hexdec($hexstr[$i] . $hexstr[$i+1]));
  }
  return $return;
}

function encrypt($str, $key)
{
    $key = hexstr($key);
    $size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    $iv = mcrypt_create_iv($size, MCRYPT_RAND);
    return $iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_CBC,$iv);
}

If I decrypt this on the php side it works fine.

Then the string is base64 encoded:

$encoded = base64_encode($encrypted);

Finally the C# program gets a hold of it and does the following:

....
byte[] decoded = Convert.FromBase64String(myWebText);
Decrypt(decoded)
.....


public static byte[] Decrypt(byte[] p)
{
    RijndaelManaged aes128 = new RijndaelManaged();
    aes128.KeySize = 128;
    //aes128.BlockSize = 
    aes128.Padding = PaddingMode.Zeros;
    aes128.Mode = CipherMode.CBC;
    aes128.Key = StringToByteArray("SOMEHEXSTRING");
    //pull the iv off the front of the byte array
    if (p.Length <= 16)
    {
        Utils.ReportError("byte array too short");
        return null;
    }
    byte[] iv = new byte[16];
    Array.Copy(p, 0, iv, 0, 16);
    aes128.IV = iv;
    ICryptoTransform transform = aes128.CreateDecryptor();
    byte[] result = transform.TransformFinalBlock(p, 16, p.Length - 16);

    Debug.Log("If this encrypted stuff was text it would be:"+System.Text.Encoding.UTF8.GetString(result));
    return result;
}


public static byte[] StringToByteArray(string hex)
{
    if (hex.Length % 2 == 1)
        throw new Exception("The binary key cannot have an odd number of digits");

    byte[] arr = new byte[hex.Length >> 1];

    for (int i = 0; i < hex.Length >> 1; ++i)
    {
        arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1])));
    }

    return arr;
}

Does anyone know what this might not be working? It must be very close because I am sure it worked at one point. Update: I did a binary compare of when i C# encode\decode and php encode decode. The php encoded Hello World is not the same as the c# Hello world when using the same IV. is this possible or does this indicate they are not using the same configuration somehow.

user2292539
  • 245
  • 1
  • 11
  • Updated to include base64 decoding code – user2292539 May 21 '14 at 21:04
  • Could you post an example encrypted string and key? I don't typically use php, but I might be able to try decrypting an already encrypted string for you to see if I can see any potential problems. – LVBen May 21 '14 at 22:25
  • Ok sure, here is some key and Hello World encoded in (after encrypting its base64 encoded in this example too) "Data:ewp/sWeooBQd7xUCNxtmwTsTy5KdZkOglkPo7PPPuY0=" Key is "BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB" don't forget the IV leading 16 bytes is in there too – user2292539 May 21 '14 at 22:58
  • Can you also post your StringToByteArray method? – LVBen May 21 '14 at 23:11
  • Function added in main description – user2292539 May 21 '14 at 23:31
  • So far, your C# code seems to be working fine on my end. I haven't tried decrypting your string yet, though. – LVBen May 21 '14 at 23:57
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackoverflow.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders May 22 '14 at 02:29

2 Answers2

1

Turns out I had changed the key to have non upper case letters and my GetHexVal function shown there only took upper case letters... Ouch

user2292539
  • 245
  • 1
  • 11
0

IDEA: The decryption key has changed.

Very nasty when it happens. Are you using a config file with decryption key? If not What is the decryptionKey used ? Has it changed?

If using localApp.config or ROOT.config and the key was changed, you can go hunting around all backups to get the key.

 <machineKey decryptionKey="SomeHexValueHere" validationKey="SomeveryLongHexvalueHere" />

But if your PHP version is working, the key must be "known"

phil soady
  • 11,043
  • 5
  • 50
  • 95
  • Yes. I have the key. I tried another solution i found on here. http://stackoverflow.com/questions/165808/simple-two-way-encryption-for-c-sharp. I can encrypt and decrypt on the c# side but I get the same issue when going from php to c#. Just junk characters as the output. I tried adding the padding and using PKCS7 but I get:CryptographicException: Bad PKCS7 padding. Invalid length 197. I am handing the crypto stuff exactly 16 bytes so I am not sure where that number is coming from. – user2292539 May 22 '14 at 05:12