JavaScript WebCryptoApi: 为什么它不能满足特定操作的要求?

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

JavaScript WebCryptoApi: Why does this not satisfy operation specific requirements?

问题

以下是翻译好的部分:

设置:
 - 我生成了一个密钥加密密钥(kek,AES-GCM,256位)
 - 我生成了一个RSA-OAEP密钥对
 - 我使用AES-GCM-256和一个随机的iv来包装生成的私钥,以pkcs8格式导出
 - 我尝试解包装密钥,但在“导入”阶段失败

控制台显示的错误消息是“DOMException:提供给操作的数据不符合要求”,我已经创建了以下的MWE:

<!-- 开始代码片段:js 隐藏:false 控制台:true Babel:false -->

<!-- 语言:lang-js -->

    (async() => {
      let exportFormat = "pkcs8";


      const keyWrappingAlgorithm = {
          name: "AES-GCM",
          length: 256,
      }
      let keyPairAlgorithm = {
          name: "RSA-OAEP",
          modulusLength: 4096,
          publicExponent: new Uint8Array([1, 0, 1]),
          hash: "SHA-256",
      };


      let kek = await window.crypto.subtle.generateKey(
          keyWrappingAlgorithm, 
          true, 
          ["decrypt", "wrapKey", "unwrapKey"]
      );

      let keyPair = await crypto.subtle.generateKey(
          keyPairAlgorithm, 
          true, 
          ["encrypt", "decrypt"]
      )



      const iv = crypto.getRandomValues(new Uint8Array(96/8));



      let wrappedPrivateKey = await crypto.subtle.wrapKey(
          exportFormat,
          keyPair.privateKey,
          kek,
          {
              ...keyWrappingAlgorithm,
              iv: iv,
          }
      )

      let decryptedData = await crypto.subtle.decrypt(
          {
              ...keyWrappingAlgorithm,
              iv: iv,
          },
          kek,
          wrappedPrivateKey,
      )
      console.log("done 1", decryptedData)
      await crypto.subtle.importKey(
          exportFormat,
          decryptedData,
          keyPairAlgorithm,
          true,
          ["encrypt", "decrypt"]
      ).then(() => {
          console.log("Success 1! This was not expected.")
      }).catch((error) => console.log("error 1", error))

      let unwrappedKey = await crypto.subtle.unwrapKey(
          exportFormat,
          wrappedPrivateKey,
          kek,
          {
              ...keyWrappingAlgorithm,
              iv: iv,
          },
          keyPairAlgorithm,
          true,
          ["encrypt", "decrypt"]
      ).then(() => {
          console.log("Success 2! This was not expected.")
      }).catch((error) => console.log("error 2", error))
    })()

<!-- 结束代码片段 -->

发生了什么?如何纠正这种行为以解包装包装的密钥?

我已经坐在这里至少2个小时了,提取了MWE,但错误消息没有提供太多信息。我尝试更改导出格式,但没有真正帮助。所有密钥都是可导出的,所以这不应该是个问题。我也认为我已经添加了所有必需的密钥用途。

请注意,我已经去掉了代码部分,只提供了文本内容的翻译。如果需要更多帮助或有其他问题,请随时提出。

英文:

Setup:

  • I generate a key-encryption-key (kek, AES-GCM, 256)
  • I generate a RSA-OAEP keypair
  • I wrap the generated private key with the kek using AES-GCM-256 and a random iv, exported as pkcs8
  • I try to unwrap the key, this fails at the "import" stage

The error message shown in the console is "DOMException: Data provided to an operation does not meet requirements", I have managed to create a MWE as follows:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

(async() =&gt; {
  let exportFormat = &quot;pkcs8&quot;;


  const keyWrappingAlgorithm = {
      name: &quot;AES-GCM&quot;,
      length: 256,
  }
  let keyPairAlgorithm = {
      name: &quot;RSA-OAEP&quot;,
      modulusLength: 4096,
      publicExponent: new Uint8Array([1, 0, 1]),
      hash: &quot;SHA-256&quot;,
  };


  let kek = await window.crypto.subtle.generateKey(
      keyWrappingAlgorithm, 
      true, 
      [&quot;decrypt&quot;, &quot;wrapKey&quot;, &quot;unwrapKey&quot;]
  );

  let keyPair = await crypto.subtle.generateKey(
      keyPairAlgorithm, 
      true, 
      [&quot;encrypt&quot;, &quot;decrypt&quot;]
  )



  const iv = crypto.getRandomValues(new Uint8Array(96/8));



  let wrappedPrivateKey = await crypto.subtle.wrapKey(
      exportFormat,
      keyPair.privateKey,
      kek,
      {
          ...keyWrappingAlgorithm,
          iv: iv,
      }
  )

  let decryptedData = await crypto.subtle.decrypt(
      {
          ...keyWrappingAlgorithm,
          iv: iv,
      },
      kek,
      wrappedPrivateKey,
  )
  console.log(&quot;done 1&quot;, decryptedData)
  await crypto.subtle.importKey(
      exportFormat,
      decryptedData,
      keyPairAlgorithm,
      true,
      [&quot;encrypt&quot;, &quot;decrypt&quot;]
  ).then(() =&gt; {
      console.log(&quot;Success 1! This was not expected.&quot;)
  }).catch((error) =&gt; console.log(&quot;error 1&quot;, error))

  let unwrappedKey = await crypto.subtle.unwrapKey(
      exportFormat,
      wrappedPrivateKey,
      kek,
      {
          ...keyWrappingAlgorithm,
          iv: iv,
      },
      keyPairAlgorithm,
      true,
      [&quot;encrypt&quot;, &quot;decrypt&quot;]
  ).then(() =&gt; {
      console.log(&quot;Success 2! This was not expected.&quot;)
  }).catch((error) =&gt; console.log(&quot;error 2&quot;, error))
})()

<!-- end snippet -->

What is going on here? How can I correct this behavior and unwrap the wrapped key?

I've been sitting at this for at least 2 hours by now to extract the MWE, but the error message doesn't give much information. I tried changing the export format, but that didn't really help. The keys all are exportable, so this shouldn't be an issue either. I also think that I added all the required key usages..

答案1

得分: 2

以下是翻译好的部分:

对于RSA-OAEP私钥只能用于解密加密需要使用公钥),即必须使用`["decrypt"]`作为*keyUsages*而不是`["encrypt", "decrypt"]`错误消息*...无法使用指定的密钥用途创建密钥...*指出了这一点
如果在`importKey()``unwrapKey()`中应用`["decrypt"]`作为*keyUsages*导入和解包将正常工作

(async() => {
  let exportFormat = "pkcs8";
  const keyWrappingAlgorithm = {
      name: "AES-GCM",
      length: 256,
  }
  let keyPairAlgorithm = {
      name: "RSA-OAEP",
      modulusLength: 4096,
      publicExponent: new Uint8Array([1, 0, 1]),
      hash: "SHA-256",
  };

  let kek = await window.crypto.subtle.generateKey(
      keyWrappingAlgorithm, 
      true, 
      ["decrypt", "wrapKey", "unwrapKey"]
  );
  let keyPair = await crypto.subtle.generateKey(
      keyPairAlgorithm, 
      true, 
      ["encrypt", "decrypt"]
  )

  const iv = crypto.getRandomValues(new Uint8Array(96/8));

  let wrappedPrivateKey = await crypto.subtle.wrapKey(
      exportFormat,
      keyPair.privateKey,
      kek,
      {
          ...keyWrappingAlgorithm,
          iv: iv,
      }
  )

  let decryptedData = await crypto.subtle.decrypt(
      {
          ...keyWrappingAlgorithm,
          iv: iv,
      },
      kek,
      wrappedPrivateKey,
  )
  
  let decryptedKey = await crypto.subtle.importKey(
      exportFormat,
      decryptedData,
      keyPairAlgorithm,
      true,
      ["decrypt"]
  )
  console.log(decryptedKey);
  console.log(ab2hex(await crypto.subtle.exportKey('pkcs8', decryptedKey)));

  let unwrappedKey = await crypto.subtle.unwrapKey(
      exportFormat,
      wrappedPrivateKey,
      kek,
      {
          ...keyWrappingAlgorithm,
          iv: iv,
      },
      keyPairAlgorithm,
      true,
      ["decrypt"]
  )
  console.log(unwrappedKey);
  console.log(ab2hex(await crypto.subtle.exportKey('pkcs8', unwrappedKey)));
})()

function ab2hex(ab) { 
  return Array.prototype.map.call(new Uint8Array(ab), x => ('00' + x.toString(16)).slice(-2)).join('');
}

希望对你有所帮助!

英文:

For RSA-OAEP a private key can only be used for decryption (encryption is done with the public key), i.e. for keyUsages [&quot;decrypt&quot;] has to be used and not [&quot;encrypt&quot;, &quot;decrypt&quot;]. The error message ...Cannot create a key using the specified key usages... points this out.
If you apply [&quot;decrypt&quot;] as keyUsages in importKey() and unwrapKey() the importing and unwrapping works:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

(async() =&gt; {
let exportFormat = &quot;pkcs8&quot;;
const keyWrappingAlgorithm = {
name: &quot;AES-GCM&quot;,
length: 256,
}
let keyPairAlgorithm = {
name: &quot;RSA-OAEP&quot;,
modulusLength: 4096,
publicExponent: new Uint8Array([1, 0, 1]),
hash: &quot;SHA-256&quot;,
};
let kek = await window.crypto.subtle.generateKey(
keyWrappingAlgorithm, 
true, 
[&quot;decrypt&quot;, &quot;wrapKey&quot;, &quot;unwrapKey&quot;]
);
let keyPair = await crypto.subtle.generateKey(
keyPairAlgorithm, 
true, 
[&quot;encrypt&quot;, &quot;decrypt&quot;]
)
const iv = crypto.getRandomValues(new Uint8Array(96/8));
let wrappedPrivateKey = await crypto.subtle.wrapKey(
exportFormat,
keyPair.privateKey,
kek,
{
...keyWrappingAlgorithm,
iv: iv,
}
)
let decryptedData = await crypto.subtle.decrypt(
{
...keyWrappingAlgorithm,
iv: iv,
},
kek,
wrappedPrivateKey,
)
let decryptedKey = await crypto.subtle.importKey(
exportFormat,
decryptedData,
keyPairAlgorithm,
true,
[&quot;decrypt&quot;]
)
console.log(decryptedKey);
console.log(ab2hex(await crypto.subtle.exportKey(&#39;pkcs8&#39;, decryptedKey)));
let unwrappedKey = await crypto.subtle.unwrapKey(
exportFormat,
wrappedPrivateKey,
kek,
{
...keyWrappingAlgorithm,
iv: iv,
},
keyPairAlgorithm,
true,
[&quot;decrypt&quot;]
)
console.log(unwrappedKey);
console.log(ab2hex(await crypto.subtle.exportKey(&#39;pkcs8&#39;, unwrappedKey)));
})()
function ab2hex(ab) { 
return Array.prototype.map.call(new Uint8Array(ab), x =&gt; (&#39;00&#39; + x.toString(16)).slice(-2)).join(&#39;&#39;);
}

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年6月5日 11:26:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76403336.html
匿名

发表评论

匿名网友

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

确定