3

I'm trying to encrypt some data in Mono C#, send it to a NodeJS server and decrypt it there. I'm trying to figure out what algorithms to use to match the two.

I send the encrypted string encoded with base64. So I do something like this in Javascript, where I know the key which was used to encrypt the data in my C# application:

var decipher = crypto.createDecipher('aes192',binkey, biniv);
var dec = decipher.update(crypted,'base64','utf8');
dec += decipher.final('utf8');
console.log("dec", dec);

In Mono I create my Cypher with:

using System.Security.Cryptography;
using (Aes aesAlg = Aes.Create("aes192"))

I need to pass the correct string to Aes.Create() in order to have it use the same algorithm, but I can't find what it should be. "aes192" is not correct it seems.

I don't need aes192 this was just a tryout. Suggest a different encryption flavor if it makes sense. Security is not much of an issue.

Here are links to .NET and Nodejs docs: http://msdn.microsoft.com/en-us/library/system.security.cryptography.aes.aspx http://nodejs.org/api/crypto.html

Thijs Koerselman
  • 21,680
  • 22
  • 74
  • 108
  • What are you protecting in what kind of situation? I think you might be better off using TLS in this case. – ntoskrnl Jun 26 '13 at 06:37
  • Since your issue seems to be .net, not the js. How about starting with an AES Then HMac or AES-GCM in c# http://stackoverflow.com/a/10366194/637783 and then work out your JS. – jbtule Jun 26 '13 at 13:20
  • @ntoskrnl I'm using this for challenge response pattern for license activation. – Thijs Koerselman Jun 27 '13 at 10:11
  • @jbtule encryption/decryption in c# is fine with the referenced example code. So I already have an encrypted string, it's just that I can't decrypt it on the Node.js side. – Thijs Koerselman Jun 27 '13 at 10:12

3 Answers3

1

This code works for my Node.js side, but please replace the static iv, otherwhise aes encryption would be useless.

var crypto = require('crypto');

function encrypt(data, key) {
    key = key || new Buffer(Core.config.crypto.cryptokey, 'binary'),
        cipher = crypto.createCipheriv('aes-256-cbc', key.toString('binary'), str_repeat('\0', 16));
    cipher.update(data.toString(), 'utf8', 'base64');
    return cipher.final('base64');
}

function decipher(data, key) {
    key = key || new Buffer(Core.config.crypto.cryptokey, 'binary'),
        decipher = crypto.createDecipheriv('aes-256-cbc', key.toString('binary'), str_repeat('\0', 16));
    decipher.update(data, 'base64', 'utf8');
    return decipher.final('utf8');
}

function str_repeat(input, multiplier) {
    var y = '';
    while (true) {
        if (multiplier & 1) {
            y += input;
        }
        multiplier >>= 1;
        if (multiplier) {
            input += input;
        } else {
            break;
        }
    }
    return y;
}

I hope this helps You.

NOTE: You need to deliver an 265bit aka 32 character key for this algorithm to work.

POSSIBLE .NET SOLUTION: This may help you Example

0

You should simply write new AesManaged().
You don't need to call Create().

You then need to set Key and IV, then call CreateDecryptor() and put it in a CryptoStream.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Well ok so you can write the code differently, but I know how to do the encryption with the key and IV. My question was how do I choose what AES flavor, so I can match it in Node.js for decryption. Or am I missing something? – Thijs Koerselman Jun 25 '13 at 21:52
  • In the meantime I've learned that the number is the key size, and you can query it from the aes object in c# with KeySize, it turns out to be 256 bytes. Still when I try 'aes-256-cbc' or 'aes-256' in nodejs I get this error TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length. Going to investigate further... – Thijs Koerselman Jun 25 '13 at 22:17
  • @0x80 You need to match the mode of operation and the padding on both sides. It helps to specify them explicitly so as not to rely on implementation specific behavior. – ntoskrnl Jun 26 '13 at 06:35
  • `CryptoStream` is only useful for large amounts of data where you don't want the whole input/output in a single array. – CodesInChaos Jun 27 '13 at 06:16
  • @ntoskrnl Any hints to where/how I can specify the padding and mode of operation? The NodeJS crypto modules doesn't seem to reference them for example. – Thijs Koerselman Jun 27 '13 at 10:08
  • @0x80 It seems that you can specify the mode of operation in the crypto.createCipher() call (e.g. `crypto.createCipher('aes-128-cbc')`). You can list all supported algorithms with crypto.getCiphers(). These crypto modules seem to use PKCS#7 padding by default. – ntoskrnl Jun 27 '13 at 11:48
0

It turned out to be a stupid mistake. I thought the create function in Node.js could take a variable argument count. Turns out you need to call the createDecipheriv() instead.

Just for the record, you can easily check the padding and mode by looking at those properties in the Aes object. The defaults are CBC and PKCS7. That padding is also used in nodejs crypto. So a for a 128 key size my code to decrypt a base64 encoded string would be:

var crypto = require('crypto');
var binkey = new Buffer(key, 'base64');
var biniv = new Buffer(iv, 'base64');
var decipher = crypto.createDecipheriv('aes-128-cbc', binkey, biniv);
var decrypted = decipher.update(crypted,'base64','utf8');
decrypted += decipher.final('utf8');
console.log("decrypted", decrypted);
Thijs Koerselman
  • 21,680
  • 22
  • 74
  • 108