如何将 AES Decrypt 从 Javascript 转换为 php

2024-02-01

我正在使用以下脚本:-

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>

并在控制台上运行它,如下所示:-

JSON.parse(CryptoJS.AES.decrypt("U2FsdGVkX1+S8UNrljj2STY8bBrYmr1qUbD2GYuJgIja1rzXY2y4BBkTf9GQxUGNyfRxP/BxiGIU7EFjnA2nTrM06ySr9bJySTjDDTqlDnY=", "87434313.47913419").toString(CryptoJS.enc.Utf8))

它成功解密了密钥大小为 17 的 AES,但是当我使用 PHP 和 phpseclib 运行它时,它会抛出错误Key of size 17 not supported

$data="U2FsdGVkX1+S8UNrljj2STY8bBrYmr1qUbD2GYuJgIja1rzXY2y4BBkTf9GQxUGNyfRxP/BxiGIU7EFjnA2nTrM06ySr9bJySTjDDTqlDnY=";
$key ="87434313.47913419";
$cipher = new AES('ecb');
$cipher->setKey($key);
echo $cipher->decrypt(base64_decode($data));

我究竟做错了什么?任何帮助表示赞赏!


正如在其他答案 https://stackoverflow.com/a/67809810/9014097,在 AES 的上下文中,CryptoJS 可以处理密钥(16、24 或 32 字节)或密码。这取决于第二个参数的类型CryptoJS.AES.encrypt()/decrypt(). A WordArray被解释为密钥,字符串被解释为密码。

在当前情况下,传递了一个字符串,因此将其作为密码进行处理。 CryptoJS 在加密过程中生成 8 字节的盐,并从盐和密码中派生出 32 字节的密钥和 16 字节的 IV。密钥导出函数是OpenSSL函数EVP_BytesToKey() https://www.openssl.org/docs/man1.1.1/man3/EVP_BytesToKey.html,它还需要一个摘要和一个迭代计数,并且 CryptoJS 使用值 MD5 和 1。

一个可能的实施EVP_BytesToKey()在 PHP 中为 AES-256/CBC 创建密钥/IV 对是:

// from: https://gist.github.com/ezimuel/67fa19030c75052b0dde278a383eda1b
function EVP_BytesToKey($salt, $password) {
    $bytes = '';
    $last = '';

    // 32 bytes key + 16 bytes IV = 48 bytes.
    while(strlen($bytes) < 48) {
        $last = hash('md5', $last . $password . $salt, true);
        $bytes.= $last;
    }
    return $bytes;
} 

CryptoJS 使用 OpenSSL 格式的密文,它由 ASCII 编码组成Salted__接下来是 8 字节盐和实际密文。发布的密文是该值的 Base64 编码。在解密过程中,盐和实际密文必须分开:

// Separate salt and ciphertext
$dataB64 = 'U2FsdGVkX1+S8UNrljj2STY8bBrYmr1qUbD2GYuJgIja1rzXY2y4BBkTf9GQxUGNyfRxP/BxiGIU7EFjnA2nTrM06ySr9bJySTjDDTqlDnY=';
$data = base64_decode($dataB64);
$salt = substr($data, 8, 8);
$ciphertext = substr($data, 16);

现在 key 和 IV 可以确定如下:

// Derive key and iv
$passphrase = '87434313.47913419';
$keyiv = EVP_BytesToKey($salt, $passphrase);
$key = substr($keyiv, 0, 32); // hex encoded: e8db19b984ed9196fff1ce9150b73eafc4cb13abe69e6dcc1ea1528dd88982ff
$iv = substr($keyiv, 32, 16); // hex encoded: 47e26ab2bf3b66eda871d4929cc91029

并且可以解密实际的密文,例如使用 phpseclib:

use phpseclib\Crypt\AES;

$cipher = new AES('cbc');
$cipher->setKey($key);
$cipher->setIV($iv);
$plaintext = $cipher->decrypt($ciphertext);
echo json_decode($plaintext); // https://xcdn-209.bato.to/7002/32e/60af5c1a22f39459ededde23/

由于CryptoJS采用OpenSSL格式,因此密文兼容OpenSSL,也可以如下解密:

openssl enc -d -aes-256-cbc -p -pass pass:87434313.47913419 -md md5 -A -a -in <file containing the U2FsdGVk...>

注意EVP_BytesToKey()被认为是不安全的。更安全的方法是使用可靠的密钥导出函数,如 Argon2 或 PBKDF2(CryptoJS 也支持后者)来导出密钥和 IV,并使用这些值执行加密。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将 AES Decrypt 从 Javascript 转换为 php 的相关文章

  • Zend Framework 生成唯一的字符串

    我想生成一个唯一的 4 6 个字符长的字母数字字符串 以便与每个记录 用户 一起保存在数据库中 db 字段具有唯一索引 因此尝试保存预先存在的字符串会生成错误 现在我正在生成一个随机字符串并使用 try catch 因此在添加新记录时如果抛
  • PHP 如何判断用户是否按下了 Enter 键或 Submit 按钮?

    我遇到的问题是我在一个表单中有多个提交输入 每个提交输入都有不同的值 我更愿意将它们保留为提交 Whenever the user presses Enter it is as though the topmost submit input
  • 删除PHP字符串中所有不匹配的字符?

    我有一个文本 我想从中删除所有不属于以下字符的字符 所需字符 0123456789 abcdefghijklmnopqrstuvwxyz n 最后一个是我确实想保留的 n 换行符 要匹配除列出的字符之外的所有字符 请使用反转字符集 http
  • 单词之间没有空格的语言(例如亚洲语言)中的断词?

    我想让 MySQL 全文搜索适用于日语和中文文本以及任何其他语言 问题在于这些语言以及可能其他语言通常在单词之间没有空格 当您必须键入与文本中相同的句子时 搜索没有用 我不能只在每个字符之间添加空格 因为英语也必须有效 我想用 PHP 或
  • 如何使用 phpunit 运行单个测试方法?

    我正在努力运行一个名为testSaveAndDrop在文件中escalation EscalationGroupTest php with phpunit 我尝试了以下组合 phpunit EscalationGroupTest escal
  • 如何检查PHP变量是否包含非数字?

    我只是想知道检查 PHP 变量中是否有非数字的方法以及它是否也检测字符之间的空格 需要确保我的表单字段中没有添加任何奇怪的内容 提前致谢 如果您的意思是您只想要一个包含数字的值 那么您可以使用ctype digit http php net
  •  
    标记内删除

    我制作了简单的 BBCode 脚本 一切正常 但后来我使用了一个 javascript 库来美化我的代码 pre pre 现在我面临的唯一问题是 br 每行代码后面的标签 pre pre tags 所以问题是我怎样才能删除 br 标记哪些在
  • 为什么我需要结束 ob_start()?

    php 文档建议我应该用 ob end flush 结束每个 ob start 我在网站的每个页面上使用一个 只是为了允许我在应用程序中的任何位置使用 firephp 日志方法 该应用程序运行良好 但我想知道是否有任何我不知道的东西可能有害
  • preg_match_all 查询仅显示有问题的外部组

    我无法弄清楚如何只显示 preg 查询的外部组级别 我会给你一个例子 preg match all start end input matches 这个输入start1 start2 2end 1end产生这个输出start1 start2
  • “使用未定义常量”注意,但该常量应该被定义

    共有三个文件 common php controller php 和 user php 文件 common php 如下所示 文件controller php看起来像 文件 user php 如下所示 执行脚本时 会给出通知 注意 使用未定
  • 在 PHP 中使用 phpseclib 时出现 RSA 问题

    我正在尝试在 phpseclib 中使用 RSA 实现 我认为在函数中执行一次代码并重新使用该函数会更容易 当我尝试向代码发送短信时 我收到一条错误消息 提示 解密错误 测试还让我意识到每次代码运行时密文都是不同的 所以我显然在那里做错了什
  • 在 Wordpress 站点中进行 AJAX 调用时出现问题

    我在使用 Wordpress 站点功能的 AJAX 部分时遇到了一些问题 该功能接受在表单上输入的邮政编码 使用 PHP 函数来查找邮政编码是否引用特定位置并返回到该位置的永久链接 我的第一个问题是关于我构建的表单 现在我的表单操作是空白的
  • 覆盖控制器 Symfony 3.4/4.0

    我目前正在尝试覆盖 FOSUserBundle 中的控制器 在新的文档中 https symfony com doc 3 4 bundles override html https symfony com doc 3 4 bundles o
  • Mac 应用程序商店 - 尝试让加密发挥作用。 。 。我缺少什么?

    我正在尝试使用 Alan Quartermain 的解决方案 如该问题所链接 Mac App Store 收据验证码 https stackoverflow com questions 4261348 mac app store recei
  • 跟踪用户何时点击浏览器上的后退按钮

    是否可以检测用户何时单击浏览器的后退按钮 我有一个 Ajax 应用程序 如果我可以检测到用户何时单击后退按钮 我可以显示适当的数据 任何使用 PHP JavaScript 的解决方案都是优选的 任何语言的解决方案都可以 只需要我可以翻译成
  • 表单计算器脚本基本价格未加载 OnLoad

    我的表单中有一个计算器来计算我的下拉选项选择 function select calculate on change calc input type checkbox calculate on click calc function cal
  • 表单提交后如何保留选择字段中的选定值?

    我有一个用于将票证上传到数据库的主页 我有一个选择字段 我想保留用户在提交表单之前选择的值 但它没有发生 这是我选择字段的代码
  • php 错误 fopen(): 文件名不能为空

    发送带有附件代码的电子邮件工作正常 最近我们已将文件传输到另一个托管服务器 idk 发生了什么 它显示以下错误 警告 fopen 第 106 行 home hugerecruitmetnt public html validatecva p
  • 如何在 PHP 中从 IP 地址/国家/地区名称查找时区 ID?

    谁能告诉我 PHP 中是否有任何方法可以从 IP 地址或国家 地区名称获取时区区域 例如 亚洲 加尔各答 描述 我正在尝试根据他 她的国家 地区设置用户时区 我从他的 IP 地址获取用户所在国家 地区 但我需要该国家 地区的时区区域 例如
  • 无法显示 Laravel 欢迎页面

    我的服务器位于 DigitalOcean 云上 我正在使用 Ubuntu 和 Apache Web 服务器 我的家用计算机运行的是 Windows 7 我使用 putty 作为终端 遵循所有指示https laracasts com ser

随机推荐