如何在Ruby中解密PHP AES-256-CBC加密的数据?
PHP AES-256-CBC加密数据的Ruby解密方案
问题背景
尝试用Ruby解密PHP通过AES-256-CBC加密的数据,PHP端解密代码正常运行,但Ruby复现逻辑时始终报错“Decryption failed”。
可正常运行的PHP解密代码
<?php function im_decrypt($ldata, $secret_key, $secret_iv) { $output = false; $encrypt_method = "AES-256-CBC"; $key = hash('sha512', $secret_key); $iv = substr(hash('sha512', $secret_iv), 0, 16); $output = openssl_decrypt(base64_decode($ldata), $encrypt_method, $key, 0, $iv); return $output; } // Sample usage $ldata = "dTZOR.............."; $secret_key = 'key......'; $secret_iv = 'iv.........'; $decrypted_data = im_decrypt($ldata, $secret_key, $secret_iv); if ($decrypted_data === false) { echo "Decryption failed\n"; } else { echo "Decrypted Data: " . $decrypted_data . "\n"; } ?>
尝试的Ruby代码(存在问题)
require 'openssl' require 'base64' require 'digest' class DecryptionService def initialize(encrypted_data, secret_key, secret_iv) @encrypted_data = encrypted_data @key = Digest::SHA512.digest(secret_key)[0, 32] # AES-256 key must be 32 bytes @iv = Digest::SHA512.digest(secret_iv)[0, 16] # IV must be 16 bytes end def decrypt decipher = OpenSSL::Cipher.new('aes-256-cbc') decipher.decrypt decipher.key = @key decipher.iv = @iv decoded_data = Base64.decode64(@encrypted_data) decrypted_data = decipher.update(decoded_data) + decipher.final decrypted_data rescue OpenSSL::Cipher::CipherError => e puts "Decryption failed: #{e.message}" nil end end # Sample usage encrypted_data = "dTZOR.............." secret_key = 'key......' secret_iv = 'iv.......' decryption_service = DecryptionService.new(encrypted_data, secret_key, secret_iv) decrypted_data = decryption_service.decrypt if decrypted_data puts "Decrypted Data: #{decrypted_data}" else puts "Decryption failed" end
问题分析
Ruby代码的核心错误在于密钥和IV的生成逻辑与PHP不一致:
- PHP中
hash('sha512', $secret_key)默认返回的是SHA512哈希的十六进制字符串(128个字符),直接将这个字符串作为密钥传入openssl_decrypt - Ruby中
Digest::SHA512.digest(secret_key)返回的是SHA512哈希的原始二进制字节流(64字节),两者的字节内容完全不匹配,导致解密失败
正确的Ruby解密代码
修正密钥和IV的生成逻辑,对齐PHP的十六进制字符串处理方式:
require 'openssl' require 'base64' require 'digest' class DecryptionService def initialize(encrypted_data, secret_key, secret_iv) @encrypted_data = encrypted_data # 生成与PHP一致的十六进制字符串密钥,取前32个字符(对应32字节) @key = Digest::SHA512.hexdigest(secret_key)[0, 32] # 生成与PHP一致的十六进制字符串IV,取前16个字符(对应16字节) @iv = Digest::SHA512.hexdigest(secret_iv)[0, 16] end def decrypt decipher = OpenSSL::Cipher.new('aes-256-cbc') decipher.decrypt decipher.key = @key decipher.iv = @iv decoded_data = Base64.decode64(@encrypted_data) decrypted_data = decipher.update(decoded_data) + decipher.final decrypted_data rescue OpenSSL::Cipher::CipherError => e puts "Decryption failed: #{e.message}" nil end end # Sample usage encrypted_data = "dTZOR.............." secret_key = 'key......' secret_iv = 'iv.......' decryption_service = DecryptionService.new(encrypted_data, secret_key, secret_iv) decrypted_data = decryption_service.decrypt if decrypted_data puts "Decrypted Data: #{decrypted_data}" else puts "Decryption failed" end
内容的提问来源于stack exchange,提问作者Sathvik V Shenoy
相关产品推荐
相关产品推荐

