0

I am trying to achieve the following result:

  • ask user for a password (works)
  • generate a key based on it using scrypt (works)
  • encrypt some string using aes-js (ctr mode) (works)
  • encrypt the generated key using node-bignumber (js library offering rsa encryption based on Tom Wu's implementation) (works)
  • decrypt the aes key using intel IPP rsa (works i think)
  • decrypt the string using intel IPP aes (ctr mode) (I am stuck here) I have to use intel IPP because I am working with intel SGX. Here is what I have so far: js code:
const n = 'BBF82F090682CE9C2338AC2B9DA871F7368D07EED41043A440D6B6F07454F51F\nB8DFBAAF035C02AB61EA48CEEB6FCD4876ED520D60E1EC4619719D8A5B8B807F\nAFB8E0A3DFC737723EE6B4B7D93A2584EE6A649D060953748834B2454598394E\nE0AAB12D7B61A51F527A9A41F6C1687FE2537298CA2A8F5946F8E5FD091DBDCB'
const e = '11'

encryptAndSendResult () {
      scrypt(this.keyword, '', {
        N: 16384,
        r: 8,
        p: 1,
        dkLen: 16,
        encoding: 'binary'
      }, derivedKey => {
        console.log(derivedKey.toString()) // prints: 167,175,52,17,202,8,60,84,93,7,96,248,48,127,97,233
        const reviewString = 'testEncryption'
        const reviewBytes = aesjs.utils.utf8.toBytes(reviewString)

        let aesCtr = new aesjs.ModeOfOperation.ctr(derivedKey, new aesjs.Counter(5))
        let encryptedBytes = aesCtr.encrypt(reviewBytes)
        const encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes)

        // Encrypt the generated AES key
        const rsaKey = new rsa.Key()
        rsaKey.setPublic(n, e)
        const encryptedKey = rsaKey.encrypt(derivedKey.toString())

        aesCtr = new aesjs.ModeOfOperation.ctr(derivedKey, new aesjs.Counter(5))
        const decryptedBytes = aesCtr.decrypt(encryptedBytes)
        const decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes)
        console.log(decryptedText) // prints: testEncryption

        this.axios.post('/test/aesDecrypt', {
          cipher: encryptedHex,
          key: encryptedKey
        }).then(response => {
          console.log(response)
        }).catch(err => {
          console.log(err)
        })
      })
    }

And here is the C function that should process that string:

#include <cstring>
#include <stdio.h>
#include <stdarg.h>
#include "sgx_tcrypto.h"
#include "ippcp.h"
#include "BigNumber.h"
#include "crypto.h"

int test_aes_decrypt(const char *encReview, const char *encKey, char *out)
{
    // encReview and encKey point to correct data - i.e. the data sent from js
    int status = 0;
    char *save_ptr;
    string key;
    uint8_t aesKey[16];
    int i = 1;
    char review[1000];

    do
    {
        // decrypt aes key (using RSA)
        status = crp_rsa_decrypt(string(encKey), key); 
        // just some wrapper function that handles the ipp rsa decrypt, 
        // removes the padding (PKCS#1 type 2), and converts the result to ascii. 
        // key = "167,175,52,17,202,8,60,84,93,7,96,248,48,127,97,233"
        if (status != ippStsNoErr)
        {
            break;
        }

        // break the key string into an array of uint8_t
        // strtok trashes the source string
        char keyTemp[100];
        memcpy(keyTemp, key.c_str(), key.length());
        aesKey[0] = (uint8_t)atoi(strtok_r(keyTemp, ",", &save_ptr));
        while (i < 16)
        {
            aesKey[i] = (uint8_t)atoi(strtok_r(NULL, ",", &save_ptr));
            i++;
        }
        // aesKey[0] = 167, aesKey[1] = 175 etc.

        // decrypt review (using AES)
        status = crp_aes_decrypt(string(encReview), aesKey, (uint8_t *)review);
        if (status != ippStsNoErr)
        {
            // it does not enter here
            break;
        }

        // review does not contain testEncryption or anything similar
        memcpy(out, review, 1000);
    } while (0);

    return status;
}

int crp_aes_decrypt(const string &cipher, uint8_t *key, uint8_t *plainText)
{
    uint8_t ctr[16];
    uint8_t ctr0[] = "\x00\x00\x00\x00\xbb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05";

    // initialize the counter
    memcpy(ctr, ctr0, sizeof(ctr));

    // convert to uppercase
    string localCipher = cipher;
        for (int i = 0; localCipher[i] != 0; i++)
            if (localCipher[i] <= 122 && localCipher[i] >= 97)
                localCipher[i] -= 32;

    return (int) sgx_aes_ctr_decrypt((sgx_aes_gcm_128bit_key_t *)key, (const uint8_t *)localCipher.c_str(), localCipher.length(), ctr, 1, plainText);
    // sgx_aes_ctr_decrypt() is a wrapper for ippsAESDecryptCTR() provided with intel sgx sdk
    // (it also performs the required initialization)
    // sgx_aes_gcm_128bit_key_t is uint8_t[16]
}

My guess is that i am not handling the aes key in the correct way. Any help or ideas are greatly appreciated. Thank you!

  • 1
    can you provide minimum test example that can be run without having to add extra stuff (since it's way too long to manually debug?) – Ahmed Masud May 25 '17 at 22:10
  • Have you printed out the resulting AES key in both instances (e.g. using hexadecimals) because that would at least show that the RSA decryption didn't fail. Furthermore, you haven't shown *how* anything failed. Do you get an error, random output? – Maarten Bodewes May 25 '17 at 23:44

0 Answers0