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

时间:2017-02-14 16:34:22

标签: 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

但是,如果我拿到那把钥匙,我们用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>'

此外,当我从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>'

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

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

1 个答案:

答案 0 :(得分:4)

这里有几个问题。

由于以下行,您的Ruby往返代码无效:

encrypted = cipher.update "flipflop" + cipher.final

应该是:

encrypted = cipher.update("flipflop") + cipher.final

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

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

以下是如何在Ruby中解密命令行加密字符串:

# Base64 cipher text from the question:
message = "Pd4+UEBW1RyTjARy1rpndQ=="
message = Base64.decode64(message)

key = "2317823178123897237891232345345234524523452345"
#Convert from hex to raw bytes:
key = [key].pack('H*')
#Pad with zero bytes to correct length:
key << ("\x00" * (32 - key.length))

iv ="123789123789123789"
#Convert from hex to raw bytes:
iv = [iv].pack('H*')
#Pad with zero bytes to correct length:
iv << ("\x00" * (16 - iv.length))

cipher = OpenSSL::Cipher.new('AES-256-CBC')
cipher.decrypt
cipher.key = key
cipher.iv = iv
plain = cipher.update(message) + cipher.final
puts plain # => 'flipflop'
相关问题