2017-09-25 160 views
2

我有一個字符串,我想使用JavaScript Web加密API與AES-GCM進行加密。我可以對它進行加密,但是當我解密時,承諾被拒絕,並且我沒有收到各種描述性的錯誤消息。AES-GCM解密拒絕承諾

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 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 

     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的IV是一種安全風險,但我只是試圖讓這個工作進行測試。您可以提供的任何幫助非常感謝,因爲這一直在困擾我整天。提前致謝!

編輯:添加了鍍鉻調試錯誤消息

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

即使它可能不是「非常具有描述性「,你能引用這個錯誤信息嗎?什麼是'sta'?你能提供[MCVE]嗎? (強調**完整**) – Kaiido

+0

@Kaiido err是一個變量傳遞給函數時它被調用,並打印錯誤信息我認爲。 sta和ats分別將字符串轉換爲arrayBuffer和arraybuffer。編輯提供進一步的細節。 –

+0

調用'.importKey()'在哪裏? – guest271314

回答

0

例外的承諾被拒絕時,下面的例外是 遇到:

InvalidAccessError當請求的操作是無效的 提供的密鑰(如無效的加密算法,或 無效的鍵指定的加密算法)。

通行證encryptedresolve()aes_encrypt()通話和aes_decrypt()呼叫,而不是sta(data)作爲data通過data已經是一個ArrayBufferaes_decrypt功能

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 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 
 

 
    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); 
 
     }); 
 
     }); 
 
    }); 
 
    }); 
 
});

+0

注意'Promise'構造函數沒有必要。 – guest271314

+0

這怎麼能消除? –

+0

@TyEverett如何消除? – guest271314