crypt 1.1.3 → 1.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/crypt/cbc.rb +7 -7
- data/crypt/idea.rb +2 -2
- data/crypt/purerubystringio.rb +378 -0
- data/test/break-idea.rb +61 -0
- data/test/devServer.rb +16 -0
- data/test/test-blowfish.rb +89 -0
- data/test/test-gost.rb +75 -0
- data/test/test-idea.rb +76 -0
- data/test/test-rijndael.rb +67 -0
- metadata +9 -2
data/crypt/cbc.rb
CHANGED
@@ -36,7 +36,7 @@ module CBC
|
|
36
36
|
cryptStream.write(encrypted)
|
37
37
|
chain = encrypted
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
# write the final block
|
41
41
|
# At most block_size()-1 bytes can be part of the message.
|
42
42
|
# That means the final byte can be used to store the number of meaningful
|
@@ -44,13 +44,13 @@ module CBC
|
|
44
44
|
block = '' if block.nil?
|
45
45
|
buffer = block.split('')
|
46
46
|
remainingMessageBytes = buffer.length
|
47
|
+
# we use 7-bit characters to avoid possible strange behavior on the Mac
|
47
48
|
remainingMessageBytes.upto(block_size()-2) { buffer << rand(128).chr }
|
48
49
|
buffer << remainingMessageBytes.chr
|
49
50
|
block = buffer.join('')
|
50
51
|
block = block ^ chain
|
51
52
|
encrypted = encrypt_block(block)
|
52
53
|
cryptStream.write(encrypted)
|
53
|
-
chain = encrypted
|
54
54
|
end
|
55
55
|
|
56
56
|
|
@@ -77,7 +77,7 @@ module CBC
|
|
77
77
|
aFile = File.new(filename, mode)
|
78
78
|
rescue
|
79
79
|
puts "Sorry. There was a problem opening the file <#{filename}>."
|
80
|
-
aFile.close unless aFile.
|
80
|
+
aFile.close() unless aFile.nil?
|
81
81
|
raise
|
82
82
|
end
|
83
83
|
return(aFile)
|
@@ -85,8 +85,8 @@ module CBC
|
|
85
85
|
|
86
86
|
|
87
87
|
def encrypt_file(plainFilename, cryptFilename)
|
88
|
-
plainFile = carefully_open_file(plainFilename, '
|
89
|
-
cryptFile = carefully_open_file(cryptFilename, '
|
88
|
+
plainFile = carefully_open_file(plainFilename, 'rb')
|
89
|
+
cryptFile = carefully_open_file(cryptFilename, 'wb+')
|
90
90
|
encrypt_stream(plainFile, cryptFile)
|
91
91
|
plainFile.close unless plainFile.closed?
|
92
92
|
cryptFile.close unless cryptFile.closed?
|
@@ -94,8 +94,8 @@ module CBC
|
|
94
94
|
|
95
95
|
|
96
96
|
def decrypt_file(cryptFilename, plainFilename)
|
97
|
-
cryptFile = carefully_open_file(cryptFilename, '
|
98
|
-
plainFile = carefully_open_file(plainFilename, '
|
97
|
+
cryptFile = carefully_open_file(cryptFilename, 'rb')
|
98
|
+
plainFile = carefully_open_file(plainFilename, 'wb+')
|
99
99
|
decrypt_stream(cryptFile, plainFile)
|
100
100
|
cryptFile.close unless cryptFile.closed?
|
101
101
|
plainFile.close unless plainFile.closed?
|
data/crypt/idea.rb
CHANGED
@@ -53,7 +53,7 @@ class IDEA
|
|
53
53
|
modulus = 0x10001
|
54
54
|
x = x.to_i % USHORT
|
55
55
|
return(x) if (x <= 1)
|
56
|
-
t1 =
|
56
|
+
t1 = USHORT / x
|
57
57
|
y = modulus % x
|
58
58
|
if (y == 1)
|
59
59
|
inv = (1 - t1) & 0xFFFF
|
@@ -76,7 +76,7 @@ class IDEA
|
|
76
76
|
|
77
77
|
def generate_encryption_subkeys(key)
|
78
78
|
encrypt_keys = []
|
79
|
-
encrypt_keys[0..7] = key
|
79
|
+
encrypt_keys[0..7] = key.dup
|
80
80
|
8.upto(51) { |i|
|
81
81
|
a = ((i + 1) % 8 > 0) ? (i-7) : (i-15)
|
82
82
|
b = ((i + 2) % 8 < 2) ? (i-14) : (i-6)
|
@@ -0,0 +1,378 @@
|
|
1
|
+
# Thanks to Binky DaClown who wrote this pure-ruby implementation
|
2
|
+
# http://rubyforge.org/projects/prstringio/
|
3
|
+
# Apparently CBC does not work well with the C-based stringio
|
4
|
+
|
5
|
+
module Crypt
|
6
|
+
class PureRubyStringIO
|
7
|
+
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
SEEK_CUR = IO::SEEK_CUR
|
11
|
+
SEEK_END = IO::SEEK_END
|
12
|
+
SEEK_SET = IO::SEEK_SET
|
13
|
+
|
14
|
+
@@relayMethods = [:<<, :all?, :any?, :binmode, :close, :close_read, :close_write, :closed?, :closed_read?,
|
15
|
+
:closed_write?, :collect, :detect, :each, :each_byte, :each_line, :each_with_index,
|
16
|
+
:entries, :eof, :eof?, :fcntl, :fileno, :find, :find_all, :flush, :fsync, :getc, :gets,
|
17
|
+
:grep, :include?, :inject, :isatty, :length, :lineno, :lineno=, :map, :max, :member?,
|
18
|
+
:min, :partition, :path, :pid, :pos, :pos=, :print, :printf, :putc, :puts, :read,
|
19
|
+
:readchar, :readline, :readlines, :reject, :rewind, :seek, :select, :size, :sort,
|
20
|
+
:sort_by, :string, :string=, :sync, :sync=, :sysread, :syswrite, :tell, :truncate, :tty?,
|
21
|
+
:ungetc, :write, :zip]
|
22
|
+
|
23
|
+
def self.open(string="", mode="r+")
|
24
|
+
if block_given? then
|
25
|
+
sio = new(string, mode)
|
26
|
+
rc = yield(sio)
|
27
|
+
sio.close
|
28
|
+
rc
|
29
|
+
else
|
30
|
+
new(string, mode)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def <<(obj)
|
35
|
+
requireWritable
|
36
|
+
write obj
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def binmode
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def close
|
45
|
+
requireOpen
|
46
|
+
@sio_closed_read = true
|
47
|
+
@sio_closed_write = true
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def close_read
|
52
|
+
raise IOError, "closing non-duplex IO for reading", caller if closed_read?
|
53
|
+
@sio_closed_read = true
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def close_write
|
58
|
+
raise IOError, "closing non-duplex IO for writing", caller if closed_write?
|
59
|
+
@sio_closed_read = true
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def closed?
|
64
|
+
closed_read? && closed_write?
|
65
|
+
end
|
66
|
+
|
67
|
+
def closed_read?
|
68
|
+
@sio_closed_read
|
69
|
+
end
|
70
|
+
|
71
|
+
def closed_write?
|
72
|
+
@sio_closed_write
|
73
|
+
end
|
74
|
+
|
75
|
+
def each(sep_string=$/, &block)
|
76
|
+
requireReadable
|
77
|
+
@sio_string.each(sep_string, &block)
|
78
|
+
@sio_pos = @sio_string.length
|
79
|
+
end
|
80
|
+
|
81
|
+
def each_byte(&block)
|
82
|
+
requireReadable
|
83
|
+
@sio_string.each_byte(&block)
|
84
|
+
@sio_pos = @sio_string.length
|
85
|
+
end
|
86
|
+
|
87
|
+
def eof
|
88
|
+
requireReadable { @sio_pos >= @sio_string.length }
|
89
|
+
end
|
90
|
+
|
91
|
+
def fcntl(integer_cmd, arg)
|
92
|
+
raise NotImplementedError, "The fcntl() function is unimplemented on this machine", caller
|
93
|
+
end
|
94
|
+
|
95
|
+
def fileno
|
96
|
+
nil
|
97
|
+
end
|
98
|
+
|
99
|
+
def flush
|
100
|
+
self
|
101
|
+
end
|
102
|
+
|
103
|
+
def fsync
|
104
|
+
0
|
105
|
+
end
|
106
|
+
|
107
|
+
def getc
|
108
|
+
requireReadable
|
109
|
+
char = @sio_string[@sio_pos]
|
110
|
+
@sio_pos += 1 unless char.nil?
|
111
|
+
char
|
112
|
+
end
|
113
|
+
|
114
|
+
def gets(sep_string=$/)
|
115
|
+
requireReadable
|
116
|
+
@sio_lineno += 1
|
117
|
+
pstart = @sio_pos
|
118
|
+
@sio_pos = @sio_string.index(sep_string, @sio_pos) || [@sio_string.length, @sio_pos].max
|
119
|
+
@sio_string[pstart..@sio_pos]
|
120
|
+
end
|
121
|
+
|
122
|
+
def initialize(string="", mode="r+")
|
123
|
+
@sio_string = string.to_s
|
124
|
+
@sio_lineno = 0
|
125
|
+
@mode = mode
|
126
|
+
@relay = nil
|
127
|
+
case mode.delete("b")
|
128
|
+
when "r"
|
129
|
+
@sio_closed_read = false
|
130
|
+
@sio_closed_write = true
|
131
|
+
@sio_pos = 0
|
132
|
+
when "r+"
|
133
|
+
@sio_closed_read = false
|
134
|
+
@sio_closed_write = false
|
135
|
+
@sio_pos = 0
|
136
|
+
when "w"
|
137
|
+
@sio_closed_read = true
|
138
|
+
@sio_closed_write = false
|
139
|
+
@sio_pos = 0
|
140
|
+
@sio_string.replace("")
|
141
|
+
when "w+"
|
142
|
+
@sio_closed_read = false
|
143
|
+
@sio_closed_write = false
|
144
|
+
@sio_pos = 0
|
145
|
+
@sio_string.replace("")
|
146
|
+
when "a"
|
147
|
+
@sio_closed_read = true
|
148
|
+
@sio_closed_write = false
|
149
|
+
@sio_pos = @sio_string.length
|
150
|
+
when "a+"
|
151
|
+
@sio_closed_read = false
|
152
|
+
@sio_closed_write = false
|
153
|
+
@sio_pos = @sio_string.length
|
154
|
+
else
|
155
|
+
raise ArgumentError, "illegal access mode #{mode}", caller
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def isatty
|
160
|
+
flase
|
161
|
+
end
|
162
|
+
|
163
|
+
def length
|
164
|
+
@sio_string.length
|
165
|
+
end
|
166
|
+
|
167
|
+
def lineno
|
168
|
+
@sio_lineno
|
169
|
+
end
|
170
|
+
|
171
|
+
def lineno=(integer)
|
172
|
+
@sio_lineno = integer
|
173
|
+
end
|
174
|
+
|
175
|
+
def path
|
176
|
+
nil
|
177
|
+
end
|
178
|
+
|
179
|
+
def pid
|
180
|
+
nil
|
181
|
+
end
|
182
|
+
|
183
|
+
def pos
|
184
|
+
@sio_pos
|
185
|
+
end
|
186
|
+
|
187
|
+
def pos=(integer)
|
188
|
+
raise Errno::EINVAL, "Invalid argument", caller if integer < 0
|
189
|
+
@sio_pos = integer
|
190
|
+
end
|
191
|
+
|
192
|
+
def print(*args)
|
193
|
+
requireWritable
|
194
|
+
args.unshift($_) if args.empty
|
195
|
+
args.each { |obj| write(obj) }
|
196
|
+
write($\) unless $\.nil?
|
197
|
+
nil
|
198
|
+
end
|
199
|
+
|
200
|
+
def printf(format_string, *args)
|
201
|
+
requireWritable
|
202
|
+
write format(format_string, *args)
|
203
|
+
nil
|
204
|
+
end
|
205
|
+
|
206
|
+
def putc(obj)
|
207
|
+
requireWritable
|
208
|
+
write(obj.is_a?(Numeric) ? sprintf("%c", obj) : obj.to_s[0..0])
|
209
|
+
obj
|
210
|
+
end
|
211
|
+
|
212
|
+
def puts(*args)
|
213
|
+
requireWritable
|
214
|
+
args.unshift("") if args.empty?
|
215
|
+
args.each { |obj|
|
216
|
+
write obj
|
217
|
+
write $/
|
218
|
+
}
|
219
|
+
nil
|
220
|
+
end
|
221
|
+
|
222
|
+
def read(length=nil, buffer=nil)
|
223
|
+
requireReadable
|
224
|
+
len = length || [@sio_string.length - @sio_pos, 0].max
|
225
|
+
raise ArgumentError, "negative length #{len} given", caller if len < 0
|
226
|
+
buffer ||= ""
|
227
|
+
pstart = @sio_pos
|
228
|
+
@sio_pos += len
|
229
|
+
buffer.replace(@sio_string[pstart..@sio_pos])
|
230
|
+
buffer.empty? && !length.nil? ? nil : buffer
|
231
|
+
end
|
232
|
+
|
233
|
+
def readchar
|
234
|
+
requireReadable
|
235
|
+
raise EOFError, "End of file reached", caller if eof?
|
236
|
+
getc
|
237
|
+
end
|
238
|
+
|
239
|
+
def readline
|
240
|
+
requireReadable
|
241
|
+
raise EOFError, "End of file reached", caller if eof?
|
242
|
+
gets
|
243
|
+
end
|
244
|
+
|
245
|
+
def readlines(sep_string=$/)
|
246
|
+
requireReadable
|
247
|
+
raise EOFError, "End of file reached", caller if eof?
|
248
|
+
rc = []
|
249
|
+
until eof
|
250
|
+
rc << gets(sep_string)
|
251
|
+
end
|
252
|
+
rc
|
253
|
+
end
|
254
|
+
|
255
|
+
def reopen(string, mode=nil)
|
256
|
+
if string.is_a?(self.class) then
|
257
|
+
raise ArgumentError, "wrong number of arguments (2 for 1)", caller if !mode.nil?
|
258
|
+
@relay = string
|
259
|
+
instance_eval(%Q{
|
260
|
+
class << self
|
261
|
+
@@relayMethods.each { |name|
|
262
|
+
define_method(name, ObjectSpace._id2ref(#{@relay.object_id}).method(("original_" + name.to_s).to_sym).to_proc)
|
263
|
+
}
|
264
|
+
end
|
265
|
+
})
|
266
|
+
else
|
267
|
+
raise ArgumentError, "wrong number of arguments (1 for 2)", caller if mode.nil?
|
268
|
+
class << self
|
269
|
+
@@relayMethods.each { |name|
|
270
|
+
alias_method(name, "original_#{name}".to_sym)
|
271
|
+
public name
|
272
|
+
}
|
273
|
+
@relay = nil
|
274
|
+
end unless @relay.nil?
|
275
|
+
@sio_string = string.to_s
|
276
|
+
@mode = mode
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def rewind
|
281
|
+
@sio_pos = 0
|
282
|
+
@sio_lineno = 0
|
283
|
+
end
|
284
|
+
|
285
|
+
def seek(amount, whence=SEEK_SET)
|
286
|
+
if whence == SEEK_CUR then
|
287
|
+
offset += @sio_pos
|
288
|
+
elsif whence == SEEK_END then
|
289
|
+
offset += size
|
290
|
+
end
|
291
|
+
@sio_pos = offset
|
292
|
+
end
|
293
|
+
|
294
|
+
def string
|
295
|
+
@sio_string
|
296
|
+
end
|
297
|
+
|
298
|
+
def string=(newstring)
|
299
|
+
@sio_string = newstring
|
300
|
+
end
|
301
|
+
|
302
|
+
def sync
|
303
|
+
true
|
304
|
+
end
|
305
|
+
|
306
|
+
def sync=(boolean)
|
307
|
+
boolean
|
308
|
+
end
|
309
|
+
|
310
|
+
def sysread(length=nil, buffer=nil)
|
311
|
+
requireReadable
|
312
|
+
raise EOFError, "End of file reached", caller if eof?
|
313
|
+
read(length, buffer)
|
314
|
+
end
|
315
|
+
|
316
|
+
def syswrite(string)
|
317
|
+
requireWritable
|
318
|
+
addition = "\000" * (@sio_string.length - @sio_pos) + string.to_s
|
319
|
+
@sio_string[@sio_pos..(addition.length - 1)] = addition
|
320
|
+
@sio_pos += addition.size
|
321
|
+
addition.size
|
322
|
+
end
|
323
|
+
|
324
|
+
#In ruby 1.8.4 truncate differs from the docs in two ways.
|
325
|
+
#First, if an integer greater that the length is given then the string is expanded to the new integer
|
326
|
+
#length. As this expansion seems to contain junk characters instead of nulls I suspect this may be a
|
327
|
+
#flaw in the C code which could cause a core dump if abused/used.
|
328
|
+
#Second, the documentation states that truncate returns 0. It returns the integer instead.
|
329
|
+
#This implementation follows the documentation in the first instance as I suspect this will be fixed
|
330
|
+
#in the C code. In the second instance, it follows the actions of the C code instead of the docs.
|
331
|
+
#This was decided as it causes no immedeate harm and this ruby implentation is to be as compatable
|
332
|
+
#as possible with the C version. Should the C version change to match the docs the ruby version
|
333
|
+
#will be simple to update as well.
|
334
|
+
def truncate(integer)
|
335
|
+
requireWritable
|
336
|
+
raise Errno::EINVAL, "Invalid argument - negative length", caller if integer < 0
|
337
|
+
@sio_string[[integer, @sio_string.length].max..-1] = ""
|
338
|
+
integer
|
339
|
+
end
|
340
|
+
|
341
|
+
def ungetc(integer)
|
342
|
+
requireWritable
|
343
|
+
if @sio_pos > 0 then
|
344
|
+
@sio_pos -= 1
|
345
|
+
putc(integer)
|
346
|
+
@sio_pos -= 1
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
alias :each_line :each
|
351
|
+
alias :eof? :eof
|
352
|
+
alias :size :length
|
353
|
+
alias :tty? :isatty
|
354
|
+
alias :tell :pos
|
355
|
+
alias :write :syswrite
|
356
|
+
|
357
|
+
protected
|
358
|
+
@@relayMethods.each { |name|
|
359
|
+
alias_method("original_#{name}".to_sym, name)
|
360
|
+
protected "original_#{name}".to_sym
|
361
|
+
}
|
362
|
+
|
363
|
+
private
|
364
|
+
|
365
|
+
def requireReadable
|
366
|
+
raise IOError, "not opened for reading", caller[1..-1] if @sio_closed_read
|
367
|
+
end
|
368
|
+
|
369
|
+
def requireWritable
|
370
|
+
raise IOError, "not opened for writing", caller[1..-1] if @sio_closed_write
|
371
|
+
end
|
372
|
+
|
373
|
+
def requireOpen
|
374
|
+
raise IOError, "closed stream", caller[1..-1] if @sio_closed_read && @sio_closed_write
|
375
|
+
end
|
376
|
+
|
377
|
+
end
|
378
|
+
end
|
data/test/break-idea.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# break-idea.rb Richard Kernahan <kernighan_rich@rubyforge.org>
|
2
|
+
# prove that IDEA is broken and try to find out why
|
3
|
+
|
4
|
+
require 'crypt/idea'
|
5
|
+
require 'crypt/blowfish'
|
6
|
+
|
7
|
+
# generate evidence for defect in IDEA implementation
|
8
|
+
# idea_en = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::ENCRYPT)
|
9
|
+
# idea_de = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::DECRYPT)
|
10
|
+
# srand()
|
11
|
+
# puts "Finding pairs that fail to encrypt:"
|
12
|
+
# while(true)
|
13
|
+
# origL = rand(Crypt::IDEA::ULONG)
|
14
|
+
# origR = rand(Crypt::IDEA::ULONG)
|
15
|
+
# cl, cr = idea_en.crypt_pair(origL, origR)
|
16
|
+
# dl, dr = idea_de.crypt_pair(cl, cr)
|
17
|
+
# if ((origL != dl) | (origR != dr))
|
18
|
+
# cl, cr = idea_en.crypt_pair(origL, origR)
|
19
|
+
# dl, dr = idea_de.crypt_pair(cl, cr)
|
20
|
+
# if ((origL != dl) | (origR != dr))
|
21
|
+
# printf("[0x%-9x , 0x%-9x]\n", origL, origR)
|
22
|
+
# $stdout.flush()
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
# fatalPairs = [
|
27
|
+
# [0x5bb809a4, 0x804d4aba ],
|
28
|
+
# [0xead99b1 , 0xf64a62dd ],
|
29
|
+
# [0x50d72345, 0x4f6036d9 ],
|
30
|
+
# [0x32d41b94, 0x796a2eb5 ],
|
31
|
+
# [0x5d8a606e, 0x33befad ],
|
32
|
+
# [0x87b9dd21, 0xf5d9e7ce ],
|
33
|
+
# [0xd96be22c, 0x68fe08c9 ],
|
34
|
+
# [0x452131e8, 0xe687bd5 ],
|
35
|
+
# [0x827d9308, 0x512ace3d ],
|
36
|
+
# [0x5f0931d1, 0xb3b5c5c1 ],
|
37
|
+
# [0xd6dc1475, 0xf8964e8b ],
|
38
|
+
# [0xb7d7bba6, 0x8b8652e9 ],
|
39
|
+
# [0x2f42b24b, 0x6a889e95 ],
|
40
|
+
# [0x4e6eaebb, 0x99816f1 ]
|
41
|
+
# ]
|
42
|
+
# fatalPairs.each { |pair|
|
43
|
+
# origL, origR = pair
|
44
|
+
# cl, cr = idea_en.crypt_pair(origL, origR)
|
45
|
+
# dl, dr = idea_de.crypt_pair(cl, cr)
|
46
|
+
# if ((origL != dl) | (origR != dr))
|
47
|
+
# puts "still broken"
|
48
|
+
# end
|
49
|
+
# }
|
50
|
+
#idea = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::ENCRYPT)
|
51
|
+
#(-3..0x10003).each { |a|
|
52
|
+
# inv = idea.mulInv(a)
|
53
|
+
# product = idea.mul(a, inv)
|
54
|
+
# if product != 1
|
55
|
+
# puts "a=#{a} inv=#{inv} mul(a,inv)=#{product}"
|
56
|
+
# $stdout.flush()
|
57
|
+
# end
|
58
|
+
#}
|
59
|
+
|
60
|
+
|
61
|
+
|
data/test/devServer.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# run the crypt website
|
2
|
+
|
3
|
+
require 'webrick'
|
4
|
+
include WEBrick
|
5
|
+
|
6
|
+
serverConfig = {
|
7
|
+
:Port => 80,
|
8
|
+
:Logger => WEBrick::Log.new($stderr, WEBrick::Log::ERROR),
|
9
|
+
:AccessLog => [[$stderr, WEBrick::AccessLog::COMBINED_LOG_FORMAT]]
|
10
|
+
}
|
11
|
+
server = WEBrick::HTTPServer.new(serverConfig)
|
12
|
+
server.mount("/", HTTPServlet::FileHandler, "C:/workspace/Crypt/site/", {:FancyIndexing => true})
|
13
|
+
server.mount("/crypt", HTTPServlet::FileHandler, "C:/workspace/Crypt/crypt/", {:FancyIndexing => true})
|
14
|
+
|
15
|
+
server.start
|
16
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# testblowfish.rb bryllig
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'crypt/blowfish'
|
5
|
+
require 'crypt/cbc'
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
class TestBlowfish < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@bf = Crypt::Blowfish.new("Who is John Galt?") # Schneier's test key
|
12
|
+
end
|
13
|
+
|
14
|
+
def teardown
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_block_size
|
18
|
+
assert_equal(8, @bf.block_size(), "Wrong block size")
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_initialize
|
22
|
+
assert_raise(RuntimeError) {
|
23
|
+
b0 = Crypt::Blowfish.new("")
|
24
|
+
}
|
25
|
+
assert_nothing_raised() {
|
26
|
+
b1 = Crypt::Blowfish.new("1")
|
27
|
+
}
|
28
|
+
assert_nothing_raised() {
|
29
|
+
b56 = Crypt::Blowfish.new("1"*56)
|
30
|
+
}
|
31
|
+
assert_raise(RuntimeError) {
|
32
|
+
b57 = Crypt::Blowfish.new("1"*57)
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_pair
|
37
|
+
bf = Crypt::Blowfish.new("Who is John Galt?")
|
38
|
+
orig_l, orig_r = [0xfedcba98, 0x76543210]
|
39
|
+
l, r = bf.encrypt_pair(orig_l, orig_r)
|
40
|
+
assert_equal(0xcc91732b, l)
|
41
|
+
assert_equal(0x8022f684, r)
|
42
|
+
l, r = bf.decrypt_pair(l, r)
|
43
|
+
assert_equal(orig_l, l)
|
44
|
+
assert_equal(orig_r, r)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_block
|
48
|
+
bf = Crypt::Blowfish.new("Who is John Galt?")
|
49
|
+
block = "norandom"
|
50
|
+
encryptedBlock = bf.encrypt_block(block)
|
51
|
+
assert_equal("\236\353k\321&Q\"\220", encryptedBlock)
|
52
|
+
decryptedBlock = bf.decrypt_block(encryptedBlock)
|
53
|
+
assert_equal(block, decryptedBlock)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_string
|
57
|
+
length = 30 + rand(26)
|
58
|
+
userkey = ""
|
59
|
+
length.times { userkey << rand(256).chr }
|
60
|
+
bf = Crypt::Blowfish.new(userkey)
|
61
|
+
string = "This is a string which is not a multiple of 8 characters long"
|
62
|
+
encryptedString = bf.encrypt_string(string)
|
63
|
+
decryptedString = bf.decrypt_string(encryptedString)
|
64
|
+
assert_equal(string, decryptedString)
|
65
|
+
secondstring = "This is another string to check repetitive use."
|
66
|
+
encryptedString = bf.encrypt_string(secondstring)
|
67
|
+
decryptedString = bf.decrypt_string(encryptedString)
|
68
|
+
assert_equal(secondstring, decryptedString)
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_file
|
73
|
+
plainText = "This is a multi-line string\nwhich is not a multiple of 8 \ncharacters long."
|
74
|
+
plainFile = File.new('plain.txt', 'wb+')
|
75
|
+
plainFile.puts(plainText)
|
76
|
+
plainFile.close()
|
77
|
+
bf = Crypt::Blowfish.new("Who is John Galt?")
|
78
|
+
bf.encrypt_file('plain.txt', 'crypt.txt')
|
79
|
+
bf.decrypt_file('crypt.txt', 'decrypt.txt')
|
80
|
+
decryptFile = File.new('decrypt.txt', 'rb')
|
81
|
+
decryptText = decryptFile.readlines().join('').chomp()
|
82
|
+
decryptFile.close()
|
83
|
+
assert_equal(plainText, decryptText)
|
84
|
+
FileUtils.rm('plain.txt')
|
85
|
+
FileUtils.rm('crypt.txt')
|
86
|
+
FileUtils.rm('decrypt.txt')
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
data/test/test-gost.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'crypt/gost'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class TestGost < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_init
|
14
|
+
assert_nothing_raised(RuntimeError) {
|
15
|
+
gost = Crypt::Gost.new("Whatever happened to Yuri Gagarin?")
|
16
|
+
}
|
17
|
+
assert_nothing_raised(RuntimeError) {
|
18
|
+
gost = Crypt::Gost.new("Whatever happened to Yuri?")
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_block_size
|
23
|
+
gost = Crypt::Gost.new("Whatever happened to Yuri?")
|
24
|
+
assert_equal(8, gost.block_size(), "Wrong block size")
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_pair
|
28
|
+
gost = Crypt::Gost.new("Whatever happened to Yuri?")
|
29
|
+
orig_l, orig_r = [0xfedcba98, 0x76543210]
|
30
|
+
l, r = gost.encrypt_pair(orig_l, orig_r)
|
31
|
+
assert_equal(0xaefaf8f4, l)
|
32
|
+
assert_equal(0xe24891b0, r)
|
33
|
+
l, r = gost.decrypt_pair(l, r)
|
34
|
+
assert_equal(orig_l, l)
|
35
|
+
assert_equal(orig_r, r)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_block
|
39
|
+
gost = Crypt::Gost.new("Whatever happened to Yuri?")
|
40
|
+
block = "norandom"
|
41
|
+
encryptedBlock = gost.encrypt_block(block)
|
42
|
+
assert_equal(".Vy\377\005\e3`", encryptedBlock)
|
43
|
+
decryptedBlock = gost.decrypt_block(encryptedBlock)
|
44
|
+
assert_equal(block, decryptedBlock)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_string
|
48
|
+
length = 25 + rand(12)
|
49
|
+
userkey = ""
|
50
|
+
length.times { userkey << rand(256).chr }
|
51
|
+
gost = Crypt::Gost.new(userkey)
|
52
|
+
string = "This is a string which is not a multiple of 8 characters long"
|
53
|
+
encryptedString = gost.encrypt_string(string)
|
54
|
+
decryptedString = gost.decrypt_string(encryptedString)
|
55
|
+
assert_equal(string, decryptedString)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_file
|
59
|
+
plainText = "This is a multi-line string\nwhich is not a multiple of 8 \ncharacters long."
|
60
|
+
plainFile = File.new('plain.txt', 'wb+')
|
61
|
+
plainFile.puts(plainText)
|
62
|
+
plainFile.close()
|
63
|
+
gost = Crypt::Gost.new("Whatever happened to Yuri?")
|
64
|
+
gost.encrypt_file('plain.txt', 'crypt.txt')
|
65
|
+
gost.decrypt_file('crypt.txt', 'decrypt.txt')
|
66
|
+
decryptFile = File.new('decrypt.txt', 'rb')
|
67
|
+
decryptText = decryptFile.readlines().join('').chomp()
|
68
|
+
decryptFile.close()
|
69
|
+
assert_equal(plainText, decryptText)
|
70
|
+
FileUtils.rm('plain.txt')
|
71
|
+
FileUtils.rm('crypt.txt')
|
72
|
+
FileUtils.rm('decrypt.txt')
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
data/test/test-idea.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'crypt/idea'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class TestIdea < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_init
|
14
|
+
assert_nothing_raised(RuntimeError) {
|
15
|
+
idea_en = Crypt::IDEA.new("Who was John Galt and where's my breakfast?", Crypt::IDEA::ENCRYPT)
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_block_size
|
20
|
+
idea_en = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::ENCRYPT)
|
21
|
+
assert_equal(8, idea_en.block_size(), "Wrong block size")
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_pair
|
25
|
+
idea_en = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::ENCRYPT)
|
26
|
+
orig_l, orig_r = [0xfedcba98, 0x76543210]
|
27
|
+
l, r = idea_en.crypt_pair(orig_l, orig_r)
|
28
|
+
assert_equal(0x05627e79, l)
|
29
|
+
assert_equal(0x69476521, r)
|
30
|
+
idea_de = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::DECRYPT)
|
31
|
+
l, r = idea_de.crypt_pair(l, r)
|
32
|
+
assert_equal(orig_l, l)
|
33
|
+
assert_equal(orig_r, r)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_block
|
37
|
+
idea_en = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::ENCRYPT)
|
38
|
+
block = "norandom"
|
39
|
+
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
|
+
decryptedBlock = idea_de.decrypt_block(encryptedBlock)
|
43
|
+
assert_equal(block, decryptedBlock)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_string
|
47
|
+
length = 25 + rand(12)
|
48
|
+
userkey = ""
|
49
|
+
length.times { userkey << rand(256).chr }
|
50
|
+
idea_en = Crypt::IDEA.new(userkey, Crypt::IDEA::ENCRYPT)
|
51
|
+
string = "This is a string which is not a multiple of 8 characters long"
|
52
|
+
encryptedString = idea_en.encrypt_string(string)
|
53
|
+
idea_de = Crypt::IDEA.new(userkey, Crypt::IDEA::DECRYPT)
|
54
|
+
decryptedString = idea_de.decrypt_string(encryptedString)
|
55
|
+
assert_equal(string, decryptedString)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_file
|
59
|
+
plainText = "This is a multi-line string\nwhich is not a multiple of 8 \ncharacters long."
|
60
|
+
plainFile = File.new('plain.txt', 'wb+')
|
61
|
+
plainFile.puts(plainText)
|
62
|
+
plainFile.close()
|
63
|
+
idea_en = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::ENCRYPT)
|
64
|
+
idea_en.encrypt_file('plain.txt', 'crypt.txt')
|
65
|
+
idea_de = Crypt::IDEA.new("Who is John Galt", Crypt::IDEA::DECRYPT)
|
66
|
+
idea_de.decrypt_file('crypt.txt', 'decrypt.txt')
|
67
|
+
decryptFile = File.new('decrypt.txt', 'rb')
|
68
|
+
decryptText = decryptFile.readlines().join('').chomp()
|
69
|
+
decryptFile.close()
|
70
|
+
assert_equal(plainText, decryptText)
|
71
|
+
FileUtils.rm('plain.txt')
|
72
|
+
FileUtils.rm('crypt.txt')
|
73
|
+
FileUtils.rm('decrypt.txt')
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'crypt/rijndael'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class TestRijndael < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_init
|
14
|
+
assert_raise(RuntimeError) {
|
15
|
+
rijndael = Crypt::Rijndael.new("Who is this John Galt guy, anyway?", 64)
|
16
|
+
}
|
17
|
+
assert_raise(RuntimeError) {
|
18
|
+
rijndael = Crypt::Rijndael.new("Who is this John Galt guy, anyway?", 128, 64)
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_block_size
|
23
|
+
rijndael = Crypt::Rijndael.new("Who is this John Galt guy, anyway?", 128, 256)
|
24
|
+
assert_equal(32, rijndael.block_size)
|
25
|
+
rijndael = Crypt::Rijndael.new("Who is this John Galt guy, anyway?", 256, 128)
|
26
|
+
assert_equal(16, rijndael.block_size)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_block
|
30
|
+
rijndael = Crypt::Rijndael.new("Who is this John Galt guy, anyway?", 128, 128)
|
31
|
+
block = "\341q\214NIj\023u\343\330s\323\354$g\277"
|
32
|
+
encryptedBlock = rijndael.encrypt_block(block)
|
33
|
+
assert_equal("\024\246^\332T\323x`\323yB\352\2159\212R", encryptedBlock)
|
34
|
+
decryptedBlock = rijndael.decrypt_block(encryptedBlock)
|
35
|
+
assert_equal(block, decryptedBlock)
|
36
|
+
rijndael = Crypt::Rijndael.new("Who is this John Galt guy, anyway?", 128, 256)
|
37
|
+
assert_raise(RuntimeError) {
|
38
|
+
encryptedBlock = rijndael.encrypt_block(block)
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_string
|
43
|
+
rijndael = Crypt::Rijndael.new("Who is this John Galt guy, anyway?")
|
44
|
+
string = "This is a string which is not a multiple of 8 characters long"
|
45
|
+
encryptedString = rijndael.encrypt_string(string)
|
46
|
+
decryptedString = rijndael.decrypt_string(encryptedString)
|
47
|
+
assert_equal(string, decryptedString)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_file
|
51
|
+
plainText = "This is a multi-line string\nwhich is not a multiple of 8 \ncharacters long."
|
52
|
+
plainFile = File.new('plain.txt', 'wb+')
|
53
|
+
plainFile.puts(plainText)
|
54
|
+
plainFile.close()
|
55
|
+
rijndael = Crypt::Rijndael.new("Who is this John Galt guy, anyway?")
|
56
|
+
rijndael.encrypt_file('plain.txt', 'crypt.txt')
|
57
|
+
rijndael.decrypt_file('crypt.txt', 'decrypt.txt')
|
58
|
+
decryptFile = File.new('decrypt.txt', 'rb')
|
59
|
+
decryptText = decryptFile.readlines().join('').chomp()
|
60
|
+
decryptFile.close()
|
61
|
+
assert_equal(plainText, decryptText)
|
62
|
+
FileUtils.rm('plain.txt')
|
63
|
+
FileUtils.rm('crypt.txt')
|
64
|
+
FileUtils.rm('decrypt.txt')
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.10
|
|
3
3
|
specification_version: 1
|
4
4
|
name: crypt
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.1.
|
7
|
-
date: 2006-08-
|
6
|
+
version: 1.1.4
|
7
|
+
date: 2006-08-06
|
8
8
|
summary: "The Crypt library is a pure-ruby implementation of a number of popular
|
9
9
|
encryption algorithms. Block cyphers currently include Blowfish, GOST, IDEA, and
|
10
10
|
Rijndael (AES). Cypher Block Chaining (CBC) has been implemented. Twofish,
|
@@ -36,9 +36,16 @@ files:
|
|
36
36
|
- crypt/gost.rb
|
37
37
|
- crypt/idea.rb
|
38
38
|
- crypt/noise.rb
|
39
|
+
- crypt/purerubystringio.rb
|
39
40
|
- crypt/rijndael-tables.rb
|
40
41
|
- crypt/rijndael.rb
|
41
42
|
- crypt/stringxor.rb
|
43
|
+
- test/break-idea.rb
|
44
|
+
- test/devServer.rb
|
45
|
+
- test/test-blowfish.rb
|
46
|
+
- test/test-gost.rb
|
47
|
+
- test/test-idea.rb
|
48
|
+
- test/test-rijndael.rb
|
42
49
|
test_files: []
|
43
50
|
rdoc_options: []
|
44
51
|
extra_rdoc_files: []
|