AES-GCM解密拒绝承诺

时间:2017-09-25 01:12:58

标签: javascript encryption aes

我有一个字符串,我想用AES-GCM使用JavaScript Web Cryptography API加密。我可以加密它,但是当我去解密时,承诺会被拒绝,而且我没有收到不同的描述性错误消息。

    function aes_encrypt(key, IV, data){
        return new Promise(function(resolve, reject){
            window.crypto.subtle.encrypt(
            {
                name: "AES-GCM",

                //Don't re-use initialization vectors!
                //Always generate a new iv every time your encrypt!
                //Recommended to use 12 bytes length
                iv: sta(IV),

                //Tag length (optional)
                tagLength: 128, //can be 32, 64, 96, 104, 112, 120 or 128 (default)
            },
            key, //from generateKey or importKey above
            sta(data) //ArrayBuffer of data you want to encrypt
            )
            .then(function(encrypted){
                //returns an ArrayBuffer containing the encrypted data
                resolve(ats(encrypted));
            })
            .catch(function(err){
                console.error(err);
            });
        });
    }

    function aes_decrypt(key, IV, data){
        return new Promise(function(resolve, reject){
            window.crypto.subtle.decrypt(
            {
                name: "AES-GCM",
                iv: sta(IV), //The initialization vector you used to encrypt
                tagLength: 128 //The tagLength you used to encrypt (if any)
            },
            key, //from generateKey or importKey above
            sta(data) //ArrayBuffer of the data
            )
            .then(function(decrypted){
                //returns an ArrayBuffer containing the decrypted data
                alert(decrypted);
                resolve(ats(new Uint8Array(decrypted)));
                //resolve(ats(decrypted));
            })
            .catch(function(err){
                console.error(err);
            });
        });
    }



    function ecdh_generate_keypair(){
        return new Promise(function(resolve, reject){
            window.crypto.subtle.generateKey(
                {
                    name: "ECDH",
                    namedCurve: "P-384" //can be "P-256", "P-384", or "P-521"
                },
                true, //whether the key is extractable (i.e. can be used in exportKey)
                ["deriveKey", "deriveBits"] //can be any combination of "deriveKey" and "deriveBits"
            )
            .then(function(key){
                //returns a keypair object
                resolve(key);
            })
            .catch(function(err){
                console.error(err);
            });
        });
    }

    function ecdh_export(key){
        return new Promise(function(resolve, reject){
            window.crypto.subtle.exportKey(
                "jwk", //can be "jwk" (public or private), "raw" (public only), "spki" (public only), or "pkcs8" (private only)
                key //can be a publicKey or privateKey, as long as extractable was true
            )
            .then(function(keydata){
                //returns the exported key data
                resolve(keydata);
            })
            .catch(function(err){
                console.error(err);
            });
        });
    }

    function ecdh_import(key){
        return new Promise(function(resolve, reject){
            window.crypto.subtle.importKey(
                "jwk", //can be "jwk" (public or private), "raw" (public only), "spki" (public only), or "pkcs8" (private only)
                key,
                {   //these are the algorithm options
                    name: "ECDH",
                    namedCurve: "P-384", //can be "P-256", "P-384", or "P-521"
                },
                true, //whether the key is extractable (i.e. can be used in exportKey)
                ["deriveKey", "deriveBits"] //"deriveKey" and/or "deriveBits" for private keys only (just put an empty list if importing a public key)
            )
            .then(function(privateKey){
                //returns a privateKey (or publicKey if you are importing a public key)
                resolve(privateKey);
            })
            .catch(function(err){
                console.error(err);
            });
        });
    }

    function ecdh_derive_key(pub, priv){
        return new Promise(function(resolve, reject){
            window.crypto.subtle.deriveKey(
            {
                name: "ECDH",
                namedCurve: "P-384", //can be "P-256", "P-384", or "P-521"
                public: pub, //an ECDH public key from generateKey or importKey
            },
            priv, //your ECDH private key from generateKey or importKey
            { //the key type you want to create based on the derived bits
                name: "AES-GCM", //can be any AES algorithm ("AES-CTR", "AES-GCM", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH", or "HMAC")
                //the generateKey parameters for that type of algorithm
                length: 256, //can be  128, 192, or 256
            },
            true, //whether the derived key is extractable (i.e. can be used in exportKey)
            ["encrypt", "decrypt"] //limited to the options in that algorithm's importKey
            )
            .then(function(keydata){
                //returns the exported key data
                resolve(keydata);
            })
            .catch(function(err){
                console.error(err);
            });
        });
    }

    function random_characters(amount){
        var text = "";
        var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

        for (var i = 0; i < amount; i++){
            text += possible.charAt(Math.floor(Math.random() * possible.length));
        }

        return text;
    }

    // string-to-arraybuffer
    function sta(data){
        var enc = new TextEncoder("utf-8");
        return enc.encode(data);
    }

    // arraybuffer-to-string
    function ats(data){
        var enc = new TextDecoder();
        return enc.decode(data);
    }

    // JSON into and out of the database for cryptokeys
    function json_compress(obj){
        var s = JSON.stringify(obj);
        s = s.replace(/,/g, "♀");
        s = s.replace(/{/g, "☺");
        s = s.replace(/}/g, "☻");
        return s;
    }
    function json_decompress(str){
        str = str.replace(/♀/g, ",");
        str = str.replace(/☺/g, "{");
        str = str.replace(/☻/g, "}");
        return JSON.parse(str);
    }

    ecdh_generate_keypair().then(function(key){
        ecdh_generate_keypair().then(function(key2){
            ecdh_derive_key(key2.publicKey, key.privateKey).then(function(aeskey){
                var m = "Hello World!";
                aes_encrypt(aeskey, "abcdefghijkl", m).then(function(c){
                    alert(c);
                    aes_decrypt(aeskey, "abcdefghijkl", c).then(function(r){
                        alert(r);
                    });
                });
            });
        });
    });

我知道对AES进行硬编码是一种安全风险,但我只是试图将其用于测试目的。非常感谢您提供的任何帮助,因为这一直困扰着我。提前谢谢!

编辑:添加Chrome调试错误消息

cryptofunctions.js:48 DOMException
(anonymous) @ cryptofunctions.js:48
Promise rejected (async)
(anonymous) @ cryptofunctions.js:47
aes_decrypt @ cryptofunctions.js:31
(anonymous) @ cryptofunctions.js:184
Promise resolved (async)
(anonymous) @ cryptofunctions.js:182
Promise resolved (async)
(anonymous) @ cryptofunctions.js:180
Promise resolved (async)
(anonymous) @ cryptofunctions.js:179
Promise resolved (async)
(anonymous) @ cryptofunctions.js:178

编辑2:决定发布整个文件,因为它似乎与问题相关。

1 个答案:

答案 0 :(得分:0)

  

例外当以下例外情况时,拒绝承诺   遇到:

     当请求的操作对于无效时,

InvalidAccessError   提供密钥(例如,无效的加密算法,或无效的密钥)   指定的加密算法)。

encrypted来电时将resolve()传递给aes_encrypt()并在data来电时通过aes_decrypt(),而不是sta(data),因为data是已经是ArrayBuffer函数内的aes_decrypt

&#13;
&#13;
function aes_encrypt(key, IV, data) {
  return window.crypto.subtle.encrypt({
        name: "AES-GCM",

        //Don't re-use initialization vectors!
        //Always generate a new iv every time your encrypt!
        //Recommended to use 12 bytes length
        iv: sta(IV),

        //Tag length (optional)
        tagLength: 128, //can be 32, 64, 96, 104, 112, 120 or 128 (default)
      },
      key, //from generateKey or importKey above
      sta(data) //ArrayBuffer of data you want to encrypt
    )
    .then(function(encrypted) {
      //returns an ArrayBuffer containing the encrypted data
      return encrypted;
    })
    .catch(function(err) {
      console.error(err);
    });
}

function aes_decrypt(key, IV, data) {
  return window.crypto.subtle.decrypt({
        name: "AES-GCM",
        iv: sta(IV), //The initialization vector you used to encrypt
        tagLength: 128 //The tagLength you used to encrypt (if any)
      },
      key, //from generateKey or importKey above
      data //ArrayBuffer of the data
    )
    .then(function(decrypted) {
      //returns an ArrayBuffer containing the decrypted data
      // alert(decrypted);
      return ats(new Uint8Array(decrypted));
      //resolve(ats(decrypted));
    })
    .catch(function(err) {
      console.error(err);
    });
}



function ecdh_generate_keypair() {
  return window.crypto.subtle.generateKey({
        name: "ECDH",
        namedCurve: "P-384" //can be "P-256", "P-384", or "P-521"
      },
      true, //whether the key is extractable (i.e. can be used in exportKey)
      ["deriveKey", "deriveBits"] //can be any combination of "deriveKey" and "deriveBits"
    )
    .then(function(key) {
      //returns a keypair object
      return key;
    })
    .catch(function(err) {
      console.error(err);
    });
}

function ecdh_export(key) {
  return window.crypto.subtle.exportKey(
      "jwk", //can be "jwk" (public or private), "raw" (public only), "spki" (public only), or "pkcs8" (private only)
      key //can be a publicKey or privateKey, as long as extractable was true
    )
    .then(function(keydata) {
      //returns the exported key data
      return keydata;
    })
    .catch(function(err) {
      console.error(err);
    });
}

function ecdh_import(key) {
  return window.crypto.subtle.importKey(
      "jwk", //can be "jwk" (public or private), "raw" (public only), "spki" (public only), or "pkcs8" (private only)
      key, { //these are the algorithm options
        name: "ECDH",
        namedCurve: "P-384", //can be "P-256", "P-384", or "P-521"
      },
      true, //whether the key is extractable (i.e. can be used in exportKey)
      ["deriveKey", "deriveBits"] //"deriveKey" and/or "deriveBits" for private keys only (just put an empty list if importing a public key)
    )
    .then(function(privateKey) {
      //returns a privateKey (or publicKey if you are importing a public key)
      return privateKey;
    })
    .catch(function(err) {
      console.error(err);
    });
}

function ecdh_derive_key(pub, priv) {
  return window.crypto.subtle.deriveKey({
        name: "ECDH",
        namedCurve: "P-384", //can be "P-256", "P-384", or "P-521"
        public: pub, //an ECDH public key from generateKey or importKey
      },
      priv, //your ECDH private key from generateKey or importKey
      { //the key type you want to create based on the derived bits
        name: "AES-GCM", //can be any AES algorithm ("AES-CTR", "AES-GCM", "AES-CMAC", "AES-GCM", "AES-CFB", "AES-KW", "ECDH", "DH", or "HMAC")
        //the generateKey parameters for that type of algorithm
        length: 256, //can be  128, 192, or 256
      },
      true, //whether the derived key is extractable (i.e. can be used in exportKey)
      ["encrypt", "decrypt"] //limited to the options in that algorithm's importKey
    )
    .then(function(keydata) {
      //returns the exported key data
      return keydata;
    })
    .catch(function(err) {
      console.error(err);
    });
}

function random_characters(amount) {
  var text = "";
  var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

  for (var i = 0; i < amount; i++) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }

  return text;
}

// string-to-arraybuffer
function sta(data) {
  var enc = new TextEncoder("utf-8");
  return enc.encode(data);
}

// arraybuffer-to-string
function ats(data) {
  var enc = new TextDecoder();
  return enc.decode(data);
}

// JSON into and out of the database for cryptokeys
function json_compress(obj) {
  var s = JSON.stringify(obj);
  s = s.replace(/,/g, "♀");
  s = s.replace(/{/g, "☺");
  s = s.replace(/}/g, "☻");
  return s;
}

function json_decompress(str) {
  str = str.replace(/♀/g, ",");
  str = str.replace(/☺/g, "{");
  str = str.replace(/☻/g, "}");
  return JSON.parse(str);
}

ecdh_generate_keypair().then(function(key) {
  ecdh_generate_keypair().then(function(key2) {
    ecdh_derive_key(key2.publicKey, key.privateKey).then(function(aeskey) {
      var m = "Hello World!";
      aes_encrypt(aeskey, "abcdefghijkl", m).then(function(c) {
        // alert(c);
        aes_decrypt(aeskey, "abcdefghijkl", c).then(function(r) {
          alert(r);
        });
      });
    });
  });
});
&#13;
&#13;
&#13;

相关问题