为什么我不能使“OpenSSL with Ruby”和“Command line OpenSSL”可以互操作?

在尝试建立可互操作的加密系统时,我在轻松的“概念validation”期间遇到了一种奇怪的情况。

我在Ruby中编写了以下代码:

  • 从我的文件系统上的虚拟文本文件创建加密文件
  • 解密加密文件
  • 与原始文件进行比较,并检查它们是否相同

这是代码:

require 'openssl' require 'base64' # Read the dummy file data = File.read("test.txt") # Create an encrypter cipher = OpenSSL::Cipher::AES.new(256, :CBC) cipher.encrypt key = "somethingreallyreallycomplicated" cipher.key = key # Encrypt and save to a file encrypted = cipher.update(data) + cipher.final open "encrypted.txt", "w" do |io| io.write Base64.encode64(encrypted) end # Create a decrypter decipher = OpenSSL::Cipher::AES.new(256, :CBC) decipher.decrypt decipher.key = key # Decrypt and save to a file encrypted_data = Base64.decode64(File.read("encrypted.txt")) plain = decipher.update(encrypted_data) + decipher.final open "decrypted.txt", "w" do |io| io.write plain end # Compare original message and decrypted message puts data == plain #=> true 

一切正常,这个脚本输出“true”

然后我尝试使用openssl命令行使用以下命令解密我的文件:

 openssl aes-256-cbc -d -a -in encrypted.txt -k somethingreallyreallycomplicated 

但我得到了: bad magic number

怎么会?

您需要在命令行上使用-K (大写)和-iv选项将键和IV显式指定为hex数字的字符串。 如果使用-k (小写),OpenSSL将使用密钥派生函数从密码派生密钥和IV。 当OpenSSL派生密钥时,它还将使用“盐渍”密文格式,这种格式与您期望的普通块状CBC不兼容。

请注意,在您的Ruby代码中,您直接使用ASCII字符串的前256位(32字节)作为键,这几乎肯定不是您想要的安全性问题的真实应用程序。 您应该使用(随机生成的)二进制密钥,或使用密钥派生函数(如PBKDF2 , bcrypt或scrypt)从密码派生密钥。