如何使用 2048 位的 Diffie-Hellman 来创建密码?

How to use Diffie-Hellman with 2048 bits to create a cipher?

我正在尝试使用 crypto.createDiffieHellman(2048)list 中找到适合 2048 位长度的算法。换一种说法, 我让 Alice 和 Bob 使用他们相应的密钥来 encrypt/decrypt 向彼此发送消息。

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);

这会引发错误 Invalid key length。解决此问题的一种方法是执行 DH_LENGTH = 256。但是,这不是一个好主意,建议的最小长度为 2048 位。现在,我可以创建一个 2048 的密钥并在 256 的长度上做一个切片,但这与做一个 256 位的 DH 有什么不同。基本上攻击者必须猜测 first/last 256 位。

你说得对,你应该坚持 DHKE 推荐的尺寸。一种常见的方法是在 Diffie-Hellman 密钥交换的输出上使用密钥派生函数。

HKDF 适合你。 HKDF 遵循 "extract-then-expand" 范式,通常,如果您找到可以访问这些功能的实现,expand 就足够了。以下来自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 是您的派生密钥,请不要将其称为密码。不仅如此。命名为 sharedKeyexchangedKey 更好。

可选上下文可用于域分离,以便您可以为不同的应用派生不同的密钥。在这里查看数据; Multiple AES Key Derivation from a master key

并且,为了前向保密,不要忘记在使用后擦除密钥。

  • Why should we process the result of the Diffie-Hellman Key Exchange?

Diffie-Hellman 密钥交换的安全性基于决策 Diffie-Hellman 假设。这个假设表明交换的密钥是一个组元素,在计算上与组中的 random/uniformly 分布式元素无法区分。

必须注意结果不是均匀分布的元素,即每个比特有1/2的概率是0或1。MSB可能不是均匀分布的。

提取熵的推荐方法是使用哈希或更好的方法由密钥派生函数处理。 HKDF 在这里就好了。