module Net::SSH::Transport::CTR

def self.extended(orig)

def self.extended(orig)
  orig.instance_eval {
    @remaining = ""
    @counter = nil
    @counter_len = orig.block_size
    orig.encrypt
    orig.padding = 0
  }
  class <<orig
    alias :_update :update
    private :_update
    undef :update
    def iv
      @counter
    end
    def iv_len
      block_size
    end
    def iv=(iv_s)
      @counter = iv_s if @counter.nil?
    end
    def encrypt
      # DO NOTHING (always set to "encrypt")
    end
    def decrypt
      # DO NOTHING (always set to "encrypt")
    end
    def padding=(pad)
      # DO NOTHING (always 0)
    end
    def reset
      @remaining = ""
    end
    def update(data)
      @remaining += data
      encrypted = ""
      while @remaining.bytesize >= block_size
        encrypted += xor!(@remaining.slice!(0, block_size),
                          _update(@counter))
        increment_counter!
      end
      encrypted
    end
    def final
      unless @remaining.empty?
        s = xor!(@remaining, _update(@counter))
      else
        s = ""
      end
      @remaining = ""
      s
    end
    private
    def xor!(s1, s2)
      s = []
      s1.unpack('Q*').zip(s2.unpack('Q*')) {|a,b| s.push(a^b) }
      s.pack('Q*')
    end
    def increment_counter!
      c = @counter_len
      while ((c -= 1) > 0)
        if @counter.setbyte(c, (@counter.getbyte(c) + 1) & 0xff) != 0
          break
        end
      end
    end
  end
end

def decrypt

def decrypt
  # DO NOTHING (always set to "encrypt")
end

def encrypt

def encrypt
  # DO NOTHING (always set to "encrypt")
end

def final

def final
  unless @remaining.empty?
    s = xor!(@remaining, _update(@counter))
  else
    s = ""
  end
  @remaining = ""
  s
end

def increment_counter!

def increment_counter!
  c = @counter_len
  while ((c -= 1) > 0)
    if @counter.setbyte(c, (@counter.getbyte(c) + 1) & 0xff) != 0
      break
    end
  end
end

def iv

def iv
  @counter
end

def iv=(iv_s)

def iv=(iv_s)
  @counter = iv_s if @counter.nil?
end

def iv_len

def iv_len
  block_size
end

def padding=(pad)

def padding=(pad)
  # DO NOTHING (always 0)
end

def reset

def reset
  @remaining = ""
end

def update(data)

def update(data)
  @remaining += data
  encrypted = ""
  while @remaining.bytesize >= block_size
    encrypted += xor!(@remaining.slice!(0, block_size),
                      _update(@counter))
    increment_counter!
  end
  encrypted
end

def xor!(s1, s2)

def xor!(s1, s2)
  s = []
  s1.unpack('Q*').zip(s2.unpack('Q*')) {|a,b| s.push(a^b) }
  s.pack('Q*')
end