crypt 1.1.3 → 1.1.4
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.
- 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: []
|