Generate RSA key pair with WebCrypto in Chromium

时间秒杀一切 提交于 2021-02-10 14:48:35

问题


The following code works in Firefox 76.0.1:

"use strict"
let RSAKeys
(async () => {
  RSAKeys = await crypto.subtle.generateKey({
      name: "RSA-OAEP",
      modulusLength: 3072,
      publicExponent: new Uint8Array([1, 0, 1]),
      hash: "SHA-256"},
    true,
// Chromium bug causes it to falsely complain that the array is empty. Sometimes adding "encrypt" helps.
    ["wrapKey"])
})()

but in Chromium 80 I get:

Uncaught (in promise) DOMException: Usages cannot be empty when creating a key.

["wrapKey"] clearly isn't an empty array, so it seems to be a browser bug. Probably this one. Can you confirm? And more importantly, do you know a workaround? (Adding the encrypt usage helped but only the first time, then the same error.) It has to be an asymmetric cipher supporting wrapping keys. According to the table in the relevant chapter of the spec, RSA-OAEP is the only possibility.


回答1:


I can reproduce the issue on Chromium version 85.0.4162.0: The key usage ["wrapKey"] generates the posted error message. But I can't reproduce that an adding of the key usage encrypt (i.e. ["wrapKey", "encrypt"]) solves the problem (not even the fist time). However, with the addition of the key usage unwrapKey (i.e. ["wrapKey", "unwrapKey"]) the error no longer occurs.

SubtleCrypto.generateKey() returns a CryptoKeyPair for "RSA-OAEP" that contains the RSA key pair. If you look in the Firefox browser console at the key pair generated with the key usage ["wrapKey", "unwrapKey"], you can see that the key usage of the public key is ["wrapKey"] and that of the private key is ["unwrapKey"]. Both are plausible, since the public key is used for wrapping and the private key for unwrapping:

However, if you look in the Firefox browser console at the key pair generated with the key usage ["wrapKey"], you can see that the key usage of the public key is unchanged ["wrapKey"], while that of the private key is empty:

So Chromium prevents the generation of a key without key usage by the corresponding error message (which obviously refers to the private key with the empty key usage). In contrast to Chromium, Firefox obviously allows this.

Now is that a Chromium bug? Actually it makes not much sense to create a key without a key usage, because it cannot be used!

Example for Firefox browser: If the following code is executed in the Firefox browser, the key pair is indeed generated and a key is wrapped because of the key usage wrapKey for the public key, but the unwrapping fails with an InvalidAccessError if the key usage unwrapKey for the private key is missing:

var test = async () => {

  try {
      
    var mode = document.querySelector('input[name="keyUsages"]:checked').value;
    var keyUsages = (mode === "wrap") ? ["wrapKey"] : ["wrapKey", "unwrapKey"] 
			  
    // Create RSA key pair
    var RSAKeys = await crypto.subtle.generateKey(
      {name: "RSA-OAEP", modulusLength: 3072, publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: {name: "SHA-256"}},
      true,
      keyUsages);
				
    // Create key to wrap
    var keyToWrap = await window.crypto.subtle.generateKey(
      {name: "AES-GCM", length: 128},
      true,
      ["encrypt", "decrypt"]);
				
    // Wrap key
    var wrappedKey = await window.crypto.subtle.wrapKey(
      "raw",
      keyToWrap,
      RSAKeys.publicKey,
      {name: "RSA-OAEP", hash: {name: "SHA-256"}});
			  
    // Unwrap key
    var unwrappedKey = await window.crypto.subtle.unwrapKey(
      "raw", 	
      wrappedKey, 	
      RSAKeys.privateKey, 
      {name: "RSA-OAEP", modulusLength: 3072, publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: {name: "SHA-256"}},
      {name: "AES-GCM", length: 128},
      false, 
      ["encrypt", "decrypt"]); 
				
    document.getElementById("result").innerHTML = "Secret key for " + unwrappedKey.algorithm.name + " unwrapped.";
    console.log(unwrappedKey);
 
    } catch(e) {
      document.getElementById("result").innerHTML = e.name + ": " + e.message;
    }
}
.as-console-wrapper { max-height: 7.0em !important; }
<!DOCTYPE html>
<html>
<body height="200">
    <input type="radio" name="keyUsages" value="wrap" checked="true"> ["wrapKey"] 
    <input type="radio" name="keyUsages" value="wrapUnwrap"> ["wrapKey", "unwrapKey"] 
    <button onclick="test()">Run</button><br/> 
    <p id="result"></p>
</body>
</html>

Therefore I would not classify this as a bug (but that's just my opinion).



来源:https://stackoverflow.com/questions/62113043/generate-rsa-key-pair-with-webcrypto-in-chromium

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!