Ruby加解密练习(ARGV)求助:encode正常但decode失败
Hey there! Let's break down why your decode function is throwing that "key too large" error, especially since your encode works perfectly. Based on what you described, this is almost always a mix-up between keys and ciphertext, or a mismatch between your encryption algorithm's requirements and how you're handling input.
Common Causes & Fixes
1. You're Using Encoded Ciphertext as a Key (Big Mistake!)
Symmetric encryption (which I assume you're using with OpenSSL) requires the same secret key for both encrypting and decrypting. The output from your encode function is the ciphertext (encrypted data), not a key. If you're passing that ciphertext into your decode function as the "key", it's way longer than valid key lengths for algorithms like AES—hence the "key too large" error.
Fix:
- Your program should accept a separate, fixed key via ARGV for both modes. For example:
- Encode:
ruby your_script.rb encode your_secret_key "plaintext here" - Decode:
ruby your_script.rb decode your_secret_key "ciphertext_from_encode"
- Encode:
2. Key Length Doesn't Match Your Encryption Algorithm
OpenSSL's cipher algorithms have strict key length requirements:
- AES-128: 16 bytes (128 bits)
- AES-192: 24 bytes (192 bits)
- AES-256: 32 bytes (256 bits)
If you initialized your cipher with, say, AES-256-CBC but passed a key longer than 32 bytes (or shorter!), you'll get errors. Accidentally passing ciphertext (which is way longer than 32 bytes) as the key triggers exactly this issue.
Fix:
- Add a check to validate key length before encryption/decryption:
# Example for AES-256 if key.bytesize != 32 puts "Error: AES-256 requires a 32-byte key (yours is #{key.bytesize} bytes)" exit 1 end
3. You're Forgetting to Decode Base64 Input
If your encode function outputs Base64-encoded text (common to make ciphertext printable), you need to decode it back to binary before passing it to the decrypt function. Skipping this step and passing the Base64 string directly (as a key or ciphertext) inflates the byte length, causing key errors.
Fix:
- When handling decode input, use
Base64.decode64()to convert the printable string back to binary:decoded_ciphertext = Base64.decode64(ARGV[2]) # Assuming ciphertext is the 3rd ARGV param
4. ARGV Parameter Order is Mixed Up
Double-check how you're parsing ARGV. If your code expects the key as the second argument but you're passing ciphertext there instead, that's a quick way to trigger the "key too large" error.
Fix:
- Add a usage message to clarify parameter order:
if ARGV.size < 3 puts "Usage: ruby #{$0} [encode/decode] <secret_key> <content>" exit 1 end mode = ARGV[0] key = ARGV[1] content = ARGV[2]
Example Working Snippet
Here's a trimmed-down, correct version of what your code should look like (using AES-256-CBC, a standard choice):
#!/usr/bin/ruby require "openssl" require "base64" def encode(key, plaintext) cipher = OpenSSL::Cipher.new('AES-256-CBC') cipher.encrypt cipher.key = key iv = cipher.random_iv # IV is required for decryption—don't lose it! encrypted = cipher.update(plaintext) + cipher.final Base64.strict_encode64(iv + encrypted) # Bundle IV and ciphertext together end def decode(key, encrypted_str) decoded = Base64.strict_decode64(encrypted_str) cipher = OpenSSL::Cipher.new('AES-256-CBC') cipher.decrypt iv = decoded[0...16] # Extract IV (first 16 bytes for AES block size) cipher.iv = iv cipher.key = key cipher.update(decoded[16..-1]) + cipher.final # Decrypt the actual ciphertext end # Handle input validation and parsing if ARGV.size < 3 puts "Usage: ruby #{$0} [encode/decode] <32_byte_key> <content>" exit 1 end mode, key, content = ARGV # Validate key length for AES-256 if key.bytesize != 32 puts "Error: AES-256 requires a 32-byte key (yours is #{key.bytesize} bytes)" exit 1 end begin if mode == "encode" puts encode(key, content) elsif mode == "decode" puts decode(key, content) else puts "Invalid mode: use 'encode' or 'decode'" end rescue => e puts "Error: #{e.message}" end
Quick Test Steps
- Generate a valid 32-byte key (e.g.,
openssl rand 32for raw binary, oropenssl rand -base64 24to get a Base64-encoded 32-byte key). - Encode a test string:
ruby your_script.rb encode "your_32_byte_key" "hello world" - Copy the output ciphertext, then decode it:
ruby your_script.rb decode "your_32_byte_key" "copied_ciphertext"
This should run without the "key too large" error.
内容的提问来源于stack exchange,提问作者Ofir Sasson

