HKDFExpand在NodeJS中

huangapple go评论71阅读模式
英文:

HKDFExpand in NodeJS

问题

Here are the translated parts:

Javascript:

import crypto from 'crypto';

const salt = 'salt';
const iterations = 100000;
const password = '123';

const masterKey = crypto.pbkdf2Sync(password, salt, iterations, 32, 'sha256');
const stretched = crypto.createHmac('sha256', 'enc').update(masterKey).digest();

console.log(masterKey.toString('hex')) // 5bb4...5990 <- Same
console.log(stretched.toString('hex')) // 82be...6890 <- Different

Python:

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import kdf, hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.kdf.hkdf import HKDFExpand

salt = 'salt'
iterations = 100000
password = b'123'

kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=bytes(salt, "utf-8"), iterations=iterations, backend=default_backend())
master_key = kdf.derive(password)

hkdf = HKDFExpand(algorithm=hashes.SHA256(), length=32, info=b"enc", backend=default_backend())
stretched = hkdf.derive(master_key)

print(master_key.hex()) # 5bb4...5990 <- Same
print(stretched.hex()) # 5bf9...473b <- Different 

I've provided the translated code parts without any additional content.

英文:

I try to implement HKDFExpand in NodeJS using crypto library
The goal is to decrypt encrypted bitwarden (password manager) password protected export in NodeJS.
I try to mimic the same behavior in NodeJS
but the expanded key is different from the python version which working for me.

Javascript:

import crypto from &#39;crypto&#39;

const salt = &#39;salt&#39;
const iterations = 100000
const password = &#39;123&#39;

const masterKey = crypto.pbkdf2Sync(password, salt, iterations, 32,&#39;sha256&#39;);
const streched = crypto.createHmac(&#39;sha256&#39;, &#39;enc&#39;).update(masterKey).digest();

console.log(masterKey.toString(&#39;hex&#39;)) // 5bb4...5990 &lt;- Same
console.log(streched.toString(&#39;hex&#39;)) // 82be...6890 &lt;- Different

Python:

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import kdf, hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.kdf.hkdf import HKDFExpand

salt = &#39;salt&#39;
iterations = 100000
password = b&#39;123&#39;

kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=bytes(salt, &quot;utf-8&quot;), iterations=iterations,backend=default_backend())
master_key = kdf.derive(password)

hkdf = HKDFExpand(algorithm=hashes.SHA256(), length=32, info=b&quot;enc&quot;, backend=default_backend())
streched = hkdf.derive(master_key)

print(master_key.hex()) # 5bb4...5990 &lt;- Same
print(streched.hex()) # 5bf9...473b &lt;- Different 

答案1

得分: 0

I found this function in the Bitwarden source code, and it works

function hkdfExpand(
    prk: Buffer,
    info: string,
    outputByteSize: number
) {
    const algorithm = "sha256";
    const hashLen = 32;
    const prkArr = new Uint8Array(prk);
    if (prkArr.length < hashLen) {
        throw new Error("prk is too small.");
    }
    const infoBuf = Buffer.from(info);
    const infoArr = new Uint8Array(infoBuf);
    let runningOkmLength = 0;
    let previousT = new Uint8Array(0);
    const n = Math.ceil(outputByteSize / hashLen);
    const okm = new Uint8Array(n * hashLen);
    for (let i = 0; i < n; i++) {
        const t = new Uint8Array(previousT.length + infoArr.length + 1);
        t.set(previousT);
        t.set(infoArr, previousT.length);
        t.set([i + 1], t.length - 1);
        previousT = new Uint8Array(hmac(t, prk, algorithm));
        okm.set(previousT, runningOkmLength);
        runningOkmLength += previousT.length;
        if (runningOkmLength >= outputByteSize) {
            break;
        }
    }
    return Buffer.from(okm.slice(0, outputByteSize).buffer);
}
英文:

I found this function in bitwarden source code, and it works

function hkdfExpand(
    prk: Buffer,
    info: string,
    outputByteSize: number
) {
    const algorithm = &quot;sha256&quot;
    const hashLen = 32;
    const prkArr = new Uint8Array(prk);
    if (prkArr.length &lt; hashLen) {
        throw new Error(&quot;prk is too small.&quot;);
    }
    const infoBuf = Buffer.from(info);
    const infoArr = new Uint8Array(infoBuf);
    let runningOkmLength = 0;
    let previousT = new Uint8Array(0);
    const n = Math.ceil(outputByteSize / hashLen);
    const okm = new Uint8Array(n * hashLen);
    for (let i = 0; i &lt; n; i++) {
        const t = new Uint8Array(previousT.length + infoArr.length + 1);
        t.set(previousT);
        t.set(infoArr, previousT.length);
        t.set([i + 1], t.length - 1);
        previousT = new Uint8Array(hmac(t, prk, algorithm));
        okm.set(previousT, runningOkmLength);
        runningOkmLength += previousT.length;
        if (runningOkmLength &gt;= outputByteSize) {
            break;
        }
    }
    return Buffer.from(okm.slice(0, outputByteSize).buffer);
}

huangapple
  • 本文由 发表于 2023年5月24日 23:32:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76325189.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定