Rails加密数据无法在Laravel解密,请求技术解决方案
Rails加密后Laravel无法解密的问题排查与修复
我帮你梳理了代码里的几个关键问题,这应该就是Laravel没法正常解密的根源:
1. HMAC参数顺序完全搞反了
OpenSSL::HMAC.hexdigest的参数顺序是 (摘要算法, 签名密钥, 待签名数据),但你当前代码里把「待签名数据」和「密钥」的位置写反了。Laravel计算MAC时,是用解码后的APP_KEY作为HMAC密钥,对iv + 加密后的内容进行签名,这一步错了的话,Laravel会直接判定MAC验证失败,根本不会尝试解密。
2. 别忘了处理APP_KEY的前缀
Laravel的APP_KEY默认是带base64:前缀的(比如base64:abcdef12345...),如果你的ENV变量里包含这个前缀,必须先去掉再做Base64解码,否则密钥会完全不对。
3. 用严格的Base64编码
Rails自带的Base64.encode64会自动加换行符,这会导致Laravel解析JSON时出错,一定要用Base64.strict_encode64来生成无换行的标准Base64字符串。
修正后的完整代码
require 'openssl' require 'base64' require 'php_serialize' # 确保已经安装了php_serialize gem def laravel_compatible_encrypt(plain_text) cipher = OpenSSL::Cipher.new('aes-256-cbc') raw_app_key = ENV['LARAVEL_APP_KEY'] # 移除Laravel APP_KEY的base64前缀(如果存在) clean_app_key = raw_app_key.gsub(/^base64:/, '') encryption_key = Base64.decode64(clean_app_key) cipher.encrypt cipher.key = encryption_key iv = cipher.random_iv cipher.iv = iv # 按照Laravel的规则序列化数据 serialized_data = PHP.serialize(plain_text) encrypted_payload = cipher.update(serialized_data) + cipher.final # 对IV和加密内容做标准Base64编码 iv_base64 = Base64.strict_encode64(iv) encrypted_base64 = Base64.strict_encode64(encrypted_payload) # 正确计算MAC:用加密密钥作为HMAC密钥,签名iv+加密内容 mac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), encryption_key, iv_base64 + encrypted_base64) # 组装Laravel要求的结构,再做一次Base64编码 final_payload = { iv: iv_base64, value: encrypted_base64, mac: mac }.to_json Base64.strict_encode64(final_payload) end # 测试加密 puts laravel_compatible_encrypt("1000")
Laravel端测试解密
你可以在Laravel里用这段代码验证:
$encryptedString = "替换成Rails输出的加密字符串"; $decrypted = decrypt($encryptedString); dd($decrypted); // 应该输出字符串"1000"
额外要确认的点
- 确保Rails和Laravel的APP_KEY完全一致(注意去掉前缀后的部分)
- 检查
PHP.serialize("1000")的输出是不是s:4:"1000";,和PHP原生serialize()的结果一致 - 最终生成的JSON结构没有多余的转义字符,Base64编码后没有换行
这样修改后,Laravel应该就能正常解密Rails加密的数据了。
内容的提问来源于stack exchange,提问作者Erick Setiawan
相关产品推荐
相关产品推荐

