Reputation: 1880
I'm trying to find an algorithm within the list that accommodates 2048 bit length with using crypto.createDiffieHellman(2048)
. In other words,
I have Alice and Bob using their corresponding secret keys to encrypt/decrypt messages to each other.
const crypto = require('crypto'),
assert = require('assert'),
algorithm = 'aes-256-cbc',
IV_LENGTH = 16,
DH_LENGTH = 2048;
const alice = crypto.createDiffieHellman(DH_LENGTH);
const aliceKey = alice.generateKeys();
const bob = crypto.createDiffieHellman(alice.getPrime(), alice.getGenerator());
const bobKey = bob.generateKeys();
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey); // should be same as aliceSecret
const password = aliceSecret;
const iv = crypto.randomBytes(IV_LENGTH).toString('hex').slice(0, IV_LENGTH);
function encrypt(text){
const cipher = crypto.createCipheriv(algorithm, password, iv)
const crypted = `${cipher.update(text,'utf8','hex')}${cipher.final('hex')}`
return crypted;
}
function decrypt(text){
const decipher = crypto.createDecipheriv(algorithm, password, iv)
const dec = `${decipher.update(text,'hex','utf8')}${decipher.final('utf8')}`
return dec;
}
const msg = encrypt('Test');
const decryptedMsg = decrypt(msg)
console.log(msg, decryptedMsg);
This throws an error Invalid key length
. One way to fix this is to do DH_LENGTH = 256
. However, this is not a good idea with recommended minimum length being 2048 bits. Now, I can create a key with 2048 and do a slice on a length of 256 but how is this any different from doing a 256 bit DH. Basically the attacker having to guess the first/last 256 bits.
Upvotes: 1
Views: 1211
Reputation: 5636
You are right, you should stick to the recommended size for DHKE. A common way is using a key derivation function on the output of the Diffie-Hellman Key Exchange.
HKDF is fine for you. HKDF follows the "extract-then-expand" paradigm and, normally, the expand
would be enough if you find and implementation that gives access to those functions. The below is from futoin-hkdf;
const hkdf = require('futoin-hkdf');
// Parameter overview
//-------------------
// initial keying material
const ikm = 'string-or-buffer';
// required output length in bytes
const length = 32;
// can be empty string or false equivalent
const salt = 'strongly-encouraged';
// optional parameter
const info = 'optional-context';
// HMAC hashing algorithm to use
const hash = 'SHA-256';
// Generic derivation
//-------------------
hkdf(ikm, length, {salt, info, hash}); // Buffer(length) - derived key
IKM is your derived key, and please don't call it passwords. It is more than that. Naming like sharedKey
or exchangedKey
is better.
The optional context can be used for domain separation so that you can derive different keys for different applications. See the datils here; Multiple AES Key Derivation from a master key
And, for forward secrecy, don't forget to erase the key after use.
- Why should we process the result of the Diffie-Hellman Key Exchange?
The security of Diffie-Hellman key exchange is based on the Decisional Diffie-Hellman assumption. This assumption says that the exchanged key is a group element that is computationally indistinguishable from a random/uniformly distributed element in the group.
One must note that the result is not uniformly distributed element, i.e. each bit has 1/2 probability for being 0 or 1. The MSB may not be uniformly distributed.
The recommended way to extract the extropy is by using a hash or better to be processed by a Key Derivation Function. HKDF would be fine here.
Upvotes: 1