Ruby 从预先存在的密钥字符串创建密码密钥

Bre*_*dly 3 ruby openssl

使用 OpenSSL CLI,我可以使用我能找到的几乎任何 ASCII 字符串来加密值,只要它符合加密方法所需的长度即可。

例如:

printf 'flipflop' | openssl enc -K 2317823178123897237891232345345234524523452345 -iv 123789123789123789 -base64 -aes-256-cbc

Pd4+UEBW1RyTjARy1rpndQ==

printf 'Pd4+UEBW1RyTjARy1rpndQ==\n' | openssl enc -d -K 2317823178123897237891232345345234524523452345 -iv 123789123789123789 -base64 -aes-256-cbc

flipflop
Run Code Online (Sandbox Code Playgroud)

但是,如果我拿了那个钥匙,我们用 Ruby 来解决这个问题:

require 'openssl'

cipher = OpenSSL::Cipher::Cipher.new 'AES-256-CBC'
cipher.encrypt
cipher.key = "2317823178123897237891232345345234524523452345"
cipher.iv = "123789123789123789"
encrypted = cipher.update "flipflop" + cipher.final
puts encrypted

cipher = OpenSSL::Cipher::Cipher.new 'AES-256-CBC'
cipher.decrypt
cipher.key = "2317823178123897237891232345345234524523452345"
cipher.iv = "123789123789123789"
plain = cipher.update(encrypted) + cipher.final
puts plain

???ISq???0?e?
crypt.rb:14:in `final': bad decrypt (OpenSSL::Cipher::CipherError)
    from crypt.rb:14:in `<main>'
Run Code Online (Sandbox Code Playgroud)

此外,当我从 openssl 命令中获取 base64 时,我得到了同样的错误解密:

require 'openssl'
require 'base64'

clear = Base64.decode64("Pd4+UEBW1RyTjARy1rpndQ==")

cipher = OpenSSL::Cipher::Cipher.new 'AES-256-CBC'
cipher.decrypt
cipher.key = "2317823178123897237891232345345234524523452345"
cipher.iv = "123789123789123789"
plain = cipher.update(clear) + cipher.final
puts plain

crypt.rb:10:in `final': bad decrypt (OpenSSL::Cipher::CipherError)
    from crypt.rb:10:in `<main>'
Run Code Online (Sandbox Code Playgroud)

我相信这里发生的是 OpenSSL 正在以一种方式转换我的密码密钥和 IV,而 ruby​​ 正在以另一种方式进行转换。例如,当您使用 PBKDF2 创建密钥时,您会得到一串十六进制值的字符串,即:“\x00\AF...”。

这是手头的问题吗?我需要将字符串转换为特定格式吗?我怎么做?这不是问题吗?

mat*_*att 5

这里有几个问题。

由于此行,您的 Ruby 往返代码无法正常工作:

encrypted = cipher.update "flipflop" + cipher.final
Run Code Online (Sandbox Code Playgroud)

它应该是:

encrypted = cipher.update("flipflop") + cipher.final
Run Code Online (Sandbox Code Playgroud)

这是导致bad decrypt错误的错误加密。否则该代码应该可以工作,尽管它使用的密钥和 ivs 与命令行版本不同。但是,它仅适用于旧版本的 Ruby 和 OpenSSL 绑定。当前版本的 Ruby 的 OpenSSL 库会检查keyiv提供的长度并在错误时引发异常。对于 aes-256-cbc,它们应该分别是 32 和 16 字节。

命令的-K-iv选项openssl enc接受十六进制编码的字符串,然后将其解码为原始字节。它还用零字节填充这些值,直到它们达到正确的长度。

以下是在 Ruby 中解密命令行加密字符串的方法:

encrypted = cipher.update "flipflop" + cipher.final
Run Code Online (Sandbox Code Playgroud)