2013-02-11 18 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