flatulent 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README +60 -16
- data/flatulent-0.0.2.gem +0 -0
- data/lib/flatulent/crypt/blowfish-tables.rb +190 -0
- data/lib/flatulent/crypt/blowfish.rb +109 -0
- data/lib/flatulent/crypt/cbc.rb +123 -0
- data/lib/flatulent/crypt/gost.rb +140 -0
- data/lib/flatulent/crypt/idea.rb +193 -0
- data/lib/flatulent/crypt/noise.rb +94 -0
- data/lib/flatulent/crypt/purerubystringio.rb +378 -0
- data/lib/flatulent/crypt/rijndael-tables.rb +117 -0
- data/lib/flatulent/crypt/rijndael.rb +269 -0
- data/lib/flatulent/crypt/stringxor.rb +27 -0
- data/lib/flatulent.rb +332 -121
- data/lib/flatulent.rb.bak +337 -0
- data/rails/app/controllers/flatulent_controller.rb +61 -6
- data/rails/lib/flatulent/attributes.rb +79 -0
- data/rails/lib/flatulent/crypt/blowfish-tables.rb +190 -0
- data/rails/lib/flatulent/crypt/blowfish.rb +109 -0
- data/rails/lib/flatulent/crypt/cbc.rb +123 -0
- data/rails/lib/flatulent/crypt/gost.rb +140 -0
- data/rails/lib/flatulent/crypt/idea.rb +193 -0
- data/rails/lib/flatulent/crypt/noise.rb +94 -0
- data/rails/lib/flatulent/crypt/purerubystringio.rb +378 -0
- data/rails/lib/flatulent/crypt/rijndael-tables.rb +117 -0
- data/rails/lib/flatulent/crypt/rijndael.rb +269 -0
- data/rails/lib/flatulent/fontfiles/banner.flf +2494 -0
- data/rails/lib/flatulent/fontfiles/big.flf +2204 -0
- data/rails/lib/flatulent/fontfiles/block.flf +1691 -0
- data/rails/lib/flatulent/fontfiles/bubble.flf +1630 -0
- data/rails/lib/flatulent/fontfiles/digital.flf +1286 -0
- data/rails/lib/flatulent/fontfiles/ivrit.flf +900 -0
- data/rails/lib/flatulent/fontfiles/lean.flf +1691 -0
- data/rails/lib/flatulent/fontfiles/mini.flf +899 -0
- data/rails/lib/flatulent/fontfiles/mnemonic.flf +3702 -0
- data/rails/lib/flatulent/fontfiles/script.flf +1493 -0
- data/rails/lib/flatulent/fontfiles/shadow.flf +1097 -0
- data/rails/lib/flatulent/fontfiles/slant.flf +1295 -0
- data/rails/lib/flatulent/fontfiles/small.flf +1097 -0
- data/rails/lib/flatulent/fontfiles/smscript.flf +1097 -0
- data/rails/lib/flatulent/fontfiles/smshadow.flf +899 -0
- data/rails/lib/flatulent/fontfiles/smslant.flf +1097 -0
- data/rails/lib/flatulent/fontfiles/standard.flf +2227 -0
- data/rails/lib/flatulent/fontfiles/term.flf +600 -0
- data/rails/lib/flatulent/pervasives.rb +32 -0
- data/rails/lib/flatulent/stringxor.rb +27 -0
- data/rails/lib/flatulent/text/double_metaphone.rb +356 -0
- data/rails/lib/flatulent/text/figlet/font.rb +117 -0
- data/rails/lib/flatulent/text/figlet/smusher.rb +64 -0
- data/rails/lib/flatulent/text/figlet/typesetter.rb +68 -0
- data/rails/lib/flatulent/text/figlet.rb +17 -0
- data/rails/lib/flatulent/text/levenshtein.rb +65 -0
- data/rails/lib/flatulent/text/metaphone.rb +97 -0
- data/rails/lib/flatulent/text/porter_stemming.rb +171 -0
- data/rails/lib/flatulent/text/soundex.rb +61 -0
- data/rails/lib/flatulent/text.rb +6 -0
- data/rails/lib/flatulent.rb +450 -0
- data/rails/log/development.log +14297 -0
- data/rails/log/fastcgi.crash.log +111 -0
- data/rails/log/lighttpd.access.log +3993 -0
- data/rails/log/lighttpd.error.log +111 -0
- data/rails/tmp/cache/javascripts/prototype.js-gzip-3275912-71260-1183440172 +0 -0
- data/rails/tmp/sessions/ruby_sess.32d68bc997054475 +0 -0
- data/rails/tmp/sessions/ruby_sess.4694a4b9bdf9bcf4 +0 -0
- data/rails/tmp/sessions/ruby_sess.99469fde69043a05 +0 -0
- data/rails/tmp/sessions/ruby_sess.a588c0a457345912 +0 -0
- data/rails/tmp/sessions/ruby_sess.b3344125a84a3efa +0 -0
- data/samples.rb +10 -0
- metadata +69 -3
- data/flatulent-0.0.0.gem +0 -0
@@ -0,0 +1,109 @@
|
|
1
|
+
# blowfish.rb Richard Kernahan <kernighan_rich@rubyforge.org>
|
2
|
+
#
|
3
|
+
# Blowfish algorithm by Bruce Schneider
|
4
|
+
# Ported by Richard Kernahan from the reference C code
|
5
|
+
module Crypt
|
6
|
+
class Blowfish
|
7
|
+
|
8
|
+
require 'crypt/cbc'
|
9
|
+
include Crypt::CBC
|
10
|
+
|
11
|
+
require 'crypt/blowfish-tables'
|
12
|
+
include Crypt::BlowfishTables
|
13
|
+
|
14
|
+
ULONG = 0x100000000
|
15
|
+
|
16
|
+
def block_size
|
17
|
+
return(8)
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def initialize(key)
|
22
|
+
@key = key
|
23
|
+
raise "Bad key length: the key must be 1-56 bytes." unless (key.length.between?(1,56))
|
24
|
+
@pArray = []
|
25
|
+
@sBoxes = []
|
26
|
+
setup_blowfish()
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def f(x)
|
31
|
+
a, b, c, d = [x].pack('N').unpack('CCCC')
|
32
|
+
y = (@sBoxes[0][a] + @sBoxes[1][b]) % ULONG
|
33
|
+
y = (y ^ @sBoxes[2][c]) % ULONG
|
34
|
+
y = (y + @sBoxes[3][d]) % ULONG
|
35
|
+
return(y)
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def setup_blowfish()
|
40
|
+
@sBoxes = Array.new(4) { |i| INITIALSBOXES[i].clone }
|
41
|
+
@pArray = INITIALPARRAY.clone
|
42
|
+
keypos = 0
|
43
|
+
0.upto(17) { |i|
|
44
|
+
data = 0
|
45
|
+
4.times {
|
46
|
+
data = ((data << 8) | @key[keypos]) % ULONG
|
47
|
+
keypos = (keypos.next) % @key.length
|
48
|
+
}
|
49
|
+
@pArray[i] = (@pArray[i] ^ data) % ULONG
|
50
|
+
}
|
51
|
+
l = 0
|
52
|
+
r = 0
|
53
|
+
0.step(17, 2) { |i|
|
54
|
+
l, r = encrypt_pair(l, r)
|
55
|
+
@pArray[i] = l
|
56
|
+
@pArray[i+1] = r
|
57
|
+
}
|
58
|
+
0.upto(3) { |i|
|
59
|
+
0.step(255, 2) { |j|
|
60
|
+
l, r = encrypt_pair(l, r)
|
61
|
+
@sBoxes[i][j] = l
|
62
|
+
@sBoxes[i][j+1] = r
|
63
|
+
}
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
def encrypt_pair(xl, xr)
|
68
|
+
0.upto(15) { |i|
|
69
|
+
xl = (xl ^ @pArray[i]) % ULONG
|
70
|
+
xr = (xr ^ f(xl)) % ULONG
|
71
|
+
xl, xr = [xl, xr].reverse
|
72
|
+
}
|
73
|
+
xl, xr = [xl, xr].reverse
|
74
|
+
xr = (xr ^ @pArray[16]) % ULONG
|
75
|
+
xl = (xl ^ @pArray[17]) % ULONG
|
76
|
+
return([xl, xr])
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def decrypt_pair(xl, xr)
|
81
|
+
17.downto(2) { |i|
|
82
|
+
xl = (xl ^ @pArray[i]) % ULONG
|
83
|
+
xr = (xr ^ f(xl)) % ULONG
|
84
|
+
xl, xr = [xl, xr].reverse
|
85
|
+
}
|
86
|
+
xl, xr = [xl, xr].reverse
|
87
|
+
xr = (xr ^ @pArray[1]) % ULONG
|
88
|
+
xl = (xl ^ @pArray[0]) % ULONG
|
89
|
+
return([xl, xr])
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
def encrypt_block(block)
|
94
|
+
xl, xr = block.unpack('NN')
|
95
|
+
xl, xr = encrypt_pair(xl, xr)
|
96
|
+
encrypted = [xl, xr].pack('NN')
|
97
|
+
return(encrypted)
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
def decrypt_block(block)
|
102
|
+
xl, xr = block.unpack('NN')
|
103
|
+
xl, xr = decrypt_pair(xl, xr)
|
104
|
+
decrypted = [xl, xr].pack('NN')
|
105
|
+
return(decrypted)
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# cbc.rb Richard Kernahan <kernighan_rich@rubyforge.org>
|
2
|
+
|
3
|
+
module Crypt
|
4
|
+
module CBC
|
5
|
+
|
6
|
+
require 'stringio'
|
7
|
+
require 'crypt/stringxor'
|
8
|
+
|
9
|
+
ULONG = 0x100000000
|
10
|
+
|
11
|
+
# When this module is mixed in with an encryption class, the class
|
12
|
+
# must provide three methods: encrypt_block(block) and decrypt_block(block)
|
13
|
+
# and block_size()
|
14
|
+
|
15
|
+
|
16
|
+
def generate_initialization_vector(words)
|
17
|
+
srand(Time.now.to_i)
|
18
|
+
vector = ""
|
19
|
+
words.times {
|
20
|
+
vector << [rand(ULONG)].pack('N')
|
21
|
+
}
|
22
|
+
return(vector)
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def encrypt_stream(plainStream, cryptStream)
|
27
|
+
# Cypher-block-chain mode
|
28
|
+
|
29
|
+
initVector = generate_initialization_vector(block_size() / 4)
|
30
|
+
chain = encrypt_block(initVector)
|
31
|
+
cryptStream.write(chain)
|
32
|
+
|
33
|
+
while ((block = plainStream.read(block_size())) && (block.length == block_size()))
|
34
|
+
block = block ^ chain
|
35
|
+
encrypted = encrypt_block(block)
|
36
|
+
cryptStream.write(encrypted)
|
37
|
+
chain = encrypted
|
38
|
+
end
|
39
|
+
|
40
|
+
# write the final block
|
41
|
+
# At most block_size()-1 bytes can be part of the message.
|
42
|
+
# That means the final byte can be used to store the number of meaningful
|
43
|
+
# bytes in the final block
|
44
|
+
block = '' if block.nil?
|
45
|
+
buffer = block.split('')
|
46
|
+
remainingMessageBytes = buffer.length
|
47
|
+
# we use 7-bit characters to avoid possible strange behavior on the Mac
|
48
|
+
remainingMessageBytes.upto(block_size()-2) { buffer << rand(128).chr }
|
49
|
+
buffer << remainingMessageBytes.chr
|
50
|
+
block = buffer.join('')
|
51
|
+
block = block ^ chain
|
52
|
+
encrypted = encrypt_block(block)
|
53
|
+
cryptStream.write(encrypted)
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def decrypt_stream(cryptStream, plainStream)
|
58
|
+
# Cypher-block-chain mode
|
59
|
+
chain = cryptStream.read(block_size())
|
60
|
+
|
61
|
+
while (block = cryptStream.read(block_size()))
|
62
|
+
decrypted = decrypt_block(block)
|
63
|
+
plainText = decrypted ^ chain
|
64
|
+
plainStream.write(plainText) unless cryptStream.eof?
|
65
|
+
chain = block
|
66
|
+
end
|
67
|
+
|
68
|
+
# write the final block, omitting the padding
|
69
|
+
buffer = plainText.split('')
|
70
|
+
remainingMessageBytes = buffer.last.unpack('C').first
|
71
|
+
remainingMessageBytes.times { plainStream.write(buffer.shift) }
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def carefully_open_file(filename, mode)
|
76
|
+
begin
|
77
|
+
aFile = File.new(filename, mode)
|
78
|
+
rescue
|
79
|
+
puts "Sorry. There was a problem opening the file <#{filename}>."
|
80
|
+
aFile.close() unless aFile.nil?
|
81
|
+
raise
|
82
|
+
end
|
83
|
+
return(aFile)
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
def encrypt_file(plainFilename, cryptFilename)
|
88
|
+
plainFile = carefully_open_file(plainFilename, 'rb')
|
89
|
+
cryptFile = carefully_open_file(cryptFilename, 'wb+')
|
90
|
+
encrypt_stream(plainFile, cryptFile)
|
91
|
+
plainFile.close unless plainFile.closed?
|
92
|
+
cryptFile.close unless cryptFile.closed?
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
def decrypt_file(cryptFilename, plainFilename)
|
97
|
+
cryptFile = carefully_open_file(cryptFilename, 'rb')
|
98
|
+
plainFile = carefully_open_file(plainFilename, 'wb+')
|
99
|
+
decrypt_stream(cryptFile, plainFile)
|
100
|
+
cryptFile.close unless cryptFile.closed?
|
101
|
+
plainFile.close unless plainFile.closed?
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def encrypt_string(plainText)
|
106
|
+
plainStream = StringIO.new(plainText)
|
107
|
+
cryptStream = StringIO.new('')
|
108
|
+
encrypt_stream(plainStream, cryptStream)
|
109
|
+
cryptText = cryptStream.string
|
110
|
+
return(cryptText)
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
def decrypt_string(cryptText)
|
115
|
+
cryptStream = StringIO.new(cryptText)
|
116
|
+
plainStream = StringIO.new('')
|
117
|
+
decrypt_stream(cryptStream, plainStream)
|
118
|
+
plainText = plainStream.string
|
119
|
+
return(plainText)
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# gost.rb
|
2
|
+
# Adapted by Richard Kernahan <kernighan_rich@rubyforge.org>
|
3
|
+
# from C++ code written by Wei Dai
|
4
|
+
# of the Crypto++ project http://www.eskimo.com/~weidai/cryptlib.html
|
5
|
+
|
6
|
+
module Crypt
|
7
|
+
class Gost
|
8
|
+
|
9
|
+
require 'crypt/cbc'
|
10
|
+
include CBC
|
11
|
+
|
12
|
+
ULONG = 0x100000000
|
13
|
+
|
14
|
+
def block_size
|
15
|
+
return(8)
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
def initialize(userKey)
|
20
|
+
|
21
|
+
# These are the S-boxes given in Applied Cryptography 2nd Ed., p. 333
|
22
|
+
@sBox = [
|
23
|
+
[4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3],
|
24
|
+
[14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9],
|
25
|
+
[5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11],
|
26
|
+
[7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3],
|
27
|
+
[6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2],
|
28
|
+
[4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14],
|
29
|
+
[13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12],
|
30
|
+
[1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]
|
31
|
+
]
|
32
|
+
|
33
|
+
# These are the S-boxes given in the GOST source code listing in Applied
|
34
|
+
# Cryptography 2nd Ed., p. 644. They appear to be from the DES S-boxes
|
35
|
+
# [13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 ],
|
36
|
+
# [ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 ],
|
37
|
+
# [12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 ],
|
38
|
+
# [ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 ],
|
39
|
+
# [ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 ],
|
40
|
+
# [10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 ],
|
41
|
+
# [15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 ],
|
42
|
+
# [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 ]
|
43
|
+
|
44
|
+
# precalculate the S table
|
45
|
+
@sTable = precalculate_S_table()
|
46
|
+
|
47
|
+
# derive the 32-byte key from the user-supplied key
|
48
|
+
userKeyLength = userKey.length
|
49
|
+
@key = userKey[0..31].unpack('C'*32)
|
50
|
+
if (userKeyLength < 32)
|
51
|
+
userKeyLength.upto(31) { @key << 0 }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
def precalculate_S_table()
|
57
|
+
sTable = [[], [], [], []]
|
58
|
+
0.upto(3) { |i|
|
59
|
+
0.upto(255) { |j|
|
60
|
+
t = @sBox[2*i][j % 16] | (@sBox[2*i+1][j/16] << 4)
|
61
|
+
u = (8*i + 11) % 32
|
62
|
+
v = (t << u) | (t >> (32-u))
|
63
|
+
sTable[i][j] = (v % ULONG)
|
64
|
+
}
|
65
|
+
}
|
66
|
+
return(sTable)
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def f(longWord)
|
71
|
+
longWord = longWord % ULONG
|
72
|
+
a, b, c, d = [longWord].pack('L').unpack('CCCC')
|
73
|
+
return(@sTable[3][d] ^ @sTable[2][c] ^ @sTable[1][b] ^ @sTable[0][a])
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def encrypt_pair(xl, xr)
|
78
|
+
3.times {
|
79
|
+
xr ^= f(xl+@key[0])
|
80
|
+
xl ^= f(xr+@key[1])
|
81
|
+
xr ^= f(xl+@key[2])
|
82
|
+
xl ^= f(xr+@key[3])
|
83
|
+
xr ^= f(xl+@key[4])
|
84
|
+
xl ^= f(xr+@key[5])
|
85
|
+
xr ^= f(xl+@key[6])
|
86
|
+
xl ^= f(xr+@key[7])
|
87
|
+
}
|
88
|
+
xr ^= f(xl+@key[7])
|
89
|
+
xl ^= f(xr+@key[6])
|
90
|
+
xr ^= f(xl+@key[5])
|
91
|
+
xl ^= f(xr+@key[4])
|
92
|
+
xr ^= f(xl+@key[3])
|
93
|
+
xl ^= f(xr+@key[2])
|
94
|
+
xr ^= f(xl+@key[1])
|
95
|
+
xl ^= f(xr+@key[0])
|
96
|
+
return([xr, xl])
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
def decrypt_pair(xl, xr)
|
101
|
+
xr ^= f(xl+@key[0])
|
102
|
+
xl ^= f(xr+@key[1])
|
103
|
+
xr ^= f(xl+@key[2])
|
104
|
+
xl ^= f(xr+@key[3])
|
105
|
+
xr ^= f(xl+@key[4])
|
106
|
+
xl ^= f(xr+@key[5])
|
107
|
+
xr ^= f(xl+@key[6])
|
108
|
+
xl ^= f(xr+@key[7])
|
109
|
+
3.times {
|
110
|
+
xr ^= f(xl+@key[7])
|
111
|
+
xl ^= f(xr+@key[6])
|
112
|
+
xr ^= f(xl+@key[5])
|
113
|
+
xl ^= f(xr+@key[4])
|
114
|
+
xr ^= f(xl+@key[3])
|
115
|
+
xl ^= f(xr+@key[2])
|
116
|
+
xr ^= f(xl+@key[1])
|
117
|
+
xl ^= f(xr+@key[0])
|
118
|
+
}
|
119
|
+
return([xr, xl])
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
def encrypt_block(block)
|
124
|
+
xl, xr = block.unpack('NN')
|
125
|
+
xl, xr = encrypt_pair(xl, xr)
|
126
|
+
encrypted = [xl, xr].pack('NN')
|
127
|
+
return(encrypted)
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
def decrypt_block(block)
|
132
|
+
xl, xr = block.unpack('NN')
|
133
|
+
xl, xr = decrypt_pair(xl, xr)
|
134
|
+
decrypted = [xl, xr].pack('NN')
|
135
|
+
return(decrypted)
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
# idea.rb Richard Kernahan <kernighan_rich@rubyforge.org>
|
2
|
+
|
3
|
+
# IDEA (International Data Encryption Algorithm) by
|
4
|
+
# Xuejia Lai and James Massey (1992). Refer to license info at end.
|
5
|
+
# Ported by Richard Kernahan 2005
|
6
|
+
|
7
|
+
module Crypt
|
8
|
+
class IDEA
|
9
|
+
|
10
|
+
require 'crypt/cbc'
|
11
|
+
include Crypt::CBC
|
12
|
+
|
13
|
+
require 'digest/md5'
|
14
|
+
|
15
|
+
ULONG = 0x100000000
|
16
|
+
USHORT = 0x10000
|
17
|
+
|
18
|
+
ENCRYPT = 0
|
19
|
+
DECRYPT = 1
|
20
|
+
|
21
|
+
|
22
|
+
def block_size
|
23
|
+
return(8)
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def initialize(key128, mode)
|
28
|
+
# IDEA is subject to attack unless the key is sufficiently random, so we
|
29
|
+
# take an MD5 digest of a variable-length passphrase to ensure a solid key
|
30
|
+
if (key128.class == String)
|
31
|
+
digest = Digest::MD5.new(key128).digest
|
32
|
+
key128 = digest.unpack('n'*8)
|
33
|
+
end
|
34
|
+
raise "Key must be 128 bits (8 words)" unless (key128.class == Array) && (key128.length == 8)
|
35
|
+
raise "Mode must be IDEA::ENCRYPT or IDEA::DECRYPT" unless ((mode == ENCRYPT) | (mode == DECRYPT))
|
36
|
+
if (mode == ENCRYPT)
|
37
|
+
@subkeys = generate_encryption_subkeys(key128)
|
38
|
+
else (mode == DECRYPT)
|
39
|
+
@subkeys = generate_decryption_subkeys(key128)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def mul(a, b)
|
45
|
+
modulus = 0x10001
|
46
|
+
return((1 - b) % USHORT) if (a == 0)
|
47
|
+
return((1 - a) % USHORT) if (b == 0)
|
48
|
+
return((a * b) % modulus)
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def mulInv(x)
|
53
|
+
modulus = 0x10001
|
54
|
+
x = x.to_i % USHORT
|
55
|
+
return(x) if (x <= 1)
|
56
|
+
t1 = USHORT / x
|
57
|
+
y = modulus % x
|
58
|
+
if (y == 1)
|
59
|
+
inv = (1 - t1) & 0xFFFF
|
60
|
+
return(inv)
|
61
|
+
end
|
62
|
+
t0 = 1
|
63
|
+
while (y != 1)
|
64
|
+
q = x / y
|
65
|
+
x = x % y
|
66
|
+
t0 = t0 + (q * t1)
|
67
|
+
return(t0) if (x == 1)
|
68
|
+
q = y / x
|
69
|
+
y = y % x
|
70
|
+
t1 = t1 + (q * t0)
|
71
|
+
end
|
72
|
+
inv = (1 - t1) & 0xFFFF
|
73
|
+
return(inv)
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def generate_encryption_subkeys(key)
|
78
|
+
encrypt_keys = []
|
79
|
+
encrypt_keys[0..7] = key.dup
|
80
|
+
8.upto(51) { |i|
|
81
|
+
a = ((i + 1) % 8 > 0) ? (i-7) : (i-15)
|
82
|
+
b = ((i + 2) % 8 < 2) ? (i-14) : (i-6)
|
83
|
+
encrypt_keys[i] = ((encrypt_keys[a] << 9) | (encrypt_keys[b] >> 7)) % USHORT
|
84
|
+
}
|
85
|
+
return(encrypt_keys)
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
def generate_decryption_subkeys(key)
|
90
|
+
encrypt_keys = generate_encryption_subkeys(key)
|
91
|
+
decrypt_keys = []
|
92
|
+
decrypt_keys[48] = mulInv(encrypt_keys.shift)
|
93
|
+
decrypt_keys[49] = (-encrypt_keys.shift) % USHORT
|
94
|
+
decrypt_keys[50] = (-encrypt_keys.shift) % USHORT
|
95
|
+
decrypt_keys[51] = mulInv(encrypt_keys.shift)
|
96
|
+
42.step(0, -6) { |i|
|
97
|
+
decrypt_keys[i+4] = encrypt_keys.shift % USHORT
|
98
|
+
decrypt_keys[i+5] = encrypt_keys.shift % USHORT
|
99
|
+
decrypt_keys[i] = mulInv(encrypt_keys.shift)
|
100
|
+
if (i ==0)
|
101
|
+
decrypt_keys[1] = (-encrypt_keys.shift) % USHORT
|
102
|
+
decrypt_keys[2] = (-encrypt_keys.shift) % USHORT
|
103
|
+
else
|
104
|
+
decrypt_keys[i+2] = (-encrypt_keys.shift) % USHORT
|
105
|
+
decrypt_keys[i+1] = (-encrypt_keys.shift) % USHORT
|
106
|
+
end
|
107
|
+
decrypt_keys[i+3] = mulInv(encrypt_keys.shift)
|
108
|
+
}
|
109
|
+
return(decrypt_keys)
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
def crypt_pair(l, r)
|
114
|
+
word = [l, r].pack('NN').unpack('nnnn')
|
115
|
+
k = @subkeys[0..51]
|
116
|
+
8.downto(1) { |i|
|
117
|
+
word[0] = mul(word[0], k.shift)
|
118
|
+
word[1] = (word[1] + k.shift) % USHORT
|
119
|
+
word[2] = (word[2] + k.shift) % USHORT
|
120
|
+
word[3] = mul(word[3], k.shift)
|
121
|
+
t2 = word[0] ^ word[2]
|
122
|
+
t2 = mul(t2, k.shift)
|
123
|
+
t1 = (t2 + (word[1] ^ word[3])) % USHORT
|
124
|
+
t1 = mul(t1, k.shift)
|
125
|
+
t2 = (t1 + t2) % USHORT
|
126
|
+
word[0] ^= t1
|
127
|
+
word[3] ^= t2
|
128
|
+
t2 ^= word[1]
|
129
|
+
word[1] = word[2] ^ t1
|
130
|
+
word[2] = t2
|
131
|
+
}
|
132
|
+
result = []
|
133
|
+
result << mul(word[0], k.shift)
|
134
|
+
result << (word[2] + k.shift) % USHORT
|
135
|
+
result << (word[1] + k.shift) % USHORT
|
136
|
+
result << mul(word[3], k.shift)
|
137
|
+
twoLongs = result.pack('nnnn').unpack('NN')
|
138
|
+
return(twoLongs)
|
139
|
+
end
|
140
|
+
|
141
|
+
def encrypt_block(block)
|
142
|
+
xl, xr = block.unpack('NN')
|
143
|
+
xl, xr = crypt_pair(xl, xr)
|
144
|
+
encrypted = [xl, xr].pack('NN')
|
145
|
+
return(encrypted)
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
def decrypt_block(block)
|
150
|
+
xl, xr = block.unpack('NN')
|
151
|
+
xl, xr = crypt_pair(xl, xr)
|
152
|
+
decrypted = [xl, xr].pack('NN')
|
153
|
+
return(decrypted)
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# LICENSE INFORMATION
|
161
|
+
#
|
162
|
+
# This software product contains the IDEA algorithm as described and claimed in
|
163
|
+
# US patent 5,214,703, EPO patent 0482154 (covering Austria, France, Germany,
|
164
|
+
# Italy, the Netherlands, Spain, Sweden, Switzerland, and the UK), and Japanese
|
165
|
+
# patent application 508119/1991, "Device for the conversion of a digital block
|
166
|
+
# and use of same" (hereinafter referred to as "the algorithm"). Any use of
|
167
|
+
# the algorithm for commercial purposes is thus subject to a license from Ascom
|
168
|
+
# Systec Ltd. of CH-5506 Maegenwil (Switzerland), being the patentee and sole
|
169
|
+
# owner of all rights, including the trademark IDEA.
|
170
|
+
#
|
171
|
+
# Commercial purposes shall mean any revenue generating purpose including but
|
172
|
+
# not limited to:
|
173
|
+
#
|
174
|
+
# i) Using the algorithm for company internal purposes (subject to a site
|
175
|
+
# license).
|
176
|
+
#
|
177
|
+
# ii) Incorporating the algorithm into any software and distributing such
|
178
|
+
# software and/or providing services relating thereto to others (subject to
|
179
|
+
# a product license).
|
180
|
+
#
|
181
|
+
# iii) Using a product containing the algorithm not covered by an IDEA license
|
182
|
+
# (subject to an end user license).
|
183
|
+
#
|
184
|
+
# All such end user license agreements are available exclusively from Ascom
|
185
|
+
# Systec Ltd and may be requested via the WWW at http://www.ascom.ch/systec or
|
186
|
+
# by email to idea@ascom.ch.
|
187
|
+
#
|
188
|
+
# Use other than for commercial purposes is strictly limited to non-revenue
|
189
|
+
# generating data transfer between private individuals. The use by government
|
190
|
+
# agencies, non-profit organizations, etc is considered as use for commercial
|
191
|
+
# purposes but may be subject to special conditions. Any misuse will be
|
192
|
+
# prosecuted.
|
193
|
+
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# crypt/rattle.rb Richard Kernahan <kernighan_rich@rubyforge.org>
|
2
|
+
|
3
|
+
# add_noise - take a message and intersperse noise to make a new noisy message of given byte-length
|
4
|
+
# remove_noise - take a noisy message and extract the message
|
5
|
+
|
6
|
+
module Crypt
|
7
|
+
module Noise
|
8
|
+
|
9
|
+
def add_noise(newLength)
|
10
|
+
message = self
|
11
|
+
usableNoisyMessageLength = newLength / 9 * 8
|
12
|
+
bitmapSize = newLength / 9
|
13
|
+
remainingBytes = newLength - usableNoisyMessageLength - bitmapSize
|
14
|
+
if (message.length > usableNoisyMessageLength)
|
15
|
+
minimumNewLength = (message.length / 8.0).ceil * 9
|
16
|
+
puts "For a clear text of #{message.length} bytes, the minimum obscured length"
|
17
|
+
puts "is #{minimumNewLength} bytes which allows for no noise in the message."
|
18
|
+
puts "You should choose an obscured length of at least double the clear text"
|
19
|
+
puts "length, such as #{message.length / 8 * 32} bytes"
|
20
|
+
raise "Insufficient length for noisy message"
|
21
|
+
end
|
22
|
+
bitmap = []
|
23
|
+
usableNoisyMessageLength.times { bitmap << false }
|
24
|
+
srand(Time.now.to_i)
|
25
|
+
positionsSelected = 0
|
26
|
+
while (positionsSelected < message.length)
|
27
|
+
positionTaken = rand(usableNoisyMessageLength)
|
28
|
+
if bitmap[positionTaken]
|
29
|
+
next
|
30
|
+
else
|
31
|
+
bitmap[positionTaken] = true
|
32
|
+
positionsSelected = positionsSelected.next
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
noisyMessage = ""
|
37
|
+
0.upto(bitmapSize-1) { |byte|
|
38
|
+
c = 0
|
39
|
+
0.upto(7) { |bit|
|
40
|
+
c = c + (1<<bit) if bitmap[byte * 8 + bit]
|
41
|
+
}
|
42
|
+
noisyMessage << c.chr
|
43
|
+
}
|
44
|
+
posInMessage = 0
|
45
|
+
0.upto(usableNoisyMessageLength-1) { |pos|
|
46
|
+
if bitmap[pos]
|
47
|
+
meaningfulByte = message[posInMessage]
|
48
|
+
noisyMessage << meaningfulByte
|
49
|
+
posInMessage = posInMessage.next
|
50
|
+
else
|
51
|
+
noiseByte = rand(256).chr
|
52
|
+
noisyMessage << noiseByte
|
53
|
+
end
|
54
|
+
}
|
55
|
+
remainingBytes.times {
|
56
|
+
noiseByte = rand(256).chr
|
57
|
+
noisyMessage << noiseByte
|
58
|
+
}
|
59
|
+
return(noisyMessage)
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def remove_noise
|
64
|
+
noisyMessage = self
|
65
|
+
bitmapSize = noisyMessage.length / 9
|
66
|
+
actualMessageLength = bitmapSize * 8
|
67
|
+
|
68
|
+
actualMessageStart = bitmapSize
|
69
|
+
actualMessageFinish = bitmapSize + actualMessageLength - 1
|
70
|
+
actualMessage = noisyMessage[actualMessageStart..actualMessageFinish]
|
71
|
+
|
72
|
+
bitmap = []
|
73
|
+
0.upto(bitmapSize - 1) { |byte|
|
74
|
+
c = noisyMessage[byte]
|
75
|
+
0.upto(7) { |bit|
|
76
|
+
bitmap[byte * 8 + bit] = (c[bit] == 1)
|
77
|
+
}
|
78
|
+
}
|
79
|
+
clearMessage = ""
|
80
|
+
0.upto(actualMessageLength) { |pos|
|
81
|
+
meaningful = bitmap[pos]
|
82
|
+
if meaningful
|
83
|
+
clearMessage << actualMessage[pos]
|
84
|
+
end
|
85
|
+
}
|
86
|
+
return(clearMessage)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class String
|
93
|
+
include Crypt::Noise
|
94
|
+
end
|