Skip to content

Instantly share code, notes, and snippets.

@drewblas
Last active August 29, 2015 14:05
Show Gist options
  • Save drewblas/00984c76d39fad59871f to your computer and use it in GitHub Desktop.
Save drewblas/00984c76d39fad59871f to your computer and use it in GitHub Desktop.
Encryption Mistake Example
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}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment