crypt 1.1.4 → 2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,48 +11,48 @@ class Rijndael
11
11
 
12
12
  require 'crypt/cbc'
13
13
  include Crypt::CBC
14
-
14
+
15
15
  require 'crypt/rijndael-tables'
16
16
  include Crypt::RijndaelTables
17
-
18
-
17
+
18
+
19
19
  def initialize(userKey, keyBits = 256, blockBits = 128)
20
20
  case keyBits
21
- when 128
21
+ when 128
22
22
  @keyWords = 4
23
- when 192
23
+ when 192
24
24
  @keyWords = 6
25
25
  when 256
26
26
  @keyWords = 8
27
27
  else raise "The key must be 128, 192, or 256 bits long."
28
28
  end
29
-
29
+
30
30
  case (keyBits >= blockBits) ? keyBits : blockBits
31
- when 128
31
+ when 128
32
32
  @rounds = 10
33
- when 192
33
+ when 192
34
34
  @rounds = 12
35
35
  when 256
36
36
  @rounds = 14
37
37
  else raise "The key and block sizes must be 128, 192, or 256 bits long."
38
38
  end
39
-
39
+
40
40
  case blockBits
41
- when 128
41
+ when 128
42
42
  @blockSize = 16
43
43
  @blockWords = 4
44
44
  @shiftIndex = 0
45
- when 192
45
+ when 192
46
46
  @blockSize = 24
47
47
  @blockWords = 6
48
48
  @shiftIndex = 1
49
- when 256
49
+ when 256
50
50
  @blockSize = 32
51
51
  @blockWords = 8
52
52
  @shiftIndex = 2
53
53
  else raise "The block size must be 128, 192, or 256 bits long."
54
54
  end
55
-
55
+
56
56
  uk = userKey.unpack('C'*userKey.length)
57
57
  maxUsefulSizeOfUserKey = (keyBits/8)
58
58
  uk = uk[0..maxUsefulSizeOfUserKey-1] # truncate
@@ -68,22 +68,22 @@ class Rijndael
68
68
  @roundKeys = generate_key_schedule(@key, keyBits, blockBits)
69
69
  end
70
70
 
71
-
71
+
72
72
  def block_size
73
73
  return(@blockSize) # needed for CBC
74
74
  end
75
-
76
-
75
+
76
+
77
77
  def mul(a, b)
78
78
  if ((a ==0) | (b == 0))
79
- result = 0
79
+ result = 0
80
80
  else
81
81
  result = AlogTable[(LogTable[a] + LogTable[b]) % 255]
82
82
  end
83
83
  return(result)
84
84
  end
85
-
86
-
85
+
86
+
87
87
  def add_round_key(blockArray, roundKey)
88
88
  0.upto(3) { |i|
89
89
  0.upto(@blockWords) { |j|
@@ -92,8 +92,8 @@ class Rijndael
92
92
  }
93
93
  return(blockArray)
94
94
  end
95
-
96
-
95
+
96
+
97
97
  def shift_rows(blockArray, direction)
98
98
  tmp = []
99
99
  1.upto(3) { |i| # row zero remains unchanged
@@ -106,8 +106,8 @@ class Rijndael
106
106
  }
107
107
  return(blockArray)
108
108
  end
109
-
110
-
109
+
110
+
111
111
  def substitution(blockArray, sBox)
112
112
  # replace every byte of the input with the byte at that position in the S-box
113
113
  0.upto(3) { |i|
@@ -117,8 +117,8 @@ class Rijndael
117
117
  }
118
118
  return(blockArray)
119
119
  end
120
-
121
-
120
+
121
+
122
122
  def mix_columns(blockArray)
123
123
  mixed = [[], [], [], []]
124
124
  0.upto(@blockWords-1) { |j|
@@ -131,22 +131,22 @@ class Rijndael
131
131
  }
132
132
  return(mixed)
133
133
  end
134
-
135
-
134
+
135
+
136
136
  def inverse_mix_columns(blockArray)
137
137
  unmixed = [[], [], [], []]
138
138
  0.upto(@blockWords-1) { |j|
139
139
  0.upto(3) { |i|
140
140
  unmixed[i][j] = mul(0xe, blockArray[i][j]) ^
141
- mul(0xb, blockArray[(i + 1) % 4][j]) ^
141
+ mul(0xb, blockArray[(i + 1) % 4][j]) ^
142
142
  mul(0xd, blockArray[(i + 2) % 4][j]) ^
143
143
  mul(0x9, blockArray[(i + 3) % 4][j])
144
144
  }
145
145
  }
146
146
  return(unmixed)
147
147
  end
148
-
149
-
148
+
149
+
150
150
  def generate_key_schedule(k, keyBits, blockBits)
151
151
  tk = k[0..3][0..@keyWords-1] # using slice to get a copy instead of a reference
152
152
  keySched = []
@@ -162,7 +162,7 @@ class Rijndael
162
162
  end
163
163
  # while not enough round key material collected, calculate new values
164
164
  rconIndex = 0
165
- while (t < (@rounds+1)*@blockWords)
165
+ while (t < (@rounds+1)*@blockWords)
166
166
  0.upto(3) { |i|
167
167
  tk[i][0] ^= S[tk[(i + 1) % 4][@keyWords - 1]]
168
168
  }
@@ -184,8 +184,8 @@ class Rijndael
184
184
  tk[i][@keyWords/2] ^= S[tk[i][@keyWords/2 - 1]]
185
185
  }
186
186
  (@keyWords/2 + 1).upto(@keyWords - 1) { |j|
187
- 0.upto(3) { |i|
188
- tk[i][j] ^= tk[i][j-1]
187
+ 0.upto(3) { |i|
188
+ tk[i][j] ^= tk[i][j-1]
189
189
  }
190
190
  }
191
191
  end
@@ -200,8 +200,8 @@ class Rijndael
200
200
  end
201
201
  return(keySched)
202
202
  end
203
-
204
-
203
+
204
+
205
205
  def encrypt_byte_array(blockArray)
206
206
  blockArray = add_round_key(blockArray, @roundKeys[0])
207
207
  1.upto(@rounds - 1) { |round|
@@ -216,54 +216,59 @@ class Rijndael
216
216
  blockArray = add_round_key(blockArray, @roundKeys[@rounds])
217
217
  return(blockArray)
218
218
  end
219
-
220
-
219
+
220
+
221
221
  def encrypt_block(block)
222
+ block = block.force_encoding("ASCII-8BIT") if block.is_a?(String) # affordance
222
223
  raise "block must be #{@blockSize} bytes long" if (block.length() != @blockSize)
223
224
  blockArray = [[], [], [], []]
224
225
  0.upto(@blockSize - 1) { |pos|
225
- blockArray[pos % 4][pos / 4] = block[pos]
226
+ b = block[pos]
227
+ b = b.ord unless b.is_a?(Fixnum)
228
+ blockArray[pos % 4][pos / 4] = b
226
229
  }
227
230
  encryptedBlock = encrypt_byte_array(blockArray)
228
- encrypted = ""
231
+ encrypted = "".force_encoding("ASCII-8BIT") # stop ruby 2 using Unicode
229
232
  0.upto(@blockSize - 1) { |pos|
230
233
  encrypted << encryptedBlock[pos % 4][pos / 4]
231
234
  }
232
235
  return(encrypted)
233
236
  end
234
-
235
-
237
+
238
+
236
239
  def decrypt_byte_array(blockArray)
237
240
  # first special round without inverse_mix_columns
238
241
  # add_round_key is an involution - applying it a second time returns the original result
239
- blockArray = add_round_key(blockArray, @roundKeys[@rounds])
242
+ blockArray = add_round_key(blockArray, @roundKeys[@rounds])
240
243
  blockArray = substitution(blockArray,Si) # using inverse S-box
241
244
  blockArray = shift_rows(blockArray,1)
242
245
  (@rounds-1).downto(1) { |round|
243
246
  blockArray = add_round_key(blockArray, @roundKeys[round])
244
247
  blockArray = inverse_mix_columns(blockArray)
245
- blockArray = substitution(blockArray, Si)
248
+ blockArray = substitution(blockArray, Si)
246
249
  blockArray = shift_rows(blockArray, 1)
247
250
  }
248
251
  blockArray = add_round_key(blockArray, @roundKeys[0])
249
252
  return(blockArray)
250
253
  end
251
-
252
-
254
+
255
+
253
256
  def decrypt_block(block)
254
257
  raise "block must be #{@blockSize} bytes long" if (block.length() != @blockSize)
255
258
  blockArray = [[], [], [], []]
256
259
  0.upto(@blockSize - 1) { |pos|
257
- blockArray[pos % 4][pos / 4] = block[pos]
260
+ b = block[pos]
261
+ b = b.ord() unless b.is_a?(Fixnum) # make sure we have a byte, not a single-char string
262
+ blockArray[pos % 4][pos / 4] = b
258
263
  }
259
264
  decryptedBlock = decrypt_byte_array(blockArray)
260
- decrypted = ""
265
+ decrypted = "".force_encoding("ASCII-8BIT") # stop ruby 2 using Unicode
261
266
  0.upto(@blockSize - 1) { |pos|
262
267
  decrypted << decryptedBlock[pos % 4][pos / 4]
263
268
  }
264
269
  return(decrypted)
265
270
  end
266
-
267
-
271
+
272
+
273
+ end
268
274
  end
269
- end
@@ -2,26 +2,26 @@
2
2
 
3
3
  module Crypt
4
4
  module StringXor
5
-
6
-
5
+
6
+
7
7
  def ^(aString)
8
8
  a = self.unpack('C'*(self.length))
9
9
  b = aString.unpack('C'*(aString.length))
10
10
  if (b.length < a.length)
11
11
  (a.length - b.length).times { b << 0 }
12
12
  end
13
- xor = ""
13
+ xor = "".force_encoding("ASCII-8BIT") # stop ruby 2 using Unicode
14
14
  0.upto(a.length-1) { |pos|
15
15
  x = a[pos] ^ b[pos]
16
16
  xor << x.chr()
17
17
  }
18
18
  return(xor)
19
19
  end
20
-
21
-
20
+
21
+
22
22
  end
23
23
  end
24
24
 
25
25
  class String
26
26
  include Crypt::StringXor
27
- end
27
+ end
@@ -1,4 +1,5 @@
1
- # testblowfish.rb bryllig
1
+ # test-blowfish.rb
2
+ # updated 11-Feb-2014 for ruby 2.0
2
3
 
3
4
  require 'test/unit'
4
5
  require 'crypt/blowfish'
@@ -6,14 +7,14 @@ require 'crypt/cbc'
6
7
  require 'fileutils'
7
8
 
8
9
  class TestBlowfish < Test::Unit::TestCase
9
-
10
+
10
11
  def setup
11
12
  @bf = Crypt::Blowfish.new("Who is John Galt?") # Schneier's test key
12
13
  end
13
-
14
+
14
15
  def teardown
15
16
  end
16
-
17
+
17
18
  def test_block_size
18
19
  assert_equal(8, @bf.block_size(), "Wrong block size")
19
20
  end
@@ -34,8 +35,8 @@ class TestBlowfish < Test::Unit::TestCase
34
35
  end
35
36
 
36
37
  def test_pair
37
- bf = Crypt::Blowfish.new("Who is John Galt?")
38
- orig_l, orig_r = [0xfedcba98, 0x76543210]
38
+ bf = Crypt::Blowfish.new("Who is John Galt?")
39
+ orig_l, orig_r = [0xfedcba98, 0x76543210]
39
40
  l, r = bf.encrypt_pair(orig_l, orig_r)
40
41
  assert_equal(0xcc91732b, l)
41
42
  assert_equal(0x8022f684, r)
@@ -45,19 +46,19 @@ class TestBlowfish < Test::Unit::TestCase
45
46
  end
46
47
 
47
48
  def test_block
48
- bf = Crypt::Blowfish.new("Who is John Galt?")
49
- block = "norandom"
49
+ bf = Crypt::Blowfish.new("Who is John Galt?")
50
+ block = "8 byte\u00cd" # unicode string of 8 bytes
50
51
  encryptedBlock = bf.encrypt_block(block)
51
- assert_equal("\236\353k\321&Q\"\220", encryptedBlock)
52
+ assert_equal("\xC4G\xD3\xFD7\xF4\x1E\xD0".force_encoding('ASCII-8BIT'), encryptedBlock)
52
53
  decryptedBlock = bf.decrypt_block(encryptedBlock)
53
54
  assert_equal(block, decryptedBlock)
54
55
  end
55
-
56
+
56
57
  def test_string
57
58
  length = 30 + rand(26)
58
59
  userkey = ""
59
60
  length.times { userkey << rand(256).chr }
60
- bf = Crypt::Blowfish.new(userkey)
61
+ bf = Crypt::Blowfish.new(userkey)
61
62
  string = "This is a string which is not a multiple of 8 characters long"
62
63
  encryptedString = bf.encrypt_string(string)
63
64
  decryptedString = bf.decrypt_string(encryptedString)
@@ -66,9 +67,9 @@ class TestBlowfish < Test::Unit::TestCase
66
67
  encryptedString = bf.encrypt_string(secondstring)
67
68
  decryptedString = bf.decrypt_string(encryptedString)
68
69
  assert_equal(secondstring, decryptedString)
69
-
70
+
70
71
  end
71
-
72
+
72
73
  def test_file
73
74
  plainText = "This is a multi-line string\nwhich is not a multiple of 8 \ncharacters long."
74
75
  plainFile = File.new('plain.txt', 'wb+')
@@ -1,3 +1,5 @@
1
+ # updated 11-Feb-2014 for ruby 2.0
2
+
1
3
  require 'test/unit'
2
4
  require 'crypt/gost'
3
5
  require 'fileutils'
@@ -9,7 +11,7 @@ class TestGost < Test::Unit::TestCase
9
11
 
10
12
  def teardown
11
13
  end
12
-
14
+
13
15
  def test_init
14
16
  assert_nothing_raised(RuntimeError) {
15
17
  gost = Crypt::Gost.new("Whatever happened to Yuri Gagarin?")
@@ -18,15 +20,15 @@ class TestGost < Test::Unit::TestCase
18
20
  gost = Crypt::Gost.new("Whatever happened to Yuri?")
19
21
  }
20
22
  end
21
-
23
+
22
24
  def test_block_size
23
25
  gost = Crypt::Gost.new("Whatever happened to Yuri?")
24
26
  assert_equal(8, gost.block_size(), "Wrong block size")
25
27
  end
26
28
 
27
29
  def test_pair
28
- gost = Crypt::Gost.new("Whatever happened to Yuri?")
29
- orig_l, orig_r = [0xfedcba98, 0x76543210]
30
+ gost = Crypt::Gost.new("Whatever happened to Yuri?")
31
+ orig_l, orig_r = [0xfedcba98, 0x76543210]
30
32
  l, r = gost.encrypt_pair(orig_l, orig_r)
31
33
  assert_equal(0xaefaf8f4, l)
32
34
  assert_equal(0xe24891b0, r)
@@ -36,31 +38,31 @@ class TestGost < Test::Unit::TestCase
36
38
  end
37
39
 
38
40
  def test_block
39
- gost = Crypt::Gost.new("Whatever happened to Yuri?")
41
+ gost = Crypt::Gost.new("Whatever happened to Yuri?")
40
42
  block = "norandom"
41
43
  encryptedBlock = gost.encrypt_block(block)
42
- assert_equal(".Vy\377\005\e3`", encryptedBlock)
44
+ assert_equal(".Vy\xFF\x05\e3`".force_encoding('ASCII-8BIT'), encryptedBlock)
43
45
  decryptedBlock = gost.decrypt_block(encryptedBlock)
44
46
  assert_equal(block, decryptedBlock)
45
47
  end
46
-
48
+
47
49
  def test_string
48
50
  length = 25 + rand(12)
49
51
  userkey = ""
50
52
  length.times { userkey << rand(256).chr }
51
- gost = Crypt::Gost.new(userkey)
53
+ gost = Crypt::Gost.new(userkey)
52
54
  string = "This is a string which is not a multiple of 8 characters long"
53
55
  encryptedString = gost.encrypt_string(string)
54
56
  decryptedString = gost.decrypt_string(encryptedString)
55
57
  assert_equal(string, decryptedString)
56
58
  end
57
-
59
+
58
60
  def test_file
59
61
  plainText = "This is a multi-line string\nwhich is not a multiple of 8 \ncharacters long."
60
62
  plainFile = File.new('plain.txt', 'wb+')
61
63
  plainFile.puts(plainText)
62
64
  plainFile.close()
63
- gost = Crypt::Gost.new("Whatever happened to Yuri?")
65
+ gost = Crypt::Gost.new("Whatever happened to Yuri?")
64
66
  gost.encrypt_file('plain.txt', 'crypt.txt')
65
67
  gost.decrypt_file('crypt.txt', 'decrypt.txt')
66
68
  decryptFile = File.new('decrypt.txt', 'rb')
@@ -72,4 +74,4 @@ class TestGost < Test::Unit::TestCase
72
74
  FileUtils.rm('decrypt.txt')
73
75
  end
74
76
 
75
- end
77
+ end
@@ -1,3 +1,5 @@
1
+ # updated 11-Feb-2014 for ruby 2.0 - changed expected values representation
2
+
1
3
  require 'test/unit'
2
4
  require 'crypt/idea'
3
5
  require 'fileutils'
@@ -9,60 +11,61 @@ class TestIdea < Test::Unit::TestCase
9
11
 
10
12
  def teardown
11
13
  end
12
-
14
+
13
15
  def test_init
14
16
  assert_nothing_raised(RuntimeError) {
15
- idea_en = Crypt::IDEA.new("Who was John Galt and where's my breakfast?", Crypt::IDEA::ENCRYPT)
17
+ idea_en = Crypt::IDEA.new("Who was John Galt and where's my breakfast?", Crypt::IDEA::ENCRYPT)
16
18
  }
17
19
  end
18
-
20
+
19
21
  def test_block_size
20
- idea_en = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::ENCRYPT)
22
+ idea_en = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::ENCRYPT)
21
23
  assert_equal(8, idea_en.block_size(), "Wrong block size")
22
24
  end
23
25
 
24
26
  def test_pair
25
- idea_en = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::ENCRYPT)
26
- orig_l, orig_r = [0xfedcba98, 0x76543210]
27
+ idea_en = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::ENCRYPT)
28
+ orig_l, orig_r = [0xfedcba98, 0x76543210]
27
29
  l, r = idea_en.crypt_pair(orig_l, orig_r)
28
30
  assert_equal(0x05627e79, l)
29
31
  assert_equal(0x69476521, r)
30
- idea_de = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::DECRYPT)
32
+ idea_de = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::DECRYPT)
31
33
  l, r = idea_de.crypt_pair(l, r)
32
34
  assert_equal(orig_l, l)
33
35
  assert_equal(orig_r, r)
34
36
  end
35
37
 
36
38
  def test_block
37
- idea_en = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::ENCRYPT)
38
- block = "norandom"
39
+ idea_en = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::ENCRYPT)
40
+ block = "8 byte\u00cd" # unicode string of 8 bytes
39
41
  encryptedBlock = idea_en.encrypt_block(block)
40
- assert_equal("\235\003\326u\001\330\361\t", encryptedBlock)
41
- idea_de = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::DECRYPT)
42
+ expected = "\xFA\xB1P\tk\xB0\x1C\xE1".force_encoding("ASCII-8BIT")
43
+ assert_equal(expected, encryptedBlock)
44
+ idea_de = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::DECRYPT)
42
45
  decryptedBlock = idea_de.decrypt_block(encryptedBlock)
43
- assert_equal(block, decryptedBlock)
46
+ assert_equal(block, decryptedBlock.force_encoding("UTF-8"))
44
47
  end
45
-
48
+
46
49
  def test_string
47
50
  length = 25 + rand(12)
48
51
  userkey = ""
49
52
  length.times { userkey << rand(256).chr }
50
- idea_en = Crypt::IDEA.new(userkey, Crypt::IDEA::ENCRYPT)
53
+ idea_en = Crypt::IDEA.new(userkey, Crypt::IDEA::ENCRYPT)
51
54
  string = "This is a string which is not a multiple of 8 characters long"
52
55
  encryptedString = idea_en.encrypt_string(string)
53
- idea_de = Crypt::IDEA.new(userkey, Crypt::IDEA::DECRYPT)
56
+ idea_de = Crypt::IDEA.new(userkey, Crypt::IDEA::DECRYPT)
54
57
  decryptedString = idea_de.decrypt_string(encryptedString)
55
58
  assert_equal(string, decryptedString)
56
59
  end
57
-
60
+
58
61
  def test_file
59
62
  plainText = "This is a multi-line string\nwhich is not a multiple of 8 \ncharacters long."
60
63
  plainFile = File.new('plain.txt', 'wb+')
61
64
  plainFile.puts(plainText)
62
65
  plainFile.close()
63
- idea_en = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::ENCRYPT)
66
+ idea_en = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::ENCRYPT)
64
67
  idea_en.encrypt_file('plain.txt', 'crypt.txt')
65
- idea_de = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::DECRYPT)
68
+ idea_de = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::DECRYPT)
66
69
  idea_de.decrypt_file('crypt.txt', 'decrypt.txt')
67
70
  decryptFile = File.new('decrypt.txt', 'rb')
68
71
  decryptText = decryptFile.readlines().join('').chomp()
@@ -73,4 +76,4 @@ class TestIdea < Test::Unit::TestCase
73
76
  FileUtils.rm('decrypt.txt')
74
77
  end
75
78
 
76
- end
79
+ end