Reputation: 11533
I am trying to AES encrypt some data, and I use random_iv
to generate an initialization vector.
def encrypt (data)
cipher = OpenSSL::Cipher::AES.new(256, :CBC)
cipher.encrypt
cipher.key = @key
iv = cipher.random_iv
encrypted = cipher.update(data) + cipher.final
encoded = Base64.encode64(encrypted+iv)
return encoded, self.sign(encoded)
end
If iv
contains '
, the encoded string ends there and everything after '
is ignored. I think random_iv
is OpenSSL::Random.random_bytes(16)
, didn't check source yet. When I get random_iv
like:
"0\xC8x'6\x86\x06\xFEG[\xCE\xF5\xF5\xCBL>"
the last 16 characters of the encoded string are nothing like it (end at C8
).
Base64.decode64('1JCQvhD6mrDXkhW4Hn9HIIr32TmYlBmp803oxOtrZMg=\n')[-16,16]
# => "\x8A\xF7\xD99\x98\x94\x19\xA9\xF3M\xE8\xC4\xEBkd\xC8"
If there is no '
in iv
, it works fine. Right now, I'm solving this problem like this:
cipher.iv = Digest::MD5.new.digest(cipher.random_iv)
since MD5
is 16byte
too, and fits the iv
requirement.
Digest::MD5.new.digest('test').bytesize
# => 16
Wondering if there is any better way to do it. And why is there '
in random_iv
in the first place? How should I escape data passed to encode64
?
Also, do I need to append bytes to my data until data.bytesize
is divisible by 16
? Or does Cipher::AES
do it for me?
cipher.update(data)
Upvotes: 1
Views: 186
Reputation: 20408
There's nothing special about '
as the contents of a string. It's just a byte with ASCII value 39.
In the statement encoded = Base64.encode64(encrypted+iv)
, iv
is not the same variable as the cipher.iv
you set two lines prior. Do you have a method or accessor in scope named iv
? Your base64 string '1JCQvhD6mrDXkhW4Hn9HIIr32TmYlBmp803oxOtrZMg=\n'
(which I presume is the result of your function) does not end with the base64 encoding of your example iv, so I'm pretty confident the +iv
part of the expression is not seeing "0\xC8x'6\x86\x06\xFEG[\xCE\xF5\xF5\xCBL>"
.
The base64 encoding of your example iv successfully roundtrips for me:
irb> iv = "0\xC8x'6\x86\x06\xFEG[\xCE\xF5\xF5\xCBL>".force_encoding('BINARY')
=> "0\xC8x'6\x86\x06\xFEG[\xCE\xF5\xF5\xCBL>"
irb> e = Base64.encode64 iv
=> "MMh4JzaGBv5HW8719ctMPg==\n"
irb> d = Base64.decode64 e
=> "0\xC8x'6\x86\x06\xFEG[\xCE\xF5\xF5\xCBL>"
irb> d == iv
=> true
Upvotes: 3