
本教程详细介绍了如何在 laravel 后端解密由前端 cryptojs 库使用 aes 算法加密的数据。文章阐述了 cryptojs 特有的密钥和 iv 派生机制(基于 md5 和盐值),并提供了两种 php 实现方案:一是直接利用 `openssl_decrypt` 函数,二是将数据适配为 laravel `encrypter` 所需的格式进行解密,确保前后端加密解密的互操作性。
在现代 Web 应用中,前端 JavaScript 库(如 CryptoJS)进行数据加密,后端 PHP 框架(如 Laravel)进行解密是一种常见的实践。然而,由于不同加密库在密钥派生、盐值处理和数据格式上的差异,直接进行解密往往会遇到挑战。本文将深入探讨如何解决这些互操作性问题,特别是在 Laravel 中解密由 CryptoJS 使用 AES-256-CBC 算法加密的数据。
理解 CryptoJS 加密机制
当你在前端使用 CryptoJS.AES.encrypt(fileContent, key).toString() 进行加密时,key 参数实际上被视为一个密码短语(passphrase),而不是直接的加密密钥。CryptoJS 在内部执行以下关键步骤:
生成随机盐值(Salt):为了增加加密的随机性和抵抗彩虹表攻击,CryptoJS 会生成一个随机的 8 字节盐值。密钥和 IV 派生:CryptoJS 采用 OpenSSL 的 EVP_BytesToKey 机制,结合密码短语和盐值,通过 MD5 算法迭代生成实际的 32 字节加密密钥(Key)和 16 字节初始化向量(IV)。密文格式:最终生成的字符串是 Base64 编码的,其结构通常是 U2FsdGVkX1 前缀(表示数据已加盐),紧接着是 Base64 编码的盐值,然后是 Base64 编码的实际密文。
因此,要在 Laravel 中成功解密,核心任务是模拟 CryptoJS 的密钥和 IV 派生过程,并正确处理其数据格式。
实现 EVP_BytesToKey 密钥派生函数
这是在 PHP 中模拟 CryptoJS 行为的关键一步。我们需要一个函数来根据盐值和密码短语生成密钥和 IV。
<?php/** * 模拟 CryptoJS 的 EVP_BytesToKey 密钥派生函数。 * CryptoJS 使用 MD5 算法来派生密钥和 IV。 * * @param string $salt 8字节的盐值。 * @param string $password 原始密码短语。 * @return string 包含派生密钥和 IV 的字节串 (32字节密钥 + 16字节IV = 48字节)。 */function EVP_BytesToKey($salt, $password) { $bytes = ''; $last = ''; // AES-256 需要 32 字节密钥,CBC 模式需要 16 字节 IV。 // 所以总共需要 48 字节。 while (strlen($bytes)
方法一:使用 openssl_decrypt 直接解密
这种方法更直接,通过 PHP 的 openssl_decrypt 函数进行解密,它不依赖 Laravel Encrypter 的特定数据格式。
步骤
获取密文和密钥:从请求中获取 CryptoJS 加密的字符串和用于加密的原始密码短语。解码并分离盐值和密文:将 Base64 编码的密文解码,并从中提取盐值和实际的加密数据。派生密钥和 IV:使用前面定义的 EVP_BytesToKey 函数,根据原始密码短语和提取的盐值生成密钥和 IV。执行解密:使用 openssl_decrypt 函数,传入加密数据、派生密钥、IV 和正确的加密算法(aes-256-cbc)。
代码示例
注意事项
确保 PHP 环境已启用 openssl 扩展。OPENSSL_RAW_DATA 标志非常重要,它指示 openssl_decrypt 返回原始的解密数据,而不是 Base64 编码或填充后的数据。此方法不包含消息认证码(MAC)的验证,因此如果数据的完整性对你的应用至关重要,你可能需要额外的机制来验证数据未被篡改。
方法二:适配 Laravel Encrypter 进行解密
如果你希望利用 Laravel 框架自带的 Encrypter 类进行解密,你需要将 CryptoJS 生成的数据格式转换为 Laravel Encrypter 所期望的格式。Laravel Encrypter 期望的数据是一个 Base64 编码的 JSON 字符串,其中包含 iv、value、mac 和 tag。由于 CryptoJS 不生成 MAC,我们需要“伪造”一个。
步骤
前三步与方法一相同:获取密文和密钥,解码并分离盐值和密文,使用 EVP_BytesToKey 派生密钥和 IV。Base64 编码 IV 和密文:将派生出的 IV 和实际密文进行 Base64 编码。伪造 MAC:使用派生出的密钥和编码后的 IV 及密文生成一个 HMAC-SHA256。虽然这个 MAC 并非由 CryptoJS 生成,但它能满足 Laravel Encrypter 的格式要求。构建 Laravel 格式 JSON:将编码后的 IV、密文、伪造的 MAC 和一个空的 tag 封装成一个 JSON 对象。Base64 编码 JSON:将 JSON 字符串进行 Base64 编码。使用 Laravel Encrypter 解密:实例化 IlluminateEncryptionEncrypter,传入派生出的密钥和算法,然后调用 decryptString 方法。
代码示例
decryptString($laravelFormat);echo "使用 Laravel Encrypter 解密结果: " . $decrypted_laravel . PHP_EOL;?>
注意事项
此方法虽然使用了 Laravel Encrypter,但由于 MAC 是伪造的,实际上并没有提供数据完整性验证。这意味着即使数据在传输过程中被篡改,Laravel Encrypter 也可能成功解密(如果 MAC 伪造得当),而不会抛出 DecryptException。确保你使用的 Laravel 版本与 Encrypter 类的行为兼容。`$key
以上就是在 Laravel 中解密 CryptoJS AES 加密数据:两种实现方式的详细内容,更多请关注php中文网其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1537113.html
微信扫一扫
支付宝扫一扫