Land #22, Implement XOR with variable-length key
This commit is contained in:
commit
a5d2e9b021
|
@ -1,28 +1,38 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Rex
|
||||
module Text
|
||||
|
||||
# Returns a XOR'd string.
|
||||
module Rex::Text
|
||||
# XOR a string against a variable-length key
|
||||
#
|
||||
# @param key [String] XOR key.
|
||||
# @param value [String] The string to XOR.
|
||||
# @return [String] An XOR'd string.
|
||||
# @param key [String] XOR key
|
||||
# @param value [String] String to XOR
|
||||
# @return [String] XOR'd string
|
||||
def self.xor(key, value)
|
||||
xor_key = key.kind_of?(Integer) || key.nil? ? key.to_i : key.to_i(16)
|
||||
unless xor_key.between?(0, 255)
|
||||
raise ArgumentError, 'XOR key should be between 0x00 to 0x0f'
|
||||
unless key && value
|
||||
raise ArgumentError, 'XOR key and value must be supplied'
|
||||
end
|
||||
|
||||
buf = ''
|
||||
|
||||
value.each_byte do |byte|
|
||||
xor_byte = byte ^ xor_key
|
||||
buf << [xor_byte].pack('c')
|
||||
xor_key =
|
||||
case key
|
||||
when String
|
||||
if key.empty?
|
||||
raise ArgumentError, 'XOR key must not be empty'
|
||||
end
|
||||
|
||||
buf
|
||||
key
|
||||
when Integer
|
||||
unless key.between?(0x00, 0xff)
|
||||
raise ArgumentError, 'XOR key must be between 0x00 and 0xff'
|
||||
end
|
||||
|
||||
# Convert integer to string
|
||||
[key].pack('C')
|
||||
end
|
||||
|
||||
# Get byte arrays for key and value
|
||||
xor_key = xor_key.bytes
|
||||
xor_value = value.bytes
|
||||
|
||||
# XOR value against cycled key
|
||||
xor_value.zip(xor_key.cycle).map { |v, k| v ^ k }.pack('C*')
|
||||
end
|
||||
end
|
|
@ -18,9 +18,24 @@ describe Rex::Text do
|
|||
expect(Rex::Text.xor(xor_key, hello_world_str)).to eq(xor_hello_world_str)
|
||||
end
|
||||
|
||||
it 'XORs with a string type key' do
|
||||
xor_key = "0x0f"
|
||||
expect(Rex::Text.xor(xor_key, hello_world_str)).to eq(xor_hello_world_str)
|
||||
it 'XORs with a variable-length key' do
|
||||
xor_key = "\x00\x00\x00\x00\x00\x0c"
|
||||
expect(Rex::Text.xor(xor_key, hello_world_str)).to eq('hello,world')
|
||||
end
|
||||
|
||||
it 'XORs with itself' do
|
||||
xor_key = hello_world_str
|
||||
expect(Rex::Text.xor(xor_key, hello_world_str)).to eq("\x00" * hello_world_str.length)
|
||||
end
|
||||
|
||||
it 'raises an ArgumentError due to a nil key' do
|
||||
bad_key = nil
|
||||
expect { Rex::Text.xor(bad_key, hello_world_str) }.to raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it 'raises an ArgumentError due to an empty key' do
|
||||
bad_key = ''
|
||||
expect { Rex::Text.xor(bad_key, hello_world_str) }.to raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it 'raises an ArgumentError due to an out of range key' do
|
||||
|
|
Loading…
Reference in New Issue