0

I have a function which encrypts certain strings for transfer to my client application in C++. The function I use in PHP to generate the encrypted string:

<?php
    echo EncryptForTransfer("This is a test"); //returns: l4/r5AUDTrPTlIfVyG0=DJKlty0VgWPSNsM2XbzkOZ79ivQA2eBWTd18FKVfgslM6UmP
    function EncryptForTransfer($EncryptMe) {
        $Key = random_string(32);
        $IV = random_string(16);
        return openssl_encrypt($EncryptMe, "AES-256-CFB", (string)$Key, false, $IV).$IV.$Key;
        }
    ?>

However, when I try to decrypt this result in C++ with the functions shown underneath, it is not returning me the string correctly (missing last parts).

int Decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext) {
    EVP_CIPHER_CTX *ctx;
    int len;
    int plaintext_len;
    if (!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
    if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cfb(), NULL, key, iv)) {
        handleErrors();
        }
    if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) {
        handleErrors();
        }
    plaintext_len = len;
    if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) {
        handleErrors();
        }
    plaintext_len += len;
    EVP_CIPHER_CTX_free(ctx);
    return plaintext_len;
    }
string DecryptFromTransfer(string DecryptMe) {
    long long DecryptFromTransferLength = DecryptMe.length();
    string TransferKey = DecryptMe.substr(DecryptFromTransferLength - 32, 32);
    string TransferIV = DecryptMe.substr(DecryptFromTransferLength - 32 - 16, 16);
    string DecryptMeOriginal = DecryptMe.substr(0, DecryptFromTransferLength - 32 - 16);
    return DecryptThis(DecryptMeOriginal, TransferKey, TransferIV);
    }
cout << DecryptFromTransfer("l4/r5AUDTrPTlIfVyG0=DJKlty0VgWPSNsM2XbzkOZ79ivQA2eBWTd18FKVfgslM6UmP"); //returns: This is

Please note that for some strings the decryption in C++ works correctly. However, for other strings the output is as stated above, only partially decrypted and missing the last parts. Maybe it is some kind of padding issue since some strings are decrypted correctly? So, what is wrong with my code?

The used string in the code above is just an example string to clarify the issue.

TVA van Hesteren
  • 1,031
  • 3
  • 20
  • 47
  • 1
    Side note: Are you sure you want to be including both the key and iv with the encrypted string? – IncredibleHat Nov 16 '17 at 15:17
  • 1
    No, and it actually won't in my application. However I had to exclude the situation that the `Key` or `IV` might be different than the ones used in PHP. However, now I am sure they are correct. In my actual application both the `Key` and `IV` will be stored separately. However, is this bad practice? How would you try to retrieve the `IV` and `Key` from the string if you don't know it's offsets? Lets's say I would place the `IV` always from pos 20 to 36 for instance? How would you know where in the encrypted string it is? It's going to give you a lot of combinations not knowing the start pos? – TVA van Hesteren Nov 16 '17 at 15:19
  • 2
    You don't need to store the IV separately. It can be either prepended or appended to the cipherText; it has a fixed length so it doesn't matter which one you choose (prepending might be a bit easier to handle though). But the key is supposed to be secret ... you don't transfer it, you hard-code it on both ends. – Narf Nov 16 '17 at 15:23
  • 1
    I don't know c++ enough to have come across this behavior, but it does sound like either .length is returning the wrong value (which all your substr are using)... or each substr isn't looking at the string correctly. You are dealing with pure base64 encoded strings, right? Not the RAW_BINARY format? – IncredibleHat Nov 16 '17 at 15:26
  • Myabe this is similar question: https://stackoverflow.com/questions/43550818/cant-decrypt-using-pgcrypto-from-aes-256-cbc-but-aes-128-cbc-is-ok unfortunately I don't remember exact solution. as I remember aes256 is same as aes128 with longer key or something like this. So I stick with aes128 with this 32bit key. I am not an expert in this area, but maybe this will give you some ideas. Also I read few notes from people about issues decrypting result of php openssl aes256 on android. – R A Nov 16 '17 at 15:58
  • @Randall, it are base64 strings indeed. Good point of the length, I'm going to look into that, since I cast them to a char... strlen() might be wrong vs str.length(); – TVA van Hesteren Nov 16 '17 at 16:03
  • @Narf, right. So I could also prepend or append the IV and Key to the encrypted string to use in decryption? Looking at safety and easiness to breach? What would you prefer? Append to the string of hardcode it on both sides? Besides that, hardcoding makes them static while my encryption uses different Key and IV pairs each cycle? – TVA van Hesteren Nov 16 '17 at 16:05
  • @TVAvanHesteren No, you do NOT prepend or append the key, anywhere. This is not down to preference. Including the key with the cipherText is like slapping a post-it note with the combination right on your safe box. – Narf Nov 16 '17 at 16:10
  • 1
    @Randall I was saying is that it should not be transmitted together with the cipherText. But that doesn't in any way imply that it shouldn't be random, or that it is a password. It's not a password; it MUST be random and it consists of bytes, not characters. – Narf Nov 16 '17 at 16:12
  • @Narf, clear. Then I stick with my encryption algorithm with seperated key and IV. :) – TVA van Hesteren Nov 16 '17 at 17:23
  • Nope that's wrong again. The key stays secret. The IV should be prepended to the ciphertext. IV should be randomly generated for each encryption operation. – Luke Joshua Park Nov 16 '17 at 20:06
  • @lukepark, Right, so why can’t I send the IV separate from the cipher? Why should I pretend it? That is giving the IV away..? – TVA van Hesteren Nov 16 '17 at 21:43
  • 1
    The IV isn't a secret value. That's just the easiest way to do it. Anyone can know the IV and cipher is still perfectly safe. The IV just has to be randomly generated and different each time, that is all. – Luke Joshua Park Nov 16 '17 at 22:59
  • @LukePark, right. Why can't I reuse the same Key and IV pair for one particular encryption routine? – TVA van Hesteren Nov 17 '17 at 13:33
  • 1
    Because IV reuse is bad. A predictable IV can make ciphers vulnerable to some of the attacks on ECB mode. If you're in GCM or CTR, it can even trivially reveal the plaintext. Don't do IV reuse. Don't. – Luke Joshua Park Nov 17 '17 at 17:16
  • Oke, but when the IV is in the cipher it isn’t considered predictable ? – TVA van Hesteren Nov 17 '17 at 18:09
  • I think you misunderstood. The requirement is that the attacker can't predict what the next IV is going to be. Prefixing it to the ciphertext is fine. – Luke Joshua Park Nov 17 '17 at 20:05

0 Answers0