Ruby中出现bad decrypt错误,Rails扩展String类解密失败求助
Fixing the "bad decrypt" Error in Your Rails String Encryption Extension
Let's break down why your code is throwing that "bad decrypt" error and fix it step by step.
What's Wrong With the Original Code?
You've got three critical issues here:
- You're ignoring the passed key
In bothencryptanddecrypt, you overwrite the inputkeywithcipher.random_key. That means you're encrypting with a random key, then trying to decrypt with a completely different random key—of course it fails! - No handling for Initialization Vector (IV)
DES-EDE3-CBC is a block cipher mode that requires an IV. OpenSSL generates a random IV automatically, but you never save or reuse it for decryption. Mismatched IVs will cause decryption to fail. - Redundant byte manipulation
The line[self].pack("H*").unpack("C*").pack("c*")is unnecessary and can introduce encoding issues.[self].pack("H*")already converts hex to binary correctly.
Fixed Code Implementation
Here's the corrected version with explanations:
require 'openssl' require 'digest' class String def encrypt(key) cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').encrypt # Process the input key to ensure it's the required 24 bytes for DES-EDE3 processed_key = Digest::SHA256.hexdigest(key)[0, 24] cipher.key = processed_key # Generate and save a random IV (required for CBC mode) iv = cipher.random_iv encrypted_data = cipher.update(self) + cipher.final # Return IV + encrypted data (both as hex, separated by a colon) "#{iv.unpack('H*')[0].upcase}:#{encrypted_data.unpack('H*')[0].upcase}" end def decrypt(key) # Split the stored IV and encrypted data iv_hex, encrypted_hex = split(':', 2) return nil unless iv_hex && encrypted_hex cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').decrypt # Use the same processed key as encryption processed_key = Digest::SHA256.hexdigest(key)[0, 24] cipher.key = processed_key # Reuse the exact IV from encryption cipher.iv = [iv_hex].pack('H*') # Convert hex back to binary and decrypt encrypted_data = [encrypted_hex].pack('H*') cipher.update(encrypted_data) + cipher.final rescue OpenSSL::Cipher::CipherError # Handle decryption failures gracefully nil end end
Key Improvements Explained
- Preserve the input key: We now use the passed key (processed to meet DES-EDE3's 24-byte requirement) instead of generating random keys for every operation.
- IV management: We generate a random IV during encryption, include it in the output, and reuse it for decryption—this is mandatory for CBC mode.
- Simplified byte conversion: Removed redundant unpack/pack steps that could break data integrity.
- Error handling: Added a rescue block to catch cipher errors and return
nilinstead of crashing.
Usage Example
# Test the implementation secret_key = "my_secure_master_key_123" original_text = "This is a secret message!" encrypted = original_text.encrypt(secret_key) decrypted = encrypted.decrypt(secret_key) puts "Original: #{original_text}" puts "Encrypted: #{encrypted}" puts "Decrypted: #{decrypted}" # Should match the original text
内容的提问来源于stack exchange,提问作者The Whiz of Oz
相关产品推荐
相关产品推荐

