我有麻烦解密在PHP与openssl_encrypt
方法加密的消息。我正在使用新的WebCrypto API(所以我使用crypto.subtle
)。麻烦解密OpenSSL的AES CTR加密文本
加密在PHP中:
$ALGO = "aes-256-ctr";
$key = "ae6865183f6f50deb68c3e8eafbede0b33f9e02961770ea5064f209f3bf156b4";
function encrypt ($data, $key) {
global $ALGO;
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($ALGO), $strong);
if (!$strong) {
exit("can't generate strong IV");
}
return bin2hex($iv).openssl_encrypt($data, $ALGO, $key, 0, $iv);
}
$enc = encrypt("Lorem ipsum dolor", $key);
exit($enc);
输出示例:
8d8c3a57d2dbb3287aca61be0bce59fbeAQ4ILKouAQ5eizPtlUTeHU=
(我可以解密,在PHP,并得到明文背面)
在JS我解密这样的:
function Ui8FromStr (StrStart) {
const Ui8Result = new Uint8Array(StrStart.length);
for (let i = 0; i < StrStart.length; i++) {
Ui8Result[i] = StrStart.charCodeAt(i);
}
return Ui8Result;
}
function StrFromUi8 (Ui8Start) {
let StrResult = "";
Ui8Start.forEach((charcode) => {
StrResult += String.fromCharCode(charcode);
});
return StrResult;
}
function Ui8FromHex (hex) {
for (var bytes = new Uint8Array(Math.ceil(hex.length/2)), c = 0; c < hex.length; c += 2)
bytes[c/2] = parseInt(hex.substr(c, 2), 16);
return bytes;
}
const ALGO = 'AES-CTR'
function decrypt (CompCipher, HexKey) {
return new Promise (function (resolve, reject) {
// remove IV from cipher
let HexIv = CompCipher.substr(0, 32);
let B64cipher = CompCipher.substr(32);
let Ui8Cipher = Ui8FromStr(atob(B64cipher));
let Ui8Iv = Ui8FromHex (HexIv);
let Ui8Key = Ui8FromHex (HexKey);
crypto.subtle.importKey("raw", Ui8Key, {name: ALGO}, false, ["encrypt", "decrypt"]). then (function (cryptokey){
return crypto.subtle.decrypt({ name: ALGO, counter: Ui8Iv, length: 128}, cryptokey, Ui8Cipher).then(function(result){
let Ui8Result = new Uint8Array(result);
let StrResult = StrFromUi8(Ui8Result);
resolve(StrResult);
}).catch (function (err){
reject(err)
});
})
})
}
当我现在运行decrypt("8d8c3a57d2dbb3287aca61be0bce59fbeAQ4ILKouAQ5eizPtlUTeHU=", "ae6865183f6f50deb68c3e8eafbede0b33f9e02961770ea5064f209f3bf156b4").then(console.log)
我得到乱码:SÌõÅ°blfçSÑ-
我的问题是,我不知道什么是counter
。我尝试了IV,但失败了。
This Github tutorial提示* ,它是IV - 或至少它的一部分,因为我已经看到人们谈论计数器是IV的一部分(类似4个字节,这意味着,四是从12个字节IV和4字节计数器)
如果这确实是真的做,那么我的问题是:我在哪里给脚本的其他12个字节IV的柜台时,只有4字节它。
谁能也许给我的加密工作的例子在PHP
* 它说,同样的柜台已被用于烯和解密。这使我相信,这是至少类似于IV
@zaph输出被做出来的十六进制IV的32个字符(16个字节)+为Base64密文的24个字符(17个字节) 密文总= 16 + 17 = 33 –
@zaph什么导致你认为密文是24字节?正如我所说,它已经预先IV,但IV是在十六进制。因此,基数64中的密文仅为17个字节(16字节的十六进制前缀 - 即32个字符的十六进制前缀) –
您拥有的是对IV和Base64编码的加密数据进行十六进制编码的错误混合。这是一个非常糟糕的主意,它肯定会使我困惑,并且肯定会失败[“最少惊奇规则”](http://principles-wiki.net/principles:Principle%20of%20Least%20Surprise?redirect=1),In界面设计,总是做最不令人意外的事情。 – zaph