5

First, let me start by stating that I am not a cryptographer by any means, and I am not very good at writing c code either, so please excuse me if the answer to this question is obvious or answered. I am developing a messaging program and cannot use TLS on the target platform. As a result, I need to find a way to encrypt each message using a symmetric pre shared key cipher, like AES.

I am seeking a method to encrypt and decrypt data between an mbedtls program (such as aescrypt2) on one end, and a nodejs program on the other. Mbedtls, formerly polarssl, is a library which provides encryption for embedded devices. Included with the source code are some sample programs, like aescrypt2, rsaencrypt, ecdsa and crypt_and_hash.

Aescrypt2 works fine when the resulting encrypted data is also decrypted using aescrypt2, but I cannot seem to get data encrypted with aescrypt to decrypt using nodejs crypto or any other program for that matter, including openssl. For example:

echo 'this is a test message' >test.txt
aescrypt 0 test.txt test.out hex:E76B2413958B00E193
aescrypt 1 test.out test.denc hex:E76B2413958B00E193
cat test.denc
this is a test message

With openssl:

openssl enc -in out.test -out outfile.txt -d -aes256 -k E76B2413958B00E193
bad magic number

Some sample node code that doesn't currently work

    var crypto = require('crypto');
    var AESCrypt = {};

AESCrypt.decrypt = function(cryptkey, iv, encryptdata) {
    encryptdata = new Buffer(encryptdata, 'base64').toString('binary');

    var decipher = crypto.createDecipheriv('aes-256-cbc', cryptkey, iv),
        decoded = decipher.update(encryptdata, 'binary', 'utf8');

    decoded += decipher.final('utf8');
    return decoded;
}

AESCrypt.encrypt = function(cryptkey, iv, cleardata) {
    var encipher = crypto.createCipheriv('aes-256-cbc', cryptkey, iv),
         encryptdata = encipher.update(cleardata, 'utf8', 'binary');

    encryptdata += encipher.final('binary');
    encode_encryptdata = new Buffer(encryptdata, 'binary').toString('base64');
    return encode_encryptdata;
}

var cryptkey   = crypto.createHash('sha256').update('Nixnogen').digest(),
    iv         = 'a2xhcgAAAAAAAAAA',
    buf        = "Here is some data for the encrypt", // 32 chars
    enc        = AESCrypt.encrypt(cryptkey, iv, buf);
    var dec        = AESCrypt.decrypt(cryptkey, iv, enc);

console.warn("encrypt length: ", enc.length);
console.warn("encrypt in Base64:", enc);
console.warn("decrypt all: " + dec);

This results in either errors or garbage text every time. I have tried tweaking a variety of things as well.

I've tried this a hundred different ways, including using the -pass pass:password arg to no avail. Using nodejs, I have either gotten bad decrypt errors, or garbled nonsense back upon decryption. I have tried following many tutorials on the net, such as this one, and suggestions from this thread, and everything else I can find. I have read that different encryption programs use different standards, so compatibility across platforms/programs/languages is not always guaranteed, but I imagine somebody has been in this predicement before and knows a solution?

How would I, using nodejs, decrypt data encrypted by aescrypt2 (or a program like it)? I have only been able to make it work using a system exec call and having node execute aescrypt2 to decrypt/encrypt the data, which is not ideal, as it slows things down considerably. I am open to using a different program than aescrypt2. The only requirements are that it must run on Linux, cannot use openssl libs (because they are not supported on the target system), the program should be small and simple, due to space limitations, and foremost, the encryption/decryption needs to be compatible with nodejs. Any help would be much appreciated.

Community
  • 1
  • 1
Chev_603
  • 313
  • 3
  • 14
  • 1
    How is this C code? – Ryan May 27 '16 at 21:22
  • I am currently trying to use the mbedlts aescrypt sample program: https://github.com/ARMmbed/mbedtls/blob/development/programs/aes/aescrypt2.c , and it does not work with any of node cryto libraries. I am looking for source that does, or a way to make it work. – Chev_603 May 27 '16 at 21:23
  • slow down, and do some research on how to write the code. – Ryan May 27 '16 at 21:25
  • Yes, I am trying to do that, but am having trouble following the mbedtls api documentation, as C is not my best language, so I am asking for help. I am hoping somebody already has a solution. – Chev_603 May 27 '16 at 21:34
  • IMHO, this is the way a question should be asked. Well phrased, clear prove of research efforts. I also don't think the close votes apply, it's a question on how to solve a problem, not on recommending some library. – Ingo Bürk May 27 '16 at 21:47
  • Thank you for pointing that out, yes this is exactly that; a question of "How do I solve this problem?" It's not about specifics, I've left it pretty open ended for that reason. – Chev_603 May 27 '16 at 22:00
  • It seems you're asking *How do I translate the aescrypt2.c code to node.js*. Stack Overflow is not a code translation service, but you can start by reading the code you've linked to. node.js' crypto module provides everything you need to make the translation. Looking at your node.js code, it seems to me that you haven't even tried to read the aescrypt2.c source code. – Artjom B. May 28 '16 at 09:48
  • On the contrary, I am looking for a solution that already works with node crypto. It doesn't need to be aescrypt2, or even specifically using the crypto library for that matter-- I only am asking for a solution to encrypt data between node and mbedtls. I agree the crypto library *must* be able to do this, but I don't know how to do it. I will take another look at the aes source and try to refine the question though. – Chev_603 May 28 '16 at 23:32

1 Answers1

2

How would I, using nodejs, decrypt data encrypted by aescrypt2 (or a program like it)?

Sorry to say, but there's no better answer than: by doing the exact same thing that aescrypt2 does when decrypting a file. You've linked to the source by yourself, so just perform the same steps in node.js as they do in C in the decrypt branch.

First of all, get familiar with the layout of the file containing the encrypted data:

    /*
     *  The encrypted file must be structured as follows:
     *
     *        00 .. 15              Initialization Vector
     *        16 .. 31              AES Encrypted Block #1
     *           ..
     *      N*16 .. (N+1)*16 - 1    AES Encrypted Block #N
     *  (N+1)*16 .. (N+1)*16 + 32   HMAC-SHA-256(ciphertext)
     */

So you need to extract the IV, the encrypted blocks and the HMAC from the file, not try to decrypt the whole thing as you try with openssl (your openssl example also does not use the right IV but rather tries to derive it from the key provided - read the man page).

Next, get the key right. The actual key used to encrypt/decrypt is not the one provided on the command line, but rather 8192 iterations of hashing the IV with the key passed on the command line, using SHA256.

Finally, they decrypt, using AES-256-ECB (your openssl and node.js examples use CBC!), every 16 bytes and XOR the result with the pervious 16 bytes (the IV is used for the first 16 bytes).

There's maybe more to it, I just listed the most obvious things I saw when reading through the aescrypt2.c code.

So my advise is: try to write the same logic in node.js and try to find node.js crypto calls for the respective mbedtls counterparts.

I'm not a crypto expert, but I bet that the aescrypt implementation has so many steps that feel complicated (like generating the actual key used), because they know how to do crypto and are just doing it the right way.

grasbueschel
  • 879
  • 2
  • 8
  • 24
  • Thanks you, honestly I was not even sure which cipher aescrypt2 was using by default, so this definitively helps. I will likely end up accepting this answer, provided someone does not come along with an easier solution in the next two days. I will try your advice and report back tomorrow. Thanks again. – Chev_603 Jun 02 '16 at 04:17
  • glad I could help. As mentioned, the reason why the aescrypt2 way seems no to be easy is most likely because it needs to be done this way in order for the whole encryption process to be secure... – grasbueschel Jun 03 '16 at 14:21
  • The manual says -- 'the actual IV to use: this must be represented as a string comprised only of hex digits. When only the key is specified using the -K option, the IV must explicitly be defined. When a password is being specified using one of the other options, the IV is generated from this password.' -- Does this mean that I would hardcode an IV to use for each message, if it is not be derived from the key? If I were using a different IV per message, that would defeat the point of a preshared key, right? – Chev_603 Jun 04 '16 at 04:10
  • It means that if you don't derive it from a key, you should generate the IV yourself (make it as much random as possible). You never ever hardcode one! Also, it's not a pre-shared key. A pre-shared key must never be public, an IV can be. It's only there for randomness, so I think if you'd like to compare it to something, compare it to a password salt. – grasbueschel Jun 04 '16 at 18:00