Class: Cipher::DisruptedTransposition

Inherits:
SimpleCipher show all
Includes:
Crypto
Defined in:
lib/cipher.rb

Overview

DisruptedTransposition

This is a complicated transposition scheme where several areas are ignored at initial filling according to the keyword then filled up later in the second phase.

See: www.quadibloc.com/crypto/pp1324.htm

http://users.telenet.be/d.rijmenants/en/handciphers.htm

Constant Summary

Constant Summary

Constants included from Crypto

Crypto::BASE

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Methods included from Crypto

#addmod10, #chainadd, #expand5to10, #find_hole, #keyshuffle, #normalize, #p1_encode, #str_to_numeric, #submod10

Constructor Details

- (DisruptedTransposition) initialize(key)

Returns a new instance of DisruptedTransposition



108
109
110
111
112
# File 'lib/cipher.rb', line 108

def initialize(key)
  @key = Key::TKey.new(key)
  @nkey = @key.to_numeric
  @lkey = @nkey.size
end

Instance Attribute Details

- (Object) key (readonly)

Returns the value of attribute key



106
107
108
# File 'lib/cipher.rb', line 106

def key
  @key
end

- (Object) lkey (readonly)

Returns the value of attribute lkey



106
107
108
# File 'lib/cipher.rb', line 106

def lkey
  @lkey
end

- (Object) nkey (readonly)

Returns the value of attribute nkey



106
107
108
# File 'lib/cipher.rb', line 106

def nkey
  @nkey
end

Instance Method Details

- (Object) compute_holes(len)

compute_holes

Compute the list of cells to be ignored in first filling phase



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/cipher.rb', line 172

def compute_holes(len)
  #
  # We have potentially as many holes as we have key letters
  # but we have a much more simple stop condition, that is, the last
  # hole is incomplete
  #
  # Return the list of unavailable [x,y] (i.e. all areas merged)
  #
  holes = Array.new
  start_row = 0
  start_x = 0
  loop do
    pos = @nkey.index(start_x)
    hole = HoleArea.new(start_row, pos, @lkey - pos, len)
    holes << hole.a
    break unless hole.complete?
    start_x += 1
    start_row = start_row + hole.ylen
  end
  holes.flatten(1)
end

- (Object) decode

decode



162
163
164
165
166
# File 'lib/cipher.rb', line 162

def decode
  @msglen = plain_text.length
  holes = compute_holes(@msglen)

end

- (Object) encode(plain_text)

encode



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/cipher.rb', line 116

def encode(plain_text)
  @msglen = plain_text.length
  holes = compute_holes(@msglen)

  j = 0
  t_len = @key.length
  table = Array.new(t_len) { '' }
  cipher_text = ''

  # 1st phase: fill in everything else than a hole
  #
  plain = plain_text.each_char.to_a
  for i in 0..(@msglen - 1) do
    pt = plain.shift
    #print "pt: #{pt} #{[i / t_len,j]} @nkey[#{j}]: #{@nkey[j]} "
    if holes.include?([i / t_len,j])
      table[@nkey[j]] << '.'
      plain.unshift(pt)
    else
      table[@nkey[j]] << pt
    end
    #puts " table[#{@nkey[j]}]: #{table[@nkey[j]]}"
    j = (j + 1) % t_len
  end

  # 2nd phase: fill in all holes
  #
  holes.each do |e|
    row = e[0]
    col = @nkey[e[1]]

    p = plain.shift
    curcol = table[col]
    curcol[row] = p
    #puts("holes: #{row},#{col} -> #{p} curcol: #{curcol}")
  end

  # Now take every column based upon key ordering
  #
  cipher_text = @nkey.sort.each.inject('') do |text, t|
    text +  table[t]
  end
end