Class: Crypt::IDEA

Inherits:
Object
  • Object
show all
Includes:
CBC
Defined in:
lib/crypt/idea.rb

Constant Summary collapse

ULONG =
0x100000000
USHORT =
0x10000
ENCRYPT =
0
DECRYPT =
1

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(key128, mode) ⇒ IDEA

Returns a new instance of IDEA.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 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.digest(key128)
    key128 = digest.unpack('n'*8)
  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 (mode == DECRYPT)
    @subkeys = generate_decryption_subkeys(key128)
  end
end

Instance Method Details

#block_sizeObject



20
21
22
# File 'lib/crypt/idea.rb', line 20

def block_size
  return(8)
end

#crypt_pair(l, r) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/crypt/idea.rb', line 111

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)
  two_longs = result.pack('nnnn').unpack('NN')
  return(two_longs)
end

#decrypt_block(block) ⇒ Object



147
148
149
150
151
152
# File 'lib/crypt/idea.rb', line 147

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) ⇒ Object



139
140
141
142
143
144
# File 'lib/crypt/idea.rb', line 139

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) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/crypt/idea.rb', line 87

def generate_decryption_subkeys(key)
  encrypt_keys = generate_encryption_subkeys(key)
  decrypt_keys = []
  decrypt_keys[48] = mul_inv(encrypt_keys.shift)
  decrypt_keys[49] = (-encrypt_keys.shift) % USHORT
  decrypt_keys[50] = (-encrypt_keys.shift) % USHORT
  decrypt_keys[51] = mul_inv(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]   = mul_inv(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] = mul_inv(encrypt_keys.shift)
  }
  return(decrypt_keys)
end

#generate_encryption_subkeys(key) ⇒ Object



75
76
77
78
79
80
81
82
83
84
# File 'lib/crypt/idea.rb', line 75

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) ⇒ Object



42
43
44
45
46
47
# File 'lib/crypt/idea.rb', line 42

def mul(a, b)
  modulus = 0x10001
  return((1 - b) % USHORT) if (a == 0)
  return((1 - a) % USHORT) if (b == 0)
  return((a * b) % modulus)
end

#mul_inv(x) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/crypt/idea.rb', line 50

def mul_inv(x)
  modulus = 0x10001
  x = x.to_i % USHORT
  return(x) if (x <= 1)
  t1 = USHORT / 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