2013-02-11 23 views
1

我正在尝试AES加密一些数据,并且我使用random_iv来生成初始化向量。未转义报价(')打破Ruby中的Base64

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) 

因为MD516byte过,并符合iv要求。

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

想知道是否有更好的方法来做到这一点。为什么'random_iv第一?我应该如何转移传递给encode64的数据?

此外,我是否需要追加字节到我的数据,直到data.bytesize可以被16整除?或者Cipher::AES为我做?

cipher.update(data) 

回答

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 
+0

同样在这里。我尝试了各种不同的引号和二进制数据组合,并且无法让它突破。如果Base64会像这样被破坏,这似乎很奇怪。其他人很久以前就会注意到它。 – Casper 2013-02-11 08:00:43

+0

嗨。原来的代码iv中的yes与定义中的编码相同,所以我的不好之处......在这里发布时弄乱了东西。 – 2013-02-11 10:29:10

+0

无论如何,我测试了它,没有.force_encoding('BINARY')它的破损。与,它工作正常。 – 2013-02-11 10:29:46