未转义的引号(')在Ruby中打破了Base64

时间:2013-02-11 06:03:30

标签: ruby

我正在尝试AES加密一些数据,并使用random_iv生成初始化向量。

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

如果iv包含',则编码的字符串将在此处结束,并忽略'之后的所有内容。我认为random_ivOpenSSL::Random.random_bytes(16),尚未检查来源。当我得到random_iv时:

"0\xC8x'6\x86\x06\xFEG[\xCE\xF5\xF5\xCBL>"

编码字符串的最后16个字符与它完全不同(以C8结束)。

Base64.decode64('1JCQvhD6mrDXkhW4Hn9HIIr32TmYlBmp803oxOtrZMg=\n')[-16,16]
# => "\x8A\xF7\xD99\x98\x94\x19\xA9\xF3M\xE8\xC4\xEBkd\xC8" 

如果'中没有iv,则可以正常使用。现在,我正在解决这个问题:

cipher.iv = Digest::MD5.new.digest(cipher.random_iv)

因为MD5也是16byte,符合iv要求。

Digest::MD5.new.digest('test').bytesize
# => 16 

想知道是否有更好的方法。为什么'首先出现random_iv?我应该如何转义传递给encode64的数据?

另外,在data.bytesize16整除之前,是否需要将字节附加到我的数据中?或者Cipher::AES为我做了吗?

cipher.update(data)

1 个答案:

答案 0 :(得分:3)

'作为字符串的内容没有什么特别之处。它只是一个ASCII值为39的字节。

encoded = Base64.encode64(encrypted+iv)语句中,iv与您之前设置两行的cipher.iv不是同一个变量。您在名为iv的范围内有方法或访问者吗?你的base64字符串'1JCQvhD6mrDXkhW4Hn9HIIr32TmYlBmp803oxOtrZMg=\n'(我认为是你的函数的结果)并不以你的例子iv的base64编码结束,所以我非常有信心表达式的+iv部分没有看到"0\xC8x'6\x86\x06\xFEG[\xCE\xF5\xF5\xCBL>"

示例iv的base64编码成功完成了我的往返:

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