3

So, I have 3 Pieces out of 4 working, iOS Encrypt-Decrypt from this Link And I am able to Decrypt the data Encrypted from iOS I am having trouble Encrypting on PHP side. When I do echo Encryption code. PHP prints something like F>HFl8aR what does it mean ?

SALTKEY = 'a16byteslongkey!';

Decryption Code: Working

     $result =  mcrypt_decrypt(MCRYPT_RIJNDAEL_128, (SALTKEY . str_repeat(chr(0x00), 16)), 
                               base64_decode($text), 'ecb');
     $pad_char = ord(substr($result, -1));
     return substr($result, 0, strlen($result) - $pad_char);

Encryption Code : Not Working

     $result =  mcrypt_encrypt(MCRYPT_RIJNDAEL_128, (SALTKEY . str_repeat(chr(0x00), 16)), 
                               base64_encode($text), 'ecb');
     $pad_char = ord(substr($result, -1));
     return substr($result, 0, strlen($result) - $pad_char);
  • Results on iOS : Text = "Hello"
    Encryption = "7opqbb7sEVNoXplyQv/X8g=="
    Decryption of (7opqbb7sEVNoXplyQv/X8g==) = "Hello"

  • Results on PHP : Text = "7opqbb7sEVNoXplyQv/X8g=="
    Decryption = "Hello"
    Encryption of (Hello) = "_~TPn~p3MF?"

GoGreen
  • 182
  • 1
  • 13
  • 1
    Try CBC mode. If it doesn't matter. –  Nov 18 '11 at 07:58
  • 1
    _PHP prints something like F>HFl8aR_ - this is much like a binary string, shouldn't it be? Try to decrypt this string – dmitry Nov 18 '11 at 08:01
  • @Alfred I Believe I Need to use same Mode as iOS which is using ECB Mode – GoGreen Nov 18 '11 at 08:05
  • 1
    @confused-demon.. No it should not be binay.. if I encrypt "Hello" on iOS I get "7opqbb7sEVNoXplyQv/X8g==" and if Decrypt "7opqbb7sEVNoXplyQv/X8g==" I get Hello.... on PHP if I Decrypt "7opqbb7sEVNoXplyQv/X8g==" I get "Hello" which is good but WHEN I Encrypt "Hello" I get "_~TPn~p3MF?" Sorry for confusing comment.. I will add this to question. – GoGreen Nov 18 '11 at 08:09

3 Answers3

3

I think its fairly obvious that the IOS encryption is giving a 7-bit result (looks like base64 encoded) while the PHP is giving an 8-bit representation.

You don't seem to have got the hang of reversing the operation.

The decryption is performed by base64_decodeing the input, then applying mcrypt_decrypt. It follows that to perform this in reverse, you'd need to first mcrypt_encrypt, and then base64_encode.

i.e.

 $result =  base64_encode(
          mcrypt_encrypt(MCRYPT_RIJNDAEL_128, 
                (SALTKEY . str_repeat(chr(0x00), 16)), 
                $text, 'ecb'));
Yuliy
  • 17,381
  • 6
  • 41
  • 47
symcbean
  • 47,736
  • 6
  • 59
  • 94
  • 1
    I hope you don't mind my edits to clarify the meaning of the inverse operation. – Yuliy Nov 18 '11 at 09:11
  • It was really good point, I tried that but it's not giving me same results.. this is what I am getting .. 1V6SDeqH5++qfooQ7xp/xg== after encrypting "Hello" and I am looking for "7opqbb7sEVNoXplyQv/X8g==".. – GoGreen Nov 19 '11 at 19:27
2

Your encryption looks very bogus:

 $result =  mcrypt_encrypt(MCRYPT_RIJNDAEL_128, (SALTKEY . str_repeat(chr(0x00), 16)), 
                           base64_encode($text), 'ecb');
 $pad_char = ord(substr($result, -1));
 return substr($result, 0, strlen($result) - $pad_char);

You encode the text with base64, then encrypt it, and then and then try to remove padding?

Instead, you have to

  • add padding (if the encryption function doesn't already do this),
  • encrypt
  • then base-64-encode the result (if you want to have it somehow readable by humans or transmit over a non-binary-safe channel).

This could look like this:

$padded = pad($text);
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, (SALTKEY . str_repeat(chr(0x00), 16)), 
                       $padded, 'ecb');
$result = base64_encode($encrypted);

(Have a look at the user-contributed notes at the mcrypt_encrypt documentation for an example on how to create the padding.)

Of course, there are some more things to remark:

  • Don't ever use ECB-mode, if you don't know anything about cryptography. It is an unsafe mode of operation. Use CBC-mode (with a random initialization vector, which is sent with the data).

  • You create your key by padding the SALTKEY with zeros. This makes your key in effect weaker than necessary. (Having a key hard-coded in the code is a bad idea anyways.) Supply a full 128-bit key, or derive one from a password using salt and a key derivation function (like PBKDF-2) with a high iteration count.

  • Your decryption function should also check that the padding is valid (i.e. consists of identical bytes), not simply removing it.

  • You should also use a message authentication code (MAC) with your message, to avoid some chosen-ciphertext attacks which allow decrypting a message.

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
  • You made really good points, right now I want to have it working second part will be doing it right. and Vote up for you.. thansk – GoGreen Nov 19 '11 at 20:01
1

see my post here: PHP iOS AES Encryption

I keep reposting this as I see the same question over and over.


I just got through this same sort of project. I used the library you referenced in "also considered..."

Here is some example code to decrypt with php:

$iv2 = '';
for($i=0;$i<16;$i++){
    $iv2 .= "\0";   
}
$plain_text_CBC = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted_text, MCRYPT_MODE_CBC, $iv2);
var_dump($plain_text_CBC);

Make sure your keys are both 256-bit (32 characters, I have not yet had any encoding issues, but if you do, remember that you are encrypting bytes, not characters). Note that 128 in MCRYPT_RIJNDAEL_128 is the block size and not the key size, while in the method AES256DecryptWithKey, 256 is a reference to the key size, while the block size is 128. AES256DecryptWithKey runs in CBC mode, but has a null initialization vector (iv).

CBC means that each block depends on the last block, and so it uses a pre-set, usually random, "block -1" called the IV

ECB means that each block is encrypted in the same way, hence it reveals when two blocks in the same message are the same. The library mentioned does not use it, so I mentioned it just for contrast.

The use of a zero iv (0000000000000000 in bytes) is considered insecure, but it does provide you with some additional security (but one might still be able to tell if the fist 16 characters of your plain text were the same each time). To fix this you would have to create an NSData *iv variable for the IV and modify the CCcrypt argument of NSData+AESCrypt.m to add [iv bytes] for the iv parameter (I have not yet tested this code), and you would need to store this iv and pass it to the php along with you message. But first I would test and have everything working with a zero iv.

Community
  • 1
  • 1
user1122069
  • 1,767
  • 1
  • 24
  • 52