class Crypt::Gost

gost.rb

Adapted by Richard Kernahan from C++ code written by Wei Dai of the Crypto++ project www.eskimo.com/~weidai/cryptlib.html

Constants

ULONG

Public Class Methods

new(userKey) click to toggle source
# File lib/crypt/gost.rb, line 18
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

Public Instance Methods

block_size() click to toggle source
# File lib/crypt/gost.rb, line 13
def block_size
  return(8)
end
decrypt_block(block) click to toggle source
# File lib/crypt/gost.rb, line 130
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) click to toggle source
# File lib/crypt/gost.rb, line 99
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) click to toggle source
# File lib/crypt/gost.rb, line 122
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) click to toggle source
# File lib/crypt/gost.rb, line 76
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) click to toggle source
# File lib/crypt/gost.rb, line 69
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_table() click to toggle source
# File lib/crypt/gost.rb, line 55
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