scepticulous/crypto-toolbox

View on GitHub
lib/crypto-toolbox/crypt_buffer/concerns/xor.rb

Summary

Maintainability
A
35 mins
Test Coverage
module CryptBufferConcern
  module Xor


    def ^(other)
      xor(other)
    end
    
    def xor_at(input,pos)
      return self if input.nil? || (pos.abs > length)

      case input.respond_to?(:to_ary)
      when true
        # map our current data to xor all inputs with the given bytepos.
        # all other bytes are kept as they were
        abs_pos = normalize_pos(pos)
        tmp = bytes.map.with_index{|b,i| i == abs_pos ? xor_multiple(b,input.to_ary) : b }
        CryptBuffer(tmp)
      else
        tmp = bytes
        tmp[pos] = tmp[pos] ^ input
        CryptBuffer(tmp)
      end 
    end
    
    def xor(input,expand_input: false)
      if expand_input
        xor_all_with(input)
      else
        xor_bytes(CryptBuffer(input).bytes)
      end
    end

    def xor_all_with(input)
      expanded = expand_bytes(CryptBuffer(input).bytes,self.bytes.length)
      xor_bytes(expanded)
    end

    def xor_space
      xor(0x20,expand_input: true)
    end
    private
    
    def xor_bytes(byt)
      len = [self.bytes.size,byt.size].min
      result = self.bytes[0...len].map.with_index{|b,i| b ^ byt[i] } + self.bytes[len,self.bytes.length - len]
      self.class.new(result)
    end

    def xor_hex(hex)
      x = hex2bytes(hex)
      xor_bytes(x)
    end

    private
    def xor_multiple(byte,bytes)

      ([byte] + bytes).reduce(:^)
    end
    def normalize_pos(pos)
      (pos < 0) ? (length() + pos ) : pos
    end

    
  end
  
end