class Crypt::IDEA

IDEA (International Data Encryption Algorithm) by Xuejia Lai and James Massey (1992). Ported by Richard Kernahan 2005

Constants

DECRYPT
ENCRYPT
USHORT

Attributes

subkeys[RW]

Public Class Methods

new(key128, mode) click to toggle source
# File lib/crypt/idea.rb, line 25
def initialize(key128, mode)
  # IDEA is subject to attack unless the key is sufficiently random, so we
  # take an MD5 digest of a variable-length passphrase to ensure a solid key
  if (key128.class == String)
    digest = Digest::MD5.new().digest(key128.b).b()
    key128 = digest.unpack('n8')
  end
  raise "Key must be 128 bits (8 words)" unless (key128.class == Array) && (key128.length == 8)
  raise "Mode must be IDEA::ENCRYPT or IDEA::DECRYPT" unless ((mode == ENCRYPT) | (mode == DECRYPT))
  if (mode == ENCRYPT)
    @subkeys = generate_encryption_subkeys(key128)
  else
    @subkeys = generate_decryption_subkeys(key128)
  end
end

Public Instance Methods

block_size() click to toggle source
# File lib/crypt/idea.rb, line 21
def block_size
  return(8)
end
crypt_pair(l, r) click to toggle source
# File lib/crypt/idea.rb, line 106
def crypt_pair(l, r)
  word = [l, r].pack('NN').unpack('nnnn')
  k = @subkeys[0..51]
  8.downto(1) { |i|
    word[0] = mul(word[0], k.shift)
    word[1] = (word[1] + k.shift) % USHORT
    word[2] = (word[2] + k.shift) % USHORT
    word[3] = mul(word[3], k.shift)
    t2 = word[0] ^ word[2]
    t2 = mul(t2, k.shift)
    t1 = (t2 + (word[1] ^ word[3])) % USHORT
    t1 = mul(t1, k.shift)
    t2 = (t1 + t2) % USHORT
    word[0] ^= t1
    word[3] ^= t2
    t2 ^= word[1]
    word[1] = word[2] ^ t1
    word[2] = t2
  }
  result = []
  result << mul(word[0], k.shift)
  result << (word[2] + k.shift) % USHORT
  result << (word[1] + k.shift) % USHORT
  result << mul(word[3], k.shift)
  twoLongs = result.pack('nnnn').unpack('NN')
  return(twoLongs)
end
decrypt_block(block) click to toggle source
# File lib/crypt/idea.rb, line 141
def decrypt_block(block)
  xl, xr = block.unpack('NN')
  xl, xr = crypt_pair(xl, xr)
  decrypted = [xl, xr].pack('NN')
  return(decrypted)
end
encrypt_block(block) click to toggle source
# File lib/crypt/idea.rb, line 134
def encrypt_block(block)
  xl, xr = block.unpack('NN')
  xl, xr = crypt_pair(xl, xr)
  encrypted = [xl, xr].pack('NN')
  return(encrypted)
end
generate_decryption_subkeys(key) click to toggle source
# File lib/crypt/idea.rb, line 83
def generate_decryption_subkeys(key)
  encrypt_keys = generate_encryption_subkeys(key)
  decrypt_keys = []
  decrypt_keys[48] = mulInv(encrypt_keys.shift)
  decrypt_keys[49] = (-encrypt_keys.shift) % USHORT
  decrypt_keys[50] = (-encrypt_keys.shift) % USHORT
  decrypt_keys[51] = mulInv(encrypt_keys.shift)
  42.step(0, -6) { |i|
    decrypt_keys[i+4] = encrypt_keys.shift % USHORT
    decrypt_keys[i+5] = encrypt_keys.shift % USHORT
    decrypt_keys[i]   = mulInv(encrypt_keys.shift)
    if (i == 0)
      decrypt_keys[1] = (-encrypt_keys.shift) % USHORT
      decrypt_keys[2] = (-encrypt_keys.shift) % USHORT
    else
      decrypt_keys[i+2] = (-encrypt_keys.shift) % USHORT
      decrypt_keys[i+1] = (-encrypt_keys.shift) % USHORT
    end
    decrypt_keys[i+3] = mulInv(encrypt_keys.shift)
  }
  return(decrypt_keys)
end
generate_encryption_subkeys(key) click to toggle source
# File lib/crypt/idea.rb, line 72
def generate_encryption_subkeys(key)
  encrypt_keys = []
  encrypt_keys[0..7] = key.dup
  8.upto(51) { |i|
    a = ((i + 1) % 8 > 0) ? (i-7)  : (i-15)
    b = ((i + 2) % 8 < 2) ? (i-14) : (i-6)
    encrypt_keys[i] = ((encrypt_keys[a] << 9) | (encrypt_keys[b] >> 7)) % USHORT
  }
  return(encrypt_keys)
end
mul(a, b) click to toggle source
# File lib/crypt/idea.rb, line 41
def mul(a, b)
  modulus = 0x10001
  return((1 - b) % USHORT) if (a == 0)
  return((1 - a) % USHORT) if (b == 0)
  return((a * b) % modulus % USHORT)   # fixed with % USHORT
end
mulInv(x) click to toggle source
# File lib/crypt/idea.rb, line 48
def mulInv(x)
  modulus = 0x10001
  x = x.to_i % 0x10000
  return(x) if (x <= 1)
  t1 = modulus / x
  y  = modulus % x
  if (y == 1)
    inv = (1 - t1) & 0xFFFF
    return(inv)
  end
  t0 = 1
  while (y != 1)
    q = x / y
    x = x % y
    t0 = t0 + (q * t1)
    return(t0) if (x == 1)
    q = y / x
    y = y % x
    t1 = t1 + (q * t0)
  end
  inv = (1 - t1) & 0xFFFF
  return(inv)
end