Skip to content

Instantly share code, notes, and snippets.

@vcsjones
Last active June 24, 2018 14:56
Show Gist options
  • Save vcsjones/f9d52327c31a822cdc2f73423cace383 to your computer and use it in GitHub Desktop.
Save vcsjones/f9d52327c31a822cdc2f73423cace383 to your computer and use it in GitHub Desktop.
require 'openssl'
encrypt_me = "what a fine day for coding" # Data to encrypt
@aes_key = (1..16).to_a.pack("C*") # Dummy bad key
@aes_iv = (17..32).to_a.pack("C*") # Dummy bad initialization vector
cipher = OpenSSL::Cipher::AES.new(128, :CBC)
cipher.encrypt # Put it in "encrypt" mode, doesn't actually encrypt
cipher.key = @aes_key
cipher.iv = @aes_iv
ciphertext = cipher.update(encrypt_me) + cipher.final
def decrypt(data)
cipher = OpenSSL::Cipher::AES.new(128, :CBC)
cipher.padding = 0
cipher.decrypt # Put it in "decrypt" mode, doesn't actually decrypt
cipher.key = @aes_key
cipher.iv = @aes_iv
plaintext = cipher.update(data)
last_octet = plaintext[-1].ord
padding = plaintext[-last_octet..-1]
is_padding_valid = padding.bytes.all? { |b| b == last_octet }
raise "BAD PADDING" unless is_padding_valid
return "Data processed"
end
ciphertext.freeze
decrypt_data = ciphertext.dup
recovered = {}
(1..16).each do |i|
position = 16-i
(0..255).each do |guess|
decrypt_data[position] = guess.chr
begin
decrypt(decrypt_data)
rescue
next
end
recovered[position] = ciphertext[position].ord ^ guess ^ i
(1..i).each do |j|
z = 16 - j
decrypt_data[z] = (ciphertext[z].ord ^ recovered[z] ^ (i+1)).chr
end
break
end
end
pp recovered.sort.map { |k, v| v }.pack("c*")
require 'openssl'
class PaddingError < StandardError
end
@aes_key = OpenSSL::Random.random_bytes(16)
def encrypt_data(plaintext)
new_iv = OpenSSL::Random.random_bytes(16)
cipher = OpenSSL::Cipher::AES.new(128, :CBC)
cipher.encrypt
cipher.key = @aes_key
cipher.iv = new_iv
ciphertext = cipher.update(plaintext) + cipher.final
[ciphertext.freeze, new_iv.freeze]
end
def process_data(iv, data)
cipher = OpenSSL::Cipher::AES.new(128, :CBC)
cipher.padding = 0
cipher.decrypt
cipher.key = @aes_key
cipher.iv = iv
plaintext = cipher.update(data)
last_octet = plaintext[-1].ord
raise PaddingError if plaintext.length - last_octet < 0
padding = plaintext[-last_octet..-1]
is_padding_valid = padding.bytes.inject(0) { |a, b|
a | (b ^ last_octet)
}.zero?
raise PaddingError unless is_padding_valid
# Process data
return true
end
ciphertext, iv = encrypt_data('what a fine day for coding')
decrypt_data = ciphertext.dup
recovered = {}
(1..16).each do |i|
position = 16-i
found = false
(0..255).each do |guess|
next if guess == ciphertext[position].ord && i == 1
decrypt_data[position] = guess.chr
begin
process_data(iv, decrypt_data)
rescue PaddingError
next
end
recovered[position] = ciphertext[position].ord ^ guess ^ i
(1..i).each do |j|
z = 16 - j
decrypt_data[z] = (ciphertext[z].ord ^ recovered[z] ^ (i+1)).chr
end
found = true
break
end
raise "Could not match padding." unless found
end
pp recovered.sort.map { |k, v| v }.pack("c*")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment