使用 CryptoJS returns 空白值的密码进行 AES 解密
AES decryption with password using CryptoJS returns a blank value
场景
我有以下代码:
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<div id="decrypted">Please wait...</div>
Insert new note:<input type="text" id="new_note"><input type="button" id="enc_button" value="Save">
<script>
var password = "testpassword";
var encrypted_text = localStorage.getItem("encrypted");
var rawData = atob(encrypted_text);
var iv = rawData.substring(0,16);
var crypttext = rawData.substring(16);
var plaintextArray = CryptoJS.AES.decrypt(
{ ciphertext: CryptoJS.enc.Latin1.parse(crypttext) },
CryptoJS.enc.Hex.parse(password),
{ iv: CryptoJS.enc.Latin1.parse(iv) }
);
var decrypted = CryptoJS.enc.Latin1.stringify(plaintextArray);
document.getElementById("decrypted").innerHTML = decrypted;
document.getElementById("enc_button").onclick = function(){
var text = document.getElementById("new_note").value;
var encrypted = CryptoJS.AES.encrypt(text, password);
localStorage.setItem("encrypted",encrypted);
}
</script>
我的代码应该做什么
使用 CryptoJS 使用 AES 加密字符串;解密保存在本地存储中的加密文本,并在 div
中显示结果
什么不起作用
虽然字符串似乎已加密,但变量 decrypt
是空的。 chrome 控制台中没有触发任何错误。
我的问题
如何成功加密和解密我的文本?
CryptoJS 有两种稍微不同的 encryption/decryption。
当您使用
var encrypted = CryptoJS.AES.encrypt(text, password);
那么您使用的是基于密码的加密,这与纯 key/IV-based 加密不同。这意味着密码和随机生成的 salt 运行 通过一次 MD5 调用生成用于实际加密的密钥和 IV。这是一种与 OpenSSL 兼容的加密方式。 encrypted
对象存储用于生成密钥和 IV 的随机盐。
当您强制将 encrypted
转换为字符串(例如将其添加到 localStorage)时,它会被转换为包含盐的 OpenSSL 兼容字符串编码。为了再次解密,你不需要自己弄乱密钥、IV 或盐,因为 CryptoJS 会自动为你做这些:
var decrypted = CryptoJS.AES.decrypt(encrypted, password);
请记住,decrypted
是一个 WordArray
对象,当您强制将其转换为字符串时,默认情况下会将内容编码为十六进制。如果你不想这样,那么你需要自己指定编码,比如 UTF-8。
由于密钥错误、密文错误或编码错误等原因导致解密失败时,通常会返回空白值。 CryptoJS 不会抛出自定义错误消息,但会尝试继续,因为您应该知道自己在做什么。
完整代码:
var password = "testpassword";
document.getElementById("enc_button").onclick = function(){
var text = document.getElementById("new_note").value;
var encrypted = CryptoJS.AES.encrypt(text, password);
encrypted = encrypted.toString();
var decrypted = CryptoJS.AES.decrypt(encrypted, password);
decrypted = decrypted.toString(CryptoJS.enc.Utf8)
document.getElementById("decrypted").innerHTML = decrypted;
}
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script>
<div id="decrypted">Please wait...</div>
Insert new note:<input type="text" id="new_note"><input type="button" id="enc_button" value="Encrypt & Decrypt">
我厌倦了通过将脚本放在 try-catch 中来调试您的代码,看起来 document.getElementById 返回未定义。这是因为在创建元素之前调用了该方法。以下步骤使这项工作有效:
负责人:
var password = "testpassword";
var encrypted_text = localStorage.getItem("encrypted");
var rawData = atob(encrypted_text);
var iv = rawData.substring(0,16);
var crypttext = rawData.substring(16);
var plaintextArray = CryptoJS.AES.decrypt(
{ ciphertext: CryptoJS.enc.Latin1.parse(crypttext) },
CryptoJS.enc.Hex.parse(password),
{ iv: CryptoJS.enc.Latin1.parse(iv) }
);
var decrypted = CryptoJS.enc.Latin1.stringify(plaintextArray);
function setComponents() {
try {
document.getElementById("decrypted").innerHTML = decrypted;
document.getElementById("enc_button").onclick = function(){
var text = document.getElementById("new_note").value;
var encrypted = CryptoJS.AES.encrypt(text, password);
localStorage.setItem("encrypted",encrypted);
alert(encrypted);
};
} catch(e) {
alert(e);
}
}
正文:
<body onload="setComponents()">
<div id="decrypted">Please wait...</div>
Insert new note:<input type="text" id="new_note"/><input type="button" id="enc_button" value="Save"/>
</body>
你可以直接查看源代码...有例子。
任何让它从密码短语生成密钥、iv 和盐的最简单方法,
是正常的方式 CryptoJS.AES.encrypt("attack at dawn!","passphrase")
但是您可以在 before 之前设置参数,例如:
CryptoJS.algo.AES.keySize=32
CryptoJS.algo.AES.blockSize=8
CryptoJS.algo.AES.ivSize=16
CryptoJS.algo.EvpKDF.cfg.iterations=100
CryptoJS.algo.EvpKDF.cfg.keySize=32
等等等等
场景
我有以下代码:
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<div id="decrypted">Please wait...</div>
Insert new note:<input type="text" id="new_note"><input type="button" id="enc_button" value="Save">
<script>
var password = "testpassword";
var encrypted_text = localStorage.getItem("encrypted");
var rawData = atob(encrypted_text);
var iv = rawData.substring(0,16);
var crypttext = rawData.substring(16);
var plaintextArray = CryptoJS.AES.decrypt(
{ ciphertext: CryptoJS.enc.Latin1.parse(crypttext) },
CryptoJS.enc.Hex.parse(password),
{ iv: CryptoJS.enc.Latin1.parse(iv) }
);
var decrypted = CryptoJS.enc.Latin1.stringify(plaintextArray);
document.getElementById("decrypted").innerHTML = decrypted;
document.getElementById("enc_button").onclick = function(){
var text = document.getElementById("new_note").value;
var encrypted = CryptoJS.AES.encrypt(text, password);
localStorage.setItem("encrypted",encrypted);
}
</script>
我的代码应该做什么
使用 CryptoJS 使用 AES 加密字符串;解密保存在本地存储中的加密文本,并在 div
中显示结果什么不起作用
虽然字符串似乎已加密,但变量 decrypt
是空的。 chrome 控制台中没有触发任何错误。
我的问题
如何成功加密和解密我的文本?
CryptoJS 有两种稍微不同的 encryption/decryption。
当您使用
var encrypted = CryptoJS.AES.encrypt(text, password);
那么您使用的是基于密码的加密,这与纯 key/IV-based 加密不同。这意味着密码和随机生成的 salt 运行 通过一次 MD5 调用生成用于实际加密的密钥和 IV。这是一种与 OpenSSL 兼容的加密方式。 encrypted
对象存储用于生成密钥和 IV 的随机盐。
当您强制将 encrypted
转换为字符串(例如将其添加到 localStorage)时,它会被转换为包含盐的 OpenSSL 兼容字符串编码。为了再次解密,你不需要自己弄乱密钥、IV 或盐,因为 CryptoJS 会自动为你做这些:
var decrypted = CryptoJS.AES.decrypt(encrypted, password);
请记住,decrypted
是一个 WordArray
对象,当您强制将其转换为字符串时,默认情况下会将内容编码为十六进制。如果你不想这样,那么你需要自己指定编码,比如 UTF-8。
由于密钥错误、密文错误或编码错误等原因导致解密失败时,通常会返回空白值。 CryptoJS 不会抛出自定义错误消息,但会尝试继续,因为您应该知道自己在做什么。
完整代码:
var password = "testpassword";
document.getElementById("enc_button").onclick = function(){
var text = document.getElementById("new_note").value;
var encrypted = CryptoJS.AES.encrypt(text, password);
encrypted = encrypted.toString();
var decrypted = CryptoJS.AES.decrypt(encrypted, password);
decrypted = decrypted.toString(CryptoJS.enc.Utf8)
document.getElementById("decrypted").innerHTML = decrypted;
}
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script>
<div id="decrypted">Please wait...</div>
Insert new note:<input type="text" id="new_note"><input type="button" id="enc_button" value="Encrypt & Decrypt">
我厌倦了通过将脚本放在 try-catch 中来调试您的代码,看起来 document.getElementById 返回未定义。这是因为在创建元素之前调用了该方法。以下步骤使这项工作有效:
负责人:
var password = "testpassword";
var encrypted_text = localStorage.getItem("encrypted");
var rawData = atob(encrypted_text);
var iv = rawData.substring(0,16);
var crypttext = rawData.substring(16);
var plaintextArray = CryptoJS.AES.decrypt(
{ ciphertext: CryptoJS.enc.Latin1.parse(crypttext) },
CryptoJS.enc.Hex.parse(password),
{ iv: CryptoJS.enc.Latin1.parse(iv) }
);
var decrypted = CryptoJS.enc.Latin1.stringify(plaintextArray);
function setComponents() {
try {
document.getElementById("decrypted").innerHTML = decrypted;
document.getElementById("enc_button").onclick = function(){
var text = document.getElementById("new_note").value;
var encrypted = CryptoJS.AES.encrypt(text, password);
localStorage.setItem("encrypted",encrypted);
alert(encrypted);
};
} catch(e) {
alert(e);
}
}
正文:
<body onload="setComponents()">
<div id="decrypted">Please wait...</div>
Insert new note:<input type="text" id="new_note"/><input type="button" id="enc_button" value="Save"/>
</body>
你可以直接查看源代码...有例子。
任何让它从密码短语生成密钥、iv 和盐的最简单方法,
是正常的方式 CryptoJS.AES.encrypt("attack at dawn!","passphrase")
但是您可以在 before 之前设置参数,例如:
CryptoJS.algo.AES.keySize=32
CryptoJS.algo.AES.blockSize=8
CryptoJS.algo.AES.ivSize=16
CryptoJS.algo.EvpKDF.cfg.iterations=100
CryptoJS.algo.EvpKDF.cfg.keySize=32
等等等等