Search code examples
phpobjective-caesmcryptcommoncrypto

AES 256 with PKCS7 padding encoded data have half ECB and half CBC block


Im trying to decode data in php returned from server: I know data AES 256 decoded and have PKCS7 padding but cant figure out which block mode it use

here is my php function:

public function decode($data)
{
    //AES decode
    $iv = mcrypt_create_iv(GEServerConnection::FBENCRYPT_BLOCK_SIZE, MCRYPT_RAND);
    $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->cryptKey, base64_decode($data), MCRYPT_MODE_ECB, $iv);

    //return $data;
    $len = strlen($data);
    $pad = ord($data[$len - 1]);

    return substr($data, 0, - $pad);
}

and example of encoded data

3KD+zb/2u5gGEWvOy0Q0nSQE9pbQZmg27iN6WLiO/Af9YjN8MhHOb8TMa5uETaab

when i decode with ECB (MCRYPT_MODE_ECB) it decode only beginning of data and rest is unreadable

"Please input yo��޸̓��g|��*P�Te���  R�B

and when decode with CBC (MCRYPT_MODE_CBC) mode it have beginning unreadable

��0�=v������.3ur username and password again"

the result should be(what i get on mac using CommonCryptor in objective-c):

"Please input your username and password again"

somebody know whats wrong or how to decode it in right way?


Solution

  • Please have a look at the Wikipedia article. See how ECB and CBC does decryption. If ECB was the mode used, you would decrypt all text correctly. It seems that the cipher used CBC because it uses previous cipher text + current cipher text + decryption function to get the original text. This is the reason why you decoded second block correctly.

    Now why is the first block decoded wrong? It is because you need to supply correct initialization vector. It must be the same that was used for encryption. We are lucky that we know that ECB decoded first block because ECB does not use initialization vector.

    The answer is simple: Use CBC with zero initialization vector (all bytes are zero) because now your random IV changed first block to wrong output.