密码的源字符串是否有最小长度?我正在尝试创建唯一的会话ID,并且正在执行以下操作:
cipherer = OpenSSL::Cipher::Cipher.new("aes-256-cbc").encrypt
cipherer.update(Time.now.to_f.*(1000).to_i.to_s(36))
但它返回一个空字符串。我将乘法因子1000
更改为较大的100000000000000
,然后它有时会返回一个空字符串,有时会返回一个长字符串。我想这是因为短于某个长度的字符串被密码映射到空字符串。这种理解是否正确?如果是这样,最小长度是多少,我怎样才能使它永远不会返回空字符串?我不需要解密它,所以不用担心舍入错误或硬件依赖性是否会使其无法破译。
答案 0 :(得分:2)
AES块大小为128位= 16字节,即16个字符。这意味着16字节进入,16字节出去。
您正在使用流媒体模式拨打OpenSSL::Cipher#update
。这意味着update
方法的输入将附加到密码的输入,直到达到最小16个字节。只有这样,才能执行加密,然后方法才会返回实际值。
这意味着,如果您使用8字节值为其提供update
,则每次只会产生一次输出:
cipherer = OpenSSL::Cipher::Cipher.new("aes-256-cbc").encrypt
#=> #<OpenSSL::Cipher::Cipher:0x007fb67426e558>
cipherer.update('X'*8)
#=> ""
cipherer.update('X'*8)
#=> "\xA0+\xD8Y\xA5\xBC68\x972\x86!\xC7\xE5\xA2\xDE"
cipherer.update('X'*8)
#=> ""
cipherer.update('X'*8)
#=> "\xFB\xB1I\xE2\x01\xB8Z\x10\xDC\x96m?\xC3\x00\x19+"
另一方面,如果您提供32字节值,则会立即加密两个块,例如
cipherer = OpenSSL::Cipher::Cipher.new("aes-256-cbc").encrypt
=> #<OpenSSL::Cipher::Cipher:0x007fb6741579f8>
cipherer.update('X'*32)
#=> "\xA0+\xD8Y\xA5\xBC68\x972\x86!\xC7\xE5\xA2\xDE\xFB\xB1I\xE2\x01\xB8Z\x10\xDC\x96m?\xC3\x00\x19+"
cipherer.update('X'*32)
#=> "\xB2!\xBA>M\x13t\xEBv^\xCE\xAE\x18\x9A\xE3S\xD96\x95\x89\xC1\xB4\xAA\xDD\xD3\xDCp\e<\x90\xA79"
cipherer.update('X'*32)
#=> "\x95\xA3-\xB9\x93D\x1D\xC0\xB3mh\xE3\xB5N\x9C\x8C\xEA\xF3\x80\xD3\xBDU\xCB'\xC0E\xDA\x02\xA8L\a\xB3"
您问题的直接解决方案是使用字符串作为输入,保证长度为16个字节。
我强烈建议您使用ruby附带的UUID实现。在实现加密内容时需要考虑很多事情。你总是更好地坚持标准并使用众所周知,广泛使用和经过实战考验的实施。也就是说,这是如何获得UUID:
require 'securerandom'
SecureRandom.uuid
#=> "c5059a24-25fc-4617-aaf7-280df52cd8d3"
这很简单。