当前位置: 首页 > 知识库问答 >
问题:

如何解密在PHP上加密的AES256数据并在Javascript中获得价值?

马峻
2023-03-14

我在PHP上使用aes-256-cbc模式加密了一些值,如下所示:

public function encrypt(string $data): string
{
    $iv = $this->getIv();
    $encryptedRaw = openssl_encrypt(
        $data,
        $this->cryptMethod, //aes-256-cbc
        $this->key,
        OPENSSL_RAW_DATA,
        $iv
    );
    $hash = hash_hmac('sha256', $encryptedRaw, $this->key, true);

    return base64_encode( $iv . $hash . $encryptedRaw );
}

然后我试着在PHP上解密,结果很好:

    public function decrypt(string $data): string
{
    $decoded = base64_decode($data);
    $ivLength = openssl_cipher_iv_length($this->cryptMethod);
    $iv = substr($decoded, 0, $ivLength);
    $hmac = substr($decoded, $ivLength, $shaLength = 32);
    $decryptedRaw = substr($decoded, $ivLength + $shaLength);
    $originalData = openssl_decrypt(
        $decryptedRaw,
        $this->cryptMethod,
        $this->key,
        OPENSSL_RAW_DATA,
        $iv
    );

所以我是JavaScript新手,我不知道如何实现与php相同的解密方法。

加密字符串及其密钥示例:

加密字符串< code > luimppajich/e 44 mwkr 0 q 9 xdyjh 5 q 8 zej hi 8 etax 5 brl 78 vsyh wdknmbga 1 l 8 SD za 6 wkz 1 cvaarefgreraq = = 密钥-< code > 9sj 6o 6 iwmitsricbxgdj

我找到的返回空字符串的示例:

    const decodedString = base64.decode(
  `lUIMFpajICh/e44Mwkr0q9xdyJh5Q8zEJHi8etax5BRl78Vsyh+wDknmBga1L8p8SDZA6WKz1CvAAREFGreRAQ==`
);

const CryptoJS = require("crypto-js");

var key = CryptoJS.enc.Latin1.parse("9SJ6O6IwmItSRICbXgdJ");
var iv = CryptoJS.enc.Latin1.parse(decodedString.slice(0, 16));
var ctx = CryptoJS.enc.Base64.parse(
  "lUIMFpajICh/e44Mwkr0q9xdyJh5Q8zEJHi8etax5BRl78Vsyh+wDknmBga1L8p8SDZA6WKz1CvAAREFGreRAQ=="
);
var enc = CryptoJS.lib.CipherParams.create({ ciphertext: ctx });
console.log(
  CryptoJS.AES.decrypt(enc, key, { iv: iv }).toString(CryptoJS.enc.Utf8)
);

}

我做错了什么?

共有2个答案

邢飞鸿
2023-03-14

给你的几点想法:

  • 检查您的编码/解码是否正常工作。对于过程的每个阶段,内分/解码,然后控制台记录输出并将输入与输出进行比较,以及PHP和javascript之间的输入。
  • CBC 模式使用填充来填充块。检查两个堆栈是否使用相同的填充类型。
  • 与其使用CBC和单独的HMAC,不如跳转到AEAD(如AES GCM),这样可以避免填充问题,并且还将MAC合并到加密中,那么更简单的接口呢?
公羊涛
2023-03-14

PHP代码中使用的密钥大小仅为20字节,因此对于AES-256来说太小(AES-2566需要32字节的密钥)。PHP/OpenSSL使用0x00值将密钥隐式填充到所需的密钥长度。在CryptoJS代码中,这必须显式完成。

此外,在 CryptoJS 代码中,IV(前 16 个字节)、HMAC(接下来的 32 个字节)和密文(其余部分)未正确分隔。

此外,缺少身份验证。为此,必须使用密钥确定密文的 HMAC,并与发送的 HMAC 进行比较。仅当身份验证成功时,才会进行解密。

如果考虑到所有这些因素,则可以修复已发布的代码,例如:

var key = CryptoJS.enc.Utf8.parse("9SJ6O6IwmItSRICbXgdJ".padEnd(32, "\0")); // pad key
var ivMacCiphertext = CryptoJS.enc.Base64.parse("lUIMFpajICh/e44Mwkr0q9xdyJh5Q8zEJHi8etax5BRl78Vsyh+wDknmBga1L8p8SDZA6WKz1CvAAREFGreRAQ==")

var iv = CryptoJS.lib.WordArray.create(ivMacCiphertext.words.slice(0, 4)); // get IV
var hmac = CryptoJS.lib.WordArray.create(ivMacCiphertext.words.slice(4, 4 + 8)); // get HMAC
var ct = CryptoJS.lib.WordArray.create(ivMacCiphertext.words.slice(4 + 8)); // get Ciphertext

var hmacCalc = CryptoJS.HmacSHA256(ct, key);
if (hmac.toString() === hmacCalc.toString()) { // authenticate
    var dt = CryptoJS.AES.decrypt({ciphertext: ct}, key, { iv: iv }).toString(CryptoJS.enc.Utf8); // decrypt
    console.log(dt);
} else {
    console.log("Decryption failed");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
 类似资料:
  • 问题内容: 我目前是一名学生,并且正在学习PHP,我正在尝试对PHP中的数据进行简单的加密/解密。我进行了一些在线研究,其中一些非常令人困惑(至少对我而言)。 这是我想做的事情: 我有一个包含这些字段 (用户ID,Fname,Lname,Email,Password)的表 我要拥有的是先将所有字段加密,然后再解密(如果没有任何加密算法,是否可以用于加密/解密) 我想学习的另一件事是如何创建一种与优

  • 我有一个由以下字段组成的表(UserID、Fname、Lname、Email、Password) 我想要的是加密所有字段,然后解密(如果没有任何加密算法,是否可以使用进行加密/解密) 我想学的另一件事是如何创建一个单向的并结合一个好的“salt”。(基本上我只想有一个加密/解密的简单实现,先生/女士,您的回答将会有很大的帮助,非常感谢。谢谢++

  • 问题内容: 我有一些需要解密的加密文本。它使用AES-256-CBC加密。我有加密的文本,密钥和iv。但是,无论我尝试什么,我似乎都无法正常工作。 互联网建议mcrypt的Rijndael密码应该能够做到这一点,所以这就是我现在所拥有的: 目前,我收到2条警告,并且输出乱码: 任何帮助,将不胜感激。 问题答案: 我并不十分熟悉的东西,但它似乎是试图替代将是一个明显的下一个步骤… 编辑: 您是对的,

  • 客户端(4.2.1)应用程序通过请求向(5.6)API发送公钥。此API使用符合的加密数据,然后使用OpenSSL public encryption和的客户端公钥加密AES加密的密钥。它将通过编码的数据发送回客户端android应用程序,客户端android应用程序将加密数据。我已经设置了一个基本的PHP测试脚本来测试整个过程,这是预期的工作。 目前,我正在客户端Android应用程序中实现解密

  • 问题内容: 我这样在Node.js中加密了一个字符串。 我注意到nodejs中的缓冲区就像十六进制,但每2个连续字符都成对出现。因此,如果我将其转换为十六进制,则长度只有一半。 例: 缓冲: 十六进制: 现在,我在aes256中使用的密钥的长度不能为64。这里,缓冲区的长度为32,十六进制的长度为64。 我想在golang中解密此密码,我将不得不使用此密钥和iv对其进行解密。 golang中的ae

  • 后台返回的json数据经过Base64加密,js怎么解密? ........