Webcrypto PBKDF2-SHA1

问题描述 投票:1回答:1

我在使用PBKDF2和Webcrypto时遇到了一个问题。我想使用PBKDF2和SHA-1算法。目前,我有。

const ENCODING = "utf-8";
const HMACSHA1 = {name: "HMAC", "hash" : "SHA-1"};
const PBKDF2SHA1 = {name: "PBKDF2", "hash": "SHA-1"};

// str2binb takes a string and outputs an ArrayBuffer

async function pbkdf2_generate_key_from_string(string) { //  Working
  return crypto.subtle.importKey(
    "raw",
    str2binb(string),
    PBKDF2SHA1,
    false,
    ["deriveKey", "deriveBits"],
  );
}

async function pbkdf2_derive_salted_key(key, salt, iterations) {  // Not working
  return crypto.subtle.deriveKey(
    {
      "name": "PBKDF2",
      "salt": salt,
      "iterations": iterations,
      "hash": "SHA-1",
      "length": 160
    },
    key,
    {
      "name": "HMAC"
      "hash": "SHA-1",
      "length": 160
    },
    true,
    [ "encrypt", "decrypt"]
  );
}

然而我知道我一定是用错了,因为它是一个支持的密钥派生算法,根据Mozilla的神奇文档,在下面的 derivedKeyAlgorithm 支持HMAC以及HMAC-SHA1。我也有它的工作与 AES-GCM 相当直接。

当我尝试时,我得到的错误信息是:

salt = b64binb("QSXCR+Q6sek8bf92"); // ArrayBuffer
key = await pbkdf2_generate_key_from_string("pencil");
x = await pbkdf2_derive_salted_key(key, salt, 4096)

Uncaught DOMException: Cannot create a key using the specified key usages.

注:据我了解,现在已经不推荐使用SHA1了,这是为了支持传统。

注2:当我把上面的内容替换成时,就可以了。

async function pbkdf2_derive_salted_key(key, data, salt, iterations) {  // Not working
  return crypto.subtle.deriveKey(
    {
      "name": "PBKDF2",
      salt: salt,
      "iterations": iterations,
      "hash": "SHA-1",
    },
    key,
    {
      "name": "AES-GCM",
      "length": 256
    },
    true,
    [ "encrypt", "decrypt"]
  );
}

谢谢您。

javascript cryptography pbkdf2 hmacsha1 webcrypto
1个回答
0
投票

在这里,我的算法是,const ENCODING = "utf-8"; const HMACSHA1 = {name: "HMAC", "hash" : "SHA-1"}; ... deriveKey,参数 keyUsages 必须改成 ["sign", "verify"]. 然后代码就会工作(因为 b64binb, str2binb 没有发布,下面的代码使用适当的替代)。)

const b64binb = base64String => Uint8Array.from(atob(base64String), c => c.charCodeAt(0));
const str2binb = str => new TextEncoder().encode(str);
const buf2hex = buffer => Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');

async function pbkdf2_generate_key_from_string(string) { 
    return crypto.subtle.importKey(
        "raw",
        str2binb(string),
        {
            name: "PBKDF2",
        },
        false,
        ["deriveKey", "deriveBits"], 
    );
}

async function pbkdf2_derive_salted_key(key, salt, iterations) {  
    return crypto.subtle.deriveKey(
        {
            name: "PBKDF2",
            salt: salt,
            iterations: iterations,
            hash: {name: "SHA-1"}
        },
        key,
        {
            name: "HMAC",
            hash: "SHA-1",
            length: 160
        },
        true,
        ["sign", "verify"] // <--------------------- Fix!
    );
}

async function test(){
    salt = b64binb("QSXCR+Q6sek8bf92"); // ArrayBuffer
    key = await pbkdf2_generate_key_from_string("pencil");
    x = await pbkdf2_derive_salted_key(key, salt, 4096)

    console.log(buf2hex(await window.crypto.subtle.exportKey("raw", x)));
}

test();

有了这个键, window.crypto.subtle.sign 使用 HMAC-SHA1 创建签名。

更新。

因为在 微妙的加密技术 一般规定使用钥匙。["encrypt", "decrypt"] 必定 keyUsages AES-GCM的参数和 ["sign", "verify"] 为HMAC-SHA。

为什么?["encrypt", "decrypt"] 用于AES-GCM?AES-GCM用于 加密 解密 信息。AES 描述了 块状密码 (允许加密一个 单一 块)和 GCM运行方式 (允许加密的 更多 比单个区块)。) GCM提供保密性、真实性和完整性。

为什么呢?["sign", "verify"] 用于HMAC-SHA?HMAC用于 签核 信息。一些操作模式,如 加拿大广播公司 只提供保密性。要 另外 供给真实性和完整性,消息可以用以下方式签名 媒体访问控制中心 (例如:一个 HMAC 它是一种特定类型的MAC,基于一个特定的 加密哈希函数 例如,SHA系列中的一种)。) MAC通常是根据密文而不是明文计算出来的(加密后的MAC). 关于SHA1漏洞,见HMAC-SHA1和HMAC-SHA256的比较。此处此处.

© www.soinside.com 2019 - 2024. All rights reserved.