bricke / Qt-AES

Native Qt AES encryption class
The Unlicense
501 stars 187 forks source link

Decrpytion with AES-NI not working #47

Closed pH-Valiu closed 11 months ago

pH-Valiu commented 2 years ago

I enabled the decryption methods in the aesni.h files and used the code from #if USE_INTEL_AESNI_IF_AVAILABLE from the encoding step for the decode method, so that I can feed AES_ECV_decrypt() with the right parameters. Unfortunately though, the computed data isn't the decrypted version of my encrypted original data.

Anyone have an idea on how to fix it or do you need further information on my code?

pH-Valiu commented 2 years ago

I got a fix for that and got AES-NI fully implemented for CBC and EBC and I was able to increase general speed a ton (e.g.: encrypting 1.9GB data stored in a QByteArray can be incrypted within roughly 2 seconds and is being returned in just milliseconds due to evasion of unnessecary deep copy and rather directly assigning the output data to QByteArray.data() I am rather new to Github though, so it will take my some time to figure out how to make a push request

bricke commented 1 year ago

Hello, opening a PR is quite easy, once you cloned my repo, create a new branch, make your changes and push it to your newly created branch. Once on the github.com, you can go into the Pull Request tab and create a Pull Request from your branch into master. Once that is done I can evaluate your suggestion and we can discuss it and once all is good I will merge it into the mainline.

Welcome to github!

kouhj commented 1 year ago

@pH-Valiu I am very interested in your patch that enables AES-NI for decryption! Could you please submit the PR or paste the patch here? Thanks a lot!

kouhj commented 1 year ago

Thanks to https://gist.github.com/acapola/d5b940da024080dfaf5f and I figured it out the reason. The AES decryption needs a different expanded key from the expanded encryption key. The code below can convert the expanded encryption key to expanded decryption key:

void AES_ExpEncKey_2_ExpDecKey(const unsigned char *enc_key,
                                  unsigned char *dec_key,
                                  int key_len
                                  )
{
    int N = key_len / sizeof(__m128i) - 1;
    __m128i *enc_key_schedule = (__m128i*)enc_key;
    __m128i *dec_key_schedule = (__m128i*)dec_key;
    dec_key_schedule[0] = enc_key_schedule[N]; // shared by last enc & 1st dec
    // generate decryption keys in reverse order.
    for (int i=1; i<N; i++)
        dec_key_schedule[i] = _mm_aesimc_si128(enc_key_schedule[N-i]);
    dec_key_schedule[N] = enc_key_schedule[0]; // // shared by 1st enc and last dec
}
pH-Valiu commented 1 year ago

Sorry for my late response.

@bricke I did it. Pull request is up and the all tests succeded on my machine.

@kouhj If you are interested in how aes-ni works even more, I highly suggest you this article from Intel themselve, since it describes really clearly how it works. https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf Furthermore, my solution, and I suspect also the original code from bricke, is just a 1 to 1 copy out of that pdf. ^^ The important part regarding different key expansion when decrypting is just written at another spot in the article, more in the front :)