user4252489 user4252489 - 1 year ago 49
Ruby Question

Why length of encrypted numerical value is different?

I encrypted numerical value as following.

> secret = Sestrong textcureRandom::hex(128)
> encryptor =, cipher: 'aes-256-cbc')

> message1 = 1
> message1.size
=> 8
> message1.class
=> Fixnum
> encrypt_message1 = encryptor.encrypt_and_sign(message1)
> encrypt_message1.length
=> 110

> message2 = 10000
> message2.size
=> 8
> message2.class
=> Fixnum
> encrypt_message2 = encryptor.encrypt_and_sign(message2)
> encrypt_message2.length
=> 110

Above result is expected result.
Because, class of number which is less than 4611686018427387903 is Fixnum, and size of Fixnum is 8 byte.
In addition, block size of AES is 128bit(16 byte).
8 byte < 16 byte.
So, both length of encrypted value of 1 and 10000 is same.

But, following case, Length of encrypted value is different.

> message3 = 1000000000000000000000000000
> message3.size
=> 12
> message3.class
=> Bignum
> encrypt_message3 = encryptor.encrypt_and_sign(message3)
> encrypt_message3.size
=> 138

1000000000000000000000000000 is Bignum,but this size is 12 and less than 16(block size of AES).
So, I expected that length of encrypted value is same to that of Fixnum.
But, these are different...

Why are these different?

Answer Source

There are multiple layers to what is happening here, and you cannot explain it solely on the data size + encryption used (ie you have to factor in the transformations that happen also)

Look at:

and after that look at: which is used in the encryptor.

There are a few stages:

  1. serializing the data you pass in (this is done using Marshal.dump if you don't specify any serializer)
  2. base64 encoding the data.
  3. generating a digest (ie signature) for the data.
  4. encrypting the data+digest and storign the result + iv from the cipher used in encrypted form.

If you want to understand the generated encrypted data you basically need to trace through the code above, but:

 ::Base64.strict_encode64(Marshal.dump(1)).size is 8
 ::Base64.strict_encode64(Marshal.dump(10000)).size is 8
 ::Base64.strict_encode64(Marshal.dump(1000000000000000000000000000)).size is 24


  Marshal.dump(1).size is 4
  Marshal.dump(10000).size is 6
  Marshal.dump(1000000000000000000000000000).size is 17

Here is how Marshal.dump works internally:

Here is how base64 encoding works: Look at the rules for padding.