module Net::SSH::Transport::CTR

Pure-Ruby implementation of Stateful Decryption Counter(SDCTR) Mode for Block Ciphers. See RFC4344 for detail.

Public Class Methods

extended(orig) click to toggle source
# File lib/net/ssh/transport/ctr.rb, line 33
def self.extended(orig)
  orig.instance_eval {
    @remaining = ""
    @counter = nil
    @counter_len = orig.block_size
    orig.encrypt
    orig.padding = 0

    singleton_class.send(:alias_method, :_update, :update)
    singleton_class.send(:private, :_update)
    singleton_class.send(:undef_method, :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 = ""

      offset = 0
      while (@remaining.bytesize - offset) >= block_size
        encrypted += xor!(@remaining.slice(offset, block_size),
                          _update(@counter))
        increment_counter!
        offset += block_size
      end
      @remaining = @remaining.slice(offset..-1)

      encrypted
    end

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

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

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

Public Instance Methods

decrypt() click to toggle source
# File lib/net/ssh/transport/ctr.rb, line 61
def decrypt
  # DO NOTHING (always set to "encrypt")
end
encrypt() click to toggle source
# File lib/net/ssh/transport/ctr.rb, line 57
def encrypt
  # DO NOTHING (always set to "encrypt")
end
final() click to toggle source
# File lib/net/ssh/transport/ctr.rb, line 90
def final
  s = @remaining.empty? ? '' : xor!(@remaining, _update(@counter))
  @remaining = ""
  s
end
increment_counter!() click to toggle source
# File lib/net/ssh/transport/ctr.rb, line 103
def increment_counter!
  c = @counter_len
  while ((c -= 1) > 0)
    if @counter.setbyte(c, (@counter.getbyte(c) + 1) & 0xff) != 0
      break
    end
  end
end
iv() click to toggle source
# File lib/net/ssh/transport/ctr.rb, line 45
def iv
  @counter
end
iv=(iv_s) click to toggle source
# File lib/net/ssh/transport/ctr.rb, line 53
def iv=(iv_s)
  @counter = iv_s if @counter.nil?
end
iv_len() click to toggle source
# File lib/net/ssh/transport/ctr.rb, line 49
def iv_len
  block_size
end
padding=(pad) click to toggle source
# File lib/net/ssh/transport/ctr.rb, line 65
def padding=(pad)
  # DO NOTHING (always 0)
end
reset() click to toggle source
# File lib/net/ssh/transport/ctr.rb, line 69
def reset
  @remaining = ""
end
update(data) click to toggle source
# File lib/net/ssh/transport/ctr.rb, line 73
def update(data)
  @remaining += data

  encrypted = ""

  offset = 0
  while (@remaining.bytesize - offset) >= block_size
    encrypted += xor!(@remaining.slice(offset, block_size),
                      _update(@counter))
    increment_counter!
    offset += block_size
  end
  @remaining = @remaining.slice(offset..-1)

  encrypted
end
xor!(s1, s2) click to toggle source
# File lib/net/ssh/transport/ctr.rb, line 96
def xor!(s1, s2)
  s = []
  s1.unpack('Q*').zip(s2.unpack('Q*')) {|a,b| s.push(a ^ b) }
  s.pack('Q*')
end