crypt 1.1.4 → 2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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