user2292539
user2292539

Reputation: 245

Decrypt returning junk data

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.

Upvotes: 1

Views: 795

Answers (2)

user2292539
user2292539

Reputation: 245

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

Upvotes: 1

phil soady
phil soady

Reputation: 11348

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"

Upvotes: 0

Related Questions