AES 块大小为 128 位 = 16 字节,即 16 个字符。这意味着 16 个字节输入和 16 个字节输出。
您正在通过调用来使用流模式OpenSSL::Cipher#update
。这意味着该update
方法的输入将附加到密码的输入,直到达到至少 16 个字节。只有这样,才能执行加密,然后该方法才会返回实际值。
这意味着,update
如果您使用 8 Bytes 值提供调用,则只会每秒钟产生一次输出,这就是您所做的:
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"
就那么简单。