C – tiny-aes-c and Javascript CryptoJS interoperability

  • A+
Category:Languages

Using tiny-aes-c. Consider the following C code:

int main(int argc, char const *argv[]) {     uint8_t key[6] = { 's','e','c','r','e','t' };     uint8_t iv[16]  = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };      uint8_t in[6]  = { 'm','e','s','a','g','e'};      uint8_t out[6] = {0x17, 0x8d, 0xc3, 0xa1, 0x56, 0x34};     struct AES_ctx ctx;      AES_init_ctx_iv(&ctx, key, iv);     AES_CTR_xcrypt_buffer(&ctx, in, 6);          printf("idx/t encrypted/t expected");     for(int i=0 ; i<6 ; i++){         printf("/n[%i]/t %.2x/t/t %.2x" , i , in[i], out[i]);     }      return 0; } 

The code encrypts a message and compares the results with the expected output. The code works fine and the output is as follows:

idx      encrypted       expected [0]      17              17 [1]      8d              8d [2]      c3              c3 [3]      a1              a1 [4]      56              56 [5]      34              34 

I have another service, a NodeJS server which uses CryptoJS.
My question is: How can I transform the C results ({0x17, 0x8d, 0xc3, 0xa1, 0x56, 0x34}) so it will match something CryptoJS could handle?


Edit: Elaborating a bit. for the purpose of this discussion, the C result is transmitted over the network, so it should be transformed to a String. As far as I know, CryptoJS uses base64 as an input for it's AES method, decrypts to bytes that later can be converted to plain text:

var bytes  = CryptoJS.AES.decrypt(BASE_64_STRING, SECRET); var plaintext = bytes.toString(CryptoJS.enc.Utf8); 

The encrypted result for the same message + secret with CryptoJS is: U2FsdGVkX1/TAYUIFnXzC76zb+sd8ol+2DfKCkwITfY= (JS Fiddle) and changes on each run.

Update 2:
Thanks to @MDTech.us_MAN answer I've made some changes to both the JS and C code, but I'm still missing a puzzle pice.

C:

int main(int argc, char const *argv[]) {     uint8_t key[16] = { 's','e','c','r','e','t','s','e','c','r','e','t','1','2','3','4' };     uint8_t iv[16]  = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };     uint8_t in[7]  = { 'm','e','s','s','a','g','e'};      struct AES_ctx ctx;      AES_init_ctx_iv(&ctx, key, iv);     AES_CTR_xcrypt_buffer(&ctx, in, 7);      printf("Encrypted: ");     for(int i=0 ; i<7 ; i++){         printf("%.2x" , in[i]);     }      return 0; } 

The encrypted HEX string C output: cba9d5bc84113c, when converted to Base64 result is :y6nVvIQRPA==

On the JS side, I'm explicitly using CTR mode with no padding, and initiating (hopefully) same iv like so:

const CryptoJS = require("crypto-js"); let iv = CryptoJS.enc.Hex.parse('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'); // 16 Bytes (same as the C code) let message = CryptoJS.AES.decrypt("y6nVvIQRPA==", "secretsecret1234", { iv: iv, mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding }); console.log(message.toString()); 

The decrypted result: a47172dfe151c7 and not the expected result "message".

What am I missing?


You should read the CryptoJS documentation more carefully. By default it uses CBC mode for the encryption so you should change your tiny-AES implementation to use that.

CryptoJS supports the following modes:

  • CBC (the default)

Also note that CryptoJS has padding enabled by default, while tiny-AES doesn't have it at all. Therefore, messages must be multiples of 16. (Or you can manually use your own padding implementation)

No padding is provided so for CBC and ECB all buffers should be mutiples of 16 bytes. For padding PKCS7 is recommendable.

Then, notice that CryptoJS autoselects the AES variant by the key size:

CryptoJS supports AES-128, AES-192, and AES-256. It will pick the variant by the size of the key you pass in. If you use a passphrase, then it will generate a 256-bit key.

So, you must consider all of these factors in your tiny-AES code.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: