2

I am building an iPhone app which gets a decrypted string via JSON from a PHP backend.

In PHP I am encrypting the string like this:

$encrypt_method = "AES-256-CBC";
    $secret_key = 'This is my secret key';
    $secret_iv = 'This is my secret iv';

    // hash
    $key = hash('sha256', $secret_key);

    // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
    $iv = substr(hash('sha256', $secret_iv), 0, 16);

    if( $action == 'encrypt' ) {
        $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
        $output = base64_encode($output);
    }

In Objective C I tried to decrypt this string with BBEAS: https://github.com/benoitsan/BBAES

This is the code I have got in Objective C:

   NSData* salt = [BBAES IVFromString:@"This is my secret iv"];

    NSData *key = [BBAES keyBySaltingPassword:@"This is my secret key" salt:salt keySize:BBAESKeySize256 numberOfIterations:BBAESPBKDF2DefaultIterationsCount];
 NSData *decryptedMessage = [BBAES decryptedDataFromString:@"RlVnd01XOE5teTNseDFGQ3JScVhkQT09" IV:salt key:key];
    NSLog(@"Decrypted message: %@", decryptedMessage);

The log only shows a null object now.

I have found a duplicate post for C#: How to decrypt an AES-256-CBC encrypted string

EDIT: Lets say that i can adjust the encoding in PHP. How should I encrypt the string in PHP to be decrypted in Objective C?

Community
  • 1
  • 1
Andrew Ho
  • 618
  • 9
  • 21
  • 1
    BBAES is rather good with only a couple of warts and a lack of interoperability documentation, one needs to read the code to determine the following. All encryption errors are handled by Assert and are not returned to the user. It does uses PKCS#7 padding. It prepends the iv. If keyBySaltingPassword is used there may be interoperability issues since NSISOLatin1StringEncoding is used. If password hashing is chosen it use MD5 for 128 bit keys and SHA256 for 256 keys, the use of MD5 is a poor choice. For some reason it used a home-grown Base64 function instead of the Apple methods. – zaph Apr 03 '15 at 12:18
  • @Zaph MD5 is relatively OK in a Key Derivation Function. That you switch hash algorithms for a specific key size probably isn't. MD5 is faster, but PBKDF2 is used to *slow down* attacks. Instead just the leftmost bytes of the SHA256 should have been used. Error handling is poor of course. If you don't use ASCII then you should expect errors, so ` NSISOLatin1StringEncoding` is OK-ish. UTF-8 is the default though. Finally, CBC by itself is not fit for peer to peer encryption, **Andrew, you need to MAC salt, IV & ciphertext**. – Maarten Bodewes Apr 04 '15 at 08:46
  • @MaartenBodewes 1. You say: "CBC by itself is not fit for peer to peer encryption", please elaborate for completeness. 2. You do realize that I am not the author yet the comment reads as if I am. – zaph Apr 04 '15 at 12:08
  • @Zaph Yeah, I realized that you are not the author, but I thought you would be interested as well (and it seems you did, as you made a good remark). As for (1), CBC is not is not fit for peer to peer encryption because it lacks integrity and authenticity. Furthermore, if padding oracle attacks are possible (they usually are) then you lose confidentiality of the plaintext as well (i.e. *no protection at all*). – Maarten Bodewes Apr 04 '15 at 12:40
  • Yep, the authentication wraps it up nicely. – zaph Apr 05 '15 at 03:05

2 Answers2

3

You are not doing the same thing in PHP as in iOS. I am not familiar with this BBAES framework, but what you seem to have is a password from which you are generating a 256 bit AES key using PBKDF key derivation, and using that to decrypt the data. However, in PHP you are hashing your password and using it to encrypt your data, so you are probably using different AES keys for encryption and decryption. And I am not sure that IVs match either.

What you should do is:

In PHP, generate a random 16 byte IV for every encryption you do and use PBKDF key derivation to generate the 256 bit AES key from your password. Keep in mind that the salt and the number of iterations have to be the same in both PHP and iOS. After the encryption, append the IV to the encrypted data and send it.

In iOS, extract the IV from the received ciphertext (the last 16 bytes), generate the AES key from your password the same way you did before using the same salt and number of iterations, and decrypt the data (without the 16 byte IV at the end)

Edit:

As @Zaph pointed out, I forgot to mention that you should use also the same type of padding. BBAES seem to use PKCS7 padding.

Levi
  • 7,313
  • 2
  • 32
  • 44
  • The thing missing from the answer is any mention of data padding. – zaph Apr 03 '15 at 11:38
  • @Zaph , Andrew & Levi: OpenSSL uses PKCS#7 padding as well, so that should at least be all right. So if you get a padding error, it's likely the key itself, not the padding mechanism. – Maarten Bodewes Apr 04 '15 at 08:47
  • @MaartenBodewes Part of the reason for specifying the padding is that the usual PHP encryption function mcrypt() uses non-standard null padding by default and does not support PKCS#7. Obviously this causes many interoperability problems. – zaph Apr 04 '15 at 12:12
  • @Zaph Yeah, trust me, I know. I rewrote the `mcrypt_encrypt` sample code. Basically, the whole `mcrypt` library is currently a steaming pile of trap; I did get some indication that it is taken up again by some devs, but the underlying C library is currently not even maintained (since 2007!). Better keep to the (horribly documented) OpenSSL functionality with all its imperfections. – Maarten Bodewes Apr 04 '15 at 12:44
  • The problem with OpenSSL is that to many times updates are not backward compatible and that is the reason Apple stated they stopped supplying the library. Apple would supply the current OpenSSL library, someone re-compiled and the application would break. P.S. I heard this in person directly from Apple at a past WWDC. – zaph Apr 04 '15 at 13:03
1

To decrypt in Objective C you can use Apples's version of the CommonCrypto C library. It has a man page and there are already several posts that show decryption examples on Stack Overflow for example:

Determine if key is incorrect with CCCrypt kCCOptionPKCS7Padding-Objective C

which comes from the tutorial here:

http://robnapier.net/aes-commoncrypto

This also really helped me:

CCCrypt decrypting in AES CBC works even without IV

If you have trouble getting it working post some code.

Community
  • 1
  • 1
WaterNotWords
  • 997
  • 1
  • 9
  • 24
  • Good advice. Rolling one's own encryption stack is problematic and I would defer to using RNCryptor. BBAES is not bad and does all the things needed for good encryption, but see my comment to the question. – zaph Apr 03 '15 at 12:20