Most plaintext must be fed as a string or a binary object to be encrypted. However, it's often possible to mis-decode the plaintext before encrypting it.
i.e. If it's received as a string in JSON, you often don't know if the string is an encoded representation (e.g. plain, hex encoded, base64 encoded, etc)
Example:
If the message to encrypt is received as 48656c6c6f
(which is Hello
in hexadecimal encoding), it's possible to accidentally encrypt 48656c6c6f
instead of Hello
.
When you decrypt, you'll get back whatever you started with, so it's easy to never know you are encrypting incorrectly.
This results in a plaintext input where the variation per-byte is very small.
If you accidentally encrypt 01001000
as an 8-byte string instead of a single
byte (0x48
, H
), then each resulting ciphertext byte is the result of only
one of two inputs: 0
or 1
.
Question:
Is it insecure to make this mistake?
Is the ciphertext somehow easier to break because you used the wrong plaintext?
What if you make this same mistake with the key instead of the plaintext?
Example Ruby code:
require 'openssl'
=begin
Most plaintext must be fed as a string or a binary object to be encrypted.
However, it's often possible to mis-decode the plaintext before encrypting it.
i.e. If it's received as a string in JSON, you often don't know if the string
is an encoded representation (e.g. plain, hex encoded, base64 encoded, etc)
Example:
If the message to encrypt is received as "48656c6c6f" (which is "Hello" in hex),
it's possible to accidentally encrypt "48656c6c6f" instead of "Hello".
When you decrypt, you'll get back whatever you started with, so it's easy to
never know you are encrypting incorrectly.
This results in a plaintext input where the variation per-byte is very small.
If you accidentally encrypt "01001000" as an 8-byte string instead of a single
byte (0x48, 'H'), then each resulting ciphertext byte is the result of only
one of two inputs: '0' or '1'.
Question:
* Is it INSECURE to make this mistake?
* Is the ciphertext somehow easier to break because you used the wrong plaintext?
* What if you make this same mistake with the KEY instead of the plaintext?
=end
real_plaintext = "Hello" # 5 bytes
plaintext_1 = real_plaintext.unpack('H*').first
puts plaintext_1 # 48 65 6c 6c 6f
plaintext_2 = real_plaintext.unpack('B*').first
puts plaintext_2 # 01001000 01100101 01101100 01101100 01101111
plaintext_3 = [real_plaintext].pack('m')
puts plaintext_3 # SGVsbG8=
# Stream cipher used here to make it more obvious about
# the different resulting lengths
def encrypt(str, method='aes-256-ctr')
cipher = OpenSSL::Cipher::Cipher.new(method)
cipher.encrypt
key = cipher.key = cipher.random_key
iv = cipher.iv = cipher.random_iv
cipher.update(str) + cipher.final
end
puts "Result of real_plaintext:"
result = encrypt(real_plaintext)
puts "Len: #{result.length} - #{result.unpack('H*').first}"
puts "Result of plaintext_1:"
result = encrypt(plaintext_1)
puts "Len: #{result.length} - #{result.unpack('H*').first}"
puts "Result of plaintext_2:"
result = encrypt(plaintext_2)
puts "Len: #{result.length} - #{result.unpack('H*').first}"
puts "Result of plaintext_3:"
result = encrypt(plaintext_3)
puts "Len: #{result.length} - #{result.unpack('H*').first}"