Class: Crypt::Gost

Inherits:
Object show all
Includes:
CBC
Defined in:
lib/flatulent/crypt/gost.rb

Constant Summary collapse

ULONG =
0x100000000

Instance Method Summary collapse

Methods included from CBC

#carefully_open_file, #decrypt_file, #decrypt_stream, #decrypt_string, #encrypt_file, #encrypt_stream, #encrypt_string, #generate_initialization_vector

Constructor Details

#initialize(userKey) ⇒ Gost

Returns a new instance of Gost.



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
# File 'lib/flatulent/crypt/gost.rb', line 19

def initialize(userKey)

  # These are the S-boxes given in Applied Cryptography 2nd Ed., p. 333
  @sBox = [
    [4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3],
    [14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9],
    [5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11],
    [7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3],
    [6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2],
    [4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14],
    [13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12],
    [1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]
  ]

  # These are the S-boxes given in the GOST source code listing in Applied
 # Cryptography 2nd Ed., p. 644.  They appear to be from the DES S-boxes
  # [13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7 ],
  # [ 4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1 ],
  # [12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11 ],
  # [ 2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9 ],
  # [ 7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15 ],
  # [10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8 ],
  # [15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10 ],
  # [14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7 ] 
  
  # precalculate the S table
  @sTable = precalculate_S_table()
  
  # derive the 32-byte key from the user-supplied key
  userKeyLength = userKey.length
  @key = userKey[0..31].unpack('C'*32)
  if (userKeyLength < 32)
    userKeyLength.upto(31) { @key << 0 }
  end
end

Instance Method Details

#block_sizeObject



14
15
16
# File 'lib/flatulent/crypt/gost.rb', line 14

def block_size
  return(8)
end

#decrypt_block(block) ⇒ Object



131
132
133
134
135
136
# File 'lib/flatulent/crypt/gost.rb', line 131

def decrypt_block(block)
  xl, xr = block.unpack('NN')
  xl, xr = decrypt_pair(xl, xr)
  decrypted = [xl, xr].pack('NN')
  return(decrypted)
end

#decrypt_pair(xl, xr) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/flatulent/crypt/gost.rb', line 100

def decrypt_pair(xl, xr)
  xr ^= f(xl+@key[0])
  xl ^= f(xr+@key[1])
  xr ^= f(xl+@key[2])
  xl ^= f(xr+@key[3])
  xr ^= f(xl+@key[4])
  xl ^= f(xr+@key[5])
  xr ^= f(xl+@key[6])
  xl ^= f(xr+@key[7])
  3.times {
    xr ^= f(xl+@key[7])
    xl ^= f(xr+@key[6])
    xr ^= f(xl+@key[5])
    xl ^= f(xr+@key[4])
    xr ^= f(xl+@key[3])
    xl ^= f(xr+@key[2])
    xr ^= f(xl+@key[1])
    xl ^= f(xr+@key[0])
  }
  return([xr, xl])
end

#encrypt_block(block) ⇒ Object



123
124
125
126
127
128
# File 'lib/flatulent/crypt/gost.rb', line 123

def encrypt_block(block)
  xl, xr = block.unpack('NN')
  xl, xr = encrypt_pair(xl, xr)
  encrypted = [xl, xr].pack('NN')
  return(encrypted)
end

#encrypt_pair(xl, xr) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/flatulent/crypt/gost.rb', line 77

def encrypt_pair(xl, xr)
  3.times {
    xr ^= f(xl+@key[0])
    xl ^= f(xr+@key[1])
    xr ^= f(xl+@key[2])
    xl ^= f(xr+@key[3])
    xr ^= f(xl+@key[4])
    xl ^= f(xr+@key[5])
    xr ^= f(xl+@key[6])
    xl ^= f(xr+@key[7])
  }
  xr ^= f(xl+@key[7])
  xl ^= f(xr+@key[6])
  xr ^= f(xl+@key[5])
  xl ^= f(xr+@key[4])
  xr ^= f(xl+@key[3])
  xl ^= f(xr+@key[2])
  xr ^= f(xl+@key[1])
  xl ^= f(xr+@key[0])
  return([xr, xl])
end

#f(longWord) ⇒ Object



70
71
72
73
74
# File 'lib/flatulent/crypt/gost.rb', line 70

def f(longWord)
  longWord = longWord % ULONG
  a, b, c, d = [longWord].pack('L').unpack('CCCC')
  return(@sTable[3][d] ^ @sTable[2][c] ^ @sTable[1][b] ^ @sTable[0][a])
end

#precalculate_S_tableObject



56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/flatulent/crypt/gost.rb', line 56

def precalculate_S_table()
  sTable = [[], [], [], []]
  0.upto(3) { |i|
    0.upto(255) { |j|
      t = @sBox[2*i][j % 16] | (@sBox[2*i+1][j/16] << 4)
      u = (8*i + 11) % 32
      v = (t << u) | (t >> (32-u))
      sTable[i][j] = (v % ULONG)
    } 
  }
  return(sTable)
end