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?
Thanks to @MDTech.us_MAN and this stack overflow question, I've found a solution, after fixing the mode and the padding, the difference was the way I was parsing the secret on the JS side. In the following example, the secret is parsed as a HEX string:
const CryptoJS = require("crypto-js");
let iv = CryptoJS.enc.Hex.parse('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'); // 16 Bytes
let secret = CryptoJS.enc.Hex.parse('73656372657473656372657431323334'); // 16 Bytes == "secretsecret1234"
let message = CryptoJS.AES.decrypt("y6nVvIQRPA==", secret, { iv: iv, mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding });
console.log(message.toString(CryptoJS.enc.Utf8)); // -> message