Module: Net::SSH::Transport::CTR

Defined in:
lib/net/ssh/transport/ctr.rb

Overview

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

Class Method Summary collapse

Class Method Details

.extended(orig) ⇒ Object


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/net/ssh/transport/ctr.rb', line 8

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