我有一个字符串,我想用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:决定发布整个文件,因为它似乎与问题相关。
答案 0 :(得分:0)
例外当以下例外情况时,拒绝承诺 遇到:
当请求的操作对于无效时,InvalidAccessError 提供密钥(例如,无效的加密算法,或无效的密钥) 指定的加密算法)。
在encrypted
来电时将resolve()
传递给aes_encrypt()
并在data
来电时通过aes_decrypt()
,而不是sta(data)
,因为data
是已经是ArrayBuffer
函数内的aes_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 = "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;