You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 07:32:34