bicrypt 1.0.0 → 1.1.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.
- data/LICENSE +205 -674
- data/README.rdoc +19 -7
- data/lib/bicrypt.rb +182 -164
- data/meta/package +8 -1
- data/meta/profile +21 -0
- data/qed/01_example.rb +57 -0
- data/qed/applique/setup.rb +10 -0
- metadata +59 -29
- data/MANIFEST +0 -18
- data/meta/authors +0 -1
- data/meta/created +0 -1
- data/meta/description +0 -1
- data/meta/homepage +0 -1
- data/meta/license +0 -1
- data/meta/released +0 -1
- data/meta/repository +0 -1
- data/meta/summary +0 -1
- data/meta/version +0 -1
data/README.rdoc
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
= BiCrypt
|
2
2
|
|
3
|
-
|
3
|
+
* docs: http://rubydoc.info/gems/bicrypt
|
4
|
+
* code: http://rubyworks.github.com/bicrypt
|
4
5
|
|
5
6
|
|
6
7
|
== DESCRIPTION
|
@@ -10,17 +11,18 @@ BiCrypt is a simple two-way encryption class.
|
|
10
11
|
|
11
12
|
== FEATURES/ISSUES
|
12
13
|
|
13
|
-
*
|
14
|
+
* Simple to use.
|
15
|
+
* Good for light-weight "deterence" applications.
|
14
16
|
|
15
17
|
|
16
18
|
== RELEASE NOTES
|
17
19
|
|
18
|
-
Please see
|
20
|
+
Please see HISTORY.rdoc file.
|
19
21
|
|
20
22
|
|
21
|
-
==
|
23
|
+
== USAGE
|
22
24
|
|
23
|
-
|
25
|
+
See QED example[qed/01_example] document.
|
24
26
|
|
25
27
|
|
26
28
|
== HOW TO INSTALL
|
@@ -43,9 +45,19 @@ Windows users use 'ruby setup.rb all'.
|
|
43
45
|
|
44
46
|
== COPYING
|
45
47
|
|
46
|
-
Copyright (c) 2007
|
48
|
+
Copyright (c) 2007 Thomas Sawyer
|
47
49
|
|
48
|
-
|
50
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
51
|
+
you may not use this file except in compliance with the License.
|
52
|
+
You may obtain a copy of the License at
|
53
|
+
|
54
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
55
|
+
|
56
|
+
Unless required by applicable law or agreed to in writing, software
|
57
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
58
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
59
|
+
See the License for the specific language governing permissions and
|
60
|
+
limitations under the License.
|
49
61
|
|
50
62
|
See LICENSE file for details.
|
51
63
|
|
data/lib/bicrypt.rb
CHANGED
@@ -1,23 +1,18 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
# A simple two-way encryption class.
|
4
|
-
#
|
5
|
-
# == Authors
|
6
|
-
#
|
7
|
-
# * Trans
|
8
|
-
#
|
9
|
-
# == Copying
|
1
|
+
# BiCrypt - A Simple Two-Way Encryption Class
|
10
2
|
#
|
11
3
|
# Copyright (c) 2007 Trans
|
12
4
|
#
|
13
|
-
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
14
8
|
#
|
15
|
-
#
|
16
|
-
# software under the same terms as Ruby.
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
17
10
|
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
21
16
|
|
22
17
|
require 'stringio'
|
23
18
|
|
@@ -25,145 +20,64 @@ require 'stringio'
|
|
25
20
|
#
|
26
21
|
# A simple two-way encryption class.
|
27
22
|
#
|
23
|
+
# This class is based on algorithms given in Applied Cryptography 2nd Ed.
|
24
|
+
#
|
25
|
+
# If subclassed, the new encryption class must provide three methods:
|
26
|
+
#
|
27
|
+
# * encrypt_block(block)
|
28
|
+
# * decrypt_block(block)
|
29
|
+
# * block_size()
|
30
|
+
#
|
28
31
|
class BiCrypt
|
29
32
|
|
30
33
|
ULONG = 0x100000000
|
31
34
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
+
# These are the S-boxes given in Applied Cryptography 2nd Ed., p. 333
|
36
|
+
SBOX = [
|
37
|
+
[4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3],
|
38
|
+
[14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9],
|
39
|
+
[5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11],
|
40
|
+
[7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3],
|
41
|
+
[6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2],
|
42
|
+
[4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14],
|
43
|
+
[13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12],
|
44
|
+
[1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]
|
45
|
+
]
|
46
|
+
|
47
|
+
# These are the S-boxes given in the GOST source code listing in Applied
|
48
|
+
# Cryptography 2nd Ed., p. 644. They appear to be from the DES S-boxes
|
49
|
+
# [13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 ],
|
50
|
+
# [ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 ],
|
51
|
+
# [12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 ],
|
52
|
+
# [ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 ],
|
53
|
+
# [ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 ],
|
54
|
+
# [10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 ],
|
55
|
+
# [15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 ],
|
56
|
+
# [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 ]
|
35
57
|
|
58
|
+
#
|
36
59
|
def initialize(userKey)
|
60
|
+
@sBox = SBOX
|
61
|
+
|
62
|
+
if userKey.size < 8
|
63
|
+
userKey += '01234567'
|
64
|
+
end
|
37
65
|
|
38
|
-
|
39
|
-
@sBox = [
|
40
|
-
[4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3],
|
41
|
-
[14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9],
|
42
|
-
[5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11],
|
43
|
-
[7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3],
|
44
|
-
[6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2],
|
45
|
-
[4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14],
|
46
|
-
[13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12],
|
47
|
-
[1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]
|
48
|
-
]
|
49
|
-
|
50
|
-
# These are the S-boxes given in the GOST source code listing in Applied
|
51
|
-
# Cryptography 2nd Ed., p. 644. They appear to be from the DES S-boxes
|
52
|
-
# [13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 ],
|
53
|
-
# [ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 ],
|
54
|
-
# [12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 ],
|
55
|
-
# [ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 ],
|
56
|
-
# [ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 ],
|
57
|
-
# [10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 ],
|
58
|
-
# [15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 ],
|
59
|
-
# [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 ]
|
60
|
-
|
61
|
-
# precalculate the S table
|
62
|
-
@sTable = precalculate_S_table()
|
66
|
+
#@sTable = precalculate_s_table()
|
63
67
|
|
64
68
|
# derive the 32-byte key from the user-supplied key
|
65
69
|
userKeyLength = userKey.length
|
70
|
+
|
66
71
|
@key = userKey[0..31].unpack('C'*32)
|
72
|
+
|
67
73
|
if (userKeyLength < 32)
|
68
74
|
userKeyLength.upto(31) { @key << 0 }
|
69
75
|
end
|
70
76
|
end
|
71
77
|
|
78
|
+
public
|
72
79
|
|
73
|
-
|
74
|
-
sTable = [[], [], [], []]
|
75
|
-
0.upto(3) { |i|
|
76
|
-
0.upto(255) { |j|
|
77
|
-
t = @sBox[2*i][j % 16] | (@sBox[2*i+1][j/16] << 4)
|
78
|
-
u = (8*i + 11) % 32
|
79
|
-
v = (t << u) | (t >> (32-u))
|
80
|
-
sTable[i][j] = (v % ULONG)
|
81
|
-
}
|
82
|
-
}
|
83
|
-
return(sTable)
|
84
|
-
end
|
85
|
-
|
86
|
-
|
87
|
-
def f(longWord)
|
88
|
-
longWord = longWord % ULONG
|
89
|
-
a, b, c, d = [longWord].pack('L').unpack('CCCC')
|
90
|
-
return(@sTable[3][d] ^ @sTable[2][c] ^ @sTable[1][b] ^ @sTable[0][a])
|
91
|
-
end
|
92
|
-
|
93
|
-
def encrypt_pair(xl, xr)
|
94
|
-
3.times {
|
95
|
-
xr ^= f(xl+@key[0])
|
96
|
-
xl ^= f(xr+@key[1])
|
97
|
-
xr ^= f(xl+@key[2])
|
98
|
-
xl ^= f(xr+@key[3])
|
99
|
-
xr ^= f(xl+@key[4])
|
100
|
-
xl ^= f(xr+@key[5])
|
101
|
-
xr ^= f(xl+@key[6])
|
102
|
-
xl ^= f(xr+@key[7])
|
103
|
-
}
|
104
|
-
xr ^= f(xl+@key[7])
|
105
|
-
xl ^= f(xr+@key[6])
|
106
|
-
xr ^= f(xl+@key[5])
|
107
|
-
xl ^= f(xr+@key[4])
|
108
|
-
xr ^= f(xl+@key[3])
|
109
|
-
xl ^= f(xr+@key[2])
|
110
|
-
xr ^= f(xl+@key[1])
|
111
|
-
xl ^= f(xr+@key[0])
|
112
|
-
return([xr, xl])
|
113
|
-
end
|
114
|
-
|
115
|
-
|
116
|
-
def decrypt_pair(xl, xr)
|
117
|
-
xr ^= f(xl+@key[0])
|
118
|
-
xl ^= f(xr+@key[1])
|
119
|
-
xr ^= f(xl+@key[2])
|
120
|
-
xl ^= f(xr+@key[3])
|
121
|
-
xr ^= f(xl+@key[4])
|
122
|
-
xl ^= f(xr+@key[5])
|
123
|
-
xr ^= f(xl+@key[6])
|
124
|
-
xl ^= f(xr+@key[7])
|
125
|
-
3.times {
|
126
|
-
xr ^= f(xl+@key[7])
|
127
|
-
xl ^= f(xr+@key[6])
|
128
|
-
xr ^= f(xl+@key[5])
|
129
|
-
xl ^= f(xr+@key[4])
|
130
|
-
xr ^= f(xl+@key[3])
|
131
|
-
xl ^= f(xr+@key[2])
|
132
|
-
xr ^= f(xl+@key[1])
|
133
|
-
xl ^= f(xr+@key[0])
|
134
|
-
}
|
135
|
-
return([xr, xl])
|
136
|
-
end
|
137
|
-
|
138
|
-
def encrypt_block(block)
|
139
|
-
xl, xr = block.unpack('NN')
|
140
|
-
xl, xr = encrypt_pair(xl, xr)
|
141
|
-
encrypted = [xl, xr].pack('NN')
|
142
|
-
return(encrypted)
|
143
|
-
end
|
144
|
-
|
145
|
-
|
146
|
-
def decrypt_block(block)
|
147
|
-
xl, xr = block.unpack('NN')
|
148
|
-
xl, xr = decrypt_pair(xl, xr)
|
149
|
-
decrypted = [xl, xr].pack('NN')
|
150
|
-
return(decrypted)
|
151
|
-
end
|
152
|
-
|
153
|
-
# When this module is mixed in with an encryption class, the class
|
154
|
-
# must provide three methods: encrypt_block(block) and decrypt_block(block)
|
155
|
-
# and block_size()
|
156
|
-
|
157
|
-
def generate_initialization_vector(words)
|
158
|
-
srand(Time.now.to_i)
|
159
|
-
vector = ""
|
160
|
-
words.times {
|
161
|
-
vector << [rand(ULONG)].pack('N')
|
162
|
-
}
|
163
|
-
return(vector)
|
164
|
-
end
|
165
|
-
|
166
|
-
|
80
|
+
# Encrypt an IO stream.
|
167
81
|
def encrypt_stream(plainStream, cryptStream)
|
168
82
|
# Cypher-block-chain mode
|
169
83
|
|
@@ -172,7 +86,7 @@ class BiCrypt
|
|
172
86
|
cryptStream.write(chain)
|
173
87
|
|
174
88
|
while ((block = plainStream.read(block_size())) && (block.length == block_size()))
|
175
|
-
block = block
|
89
|
+
block = xor(block, chain)
|
176
90
|
encrypted = encrypt_block(block)
|
177
91
|
cryptStream.write(encrypted)
|
178
92
|
chain = encrypted
|
@@ -189,19 +103,19 @@ class BiCrypt
|
|
189
103
|
remainingMessageBytes.upto(block_size()-2) { buffer << rand(128).chr }
|
190
104
|
buffer << remainingMessageBytes.chr
|
191
105
|
block = buffer.join('')
|
192
|
-
block = block
|
106
|
+
block = xor(block, chain)
|
193
107
|
encrypted = encrypt_block(block)
|
194
108
|
cryptStream.write(encrypted)
|
195
109
|
end
|
196
110
|
|
197
|
-
|
111
|
+
# Decrypt an encrypted IO stream.
|
198
112
|
def decrypt_stream(cryptStream, plainStream)
|
199
113
|
# Cypher-block-chain mode
|
200
114
|
chain = cryptStream.read(block_size())
|
201
115
|
|
202
116
|
while (block = cryptStream.read(block_size()))
|
203
117
|
decrypted = decrypt_block(block)
|
204
|
-
plainText = decrypted
|
118
|
+
plainText = xor(decrypted, chain)
|
205
119
|
plainStream.write(plainText) unless cryptStream.eof?
|
206
120
|
chain = block
|
207
121
|
end
|
@@ -212,19 +126,7 @@ class BiCrypt
|
|
212
126
|
remainingMessageBytes.times { plainStream.write(buffer.shift) }
|
213
127
|
end
|
214
128
|
|
215
|
-
|
216
|
-
def carefully_open_file(filename, mode)
|
217
|
-
begin
|
218
|
-
aFile = File.new(filename, mode)
|
219
|
-
rescue
|
220
|
-
puts "Sorry. There was a problem opening the file <#{filename}>."
|
221
|
-
aFile.close() unless aFile.nil?
|
222
|
-
raise
|
223
|
-
end
|
224
|
-
return(aFile)
|
225
|
-
end
|
226
|
-
|
227
|
-
|
129
|
+
# Encrypt a file.
|
228
130
|
def encrypt_file(plainFilename, cryptFilename)
|
229
131
|
plainFile = carefully_open_file(plainFilename, 'rb')
|
230
132
|
cryptFile = carefully_open_file(cryptFilename, 'wb+')
|
@@ -233,7 +135,7 @@ class BiCrypt
|
|
233
135
|
cryptFile.close unless cryptFile.closed?
|
234
136
|
end
|
235
137
|
|
236
|
-
|
138
|
+
# Decrypt an encrypted file.
|
237
139
|
def decrypt_file(cryptFilename, plainFilename)
|
238
140
|
cryptFile = carefully_open_file(cryptFilename, 'rb')
|
239
141
|
plainFile = carefully_open_file(plainFilename, 'wb+')
|
@@ -242,7 +144,7 @@ class BiCrypt
|
|
242
144
|
plainFile.close unless plainFile.closed?
|
243
145
|
end
|
244
146
|
|
245
|
-
|
147
|
+
# Encrypt a string.
|
246
148
|
def encrypt_string(plainText)
|
247
149
|
plainStream = StringIO.new(plainText)
|
248
150
|
cryptStream = StringIO.new('')
|
@@ -251,7 +153,7 @@ class BiCrypt
|
|
251
153
|
return(cryptText)
|
252
154
|
end
|
253
155
|
|
254
|
-
|
156
|
+
# Decrypt an encrypted string.
|
255
157
|
def decrypt_string(cryptText)
|
256
158
|
cryptStream = StringIO.new(cryptText)
|
257
159
|
plainStream = StringIO.new('')
|
@@ -260,10 +162,122 @@ class BiCrypt
|
|
260
162
|
return(plainText)
|
261
163
|
end
|
262
164
|
|
263
|
-
|
165
|
+
private
|
166
|
+
|
167
|
+
# S-boxes.
|
168
|
+
attr :sBox
|
169
|
+
|
170
|
+
# Calculated S-boxes
|
171
|
+
def sTable
|
172
|
+
@sTable ||= (
|
173
|
+
sTable = [[], [], [], []]
|
174
|
+
0.upto(3) { |i|
|
175
|
+
0.upto(255) { |j|
|
176
|
+
t = sBox[2*i][j % 16] | (sBox[2*i+1][j/16] << 4)
|
177
|
+
u = (8*i + 11) % 32
|
178
|
+
v = (t << u) | (t >> (32-u))
|
179
|
+
sTable[i][j] = (v % ULONG)
|
180
|
+
}
|
181
|
+
}
|
182
|
+
sTable
|
183
|
+
)
|
184
|
+
end
|
264
185
|
|
186
|
+
#
|
187
|
+
def encrypt_block(block)
|
188
|
+
xl, xr = block.unpack('NN')
|
189
|
+
xl, xr = encrypt_pair(xl, xr)
|
190
|
+
encrypted = [xl, xr].pack('NN')
|
191
|
+
return(encrypted)
|
192
|
+
end
|
265
193
|
|
266
|
-
|
194
|
+
#
|
195
|
+
def decrypt_block(block)
|
196
|
+
xl, xr = block.unpack('NN')
|
197
|
+
xl, xr = decrypt_pair(xl, xr)
|
198
|
+
decrypted = [xl, xr].pack('NN')
|
199
|
+
return(decrypted)
|
200
|
+
end
|
201
|
+
|
202
|
+
#
|
203
|
+
def block_size
|
204
|
+
8
|
205
|
+
end
|
206
|
+
|
207
|
+
#
|
208
|
+
def encrypt_pair(xl, xr)
|
209
|
+
3.times {
|
210
|
+
xr ^= f(xl+@key[0])
|
211
|
+
xl ^= f(xr+@key[1])
|
212
|
+
xr ^= f(xl+@key[2])
|
213
|
+
xl ^= f(xr+@key[3])
|
214
|
+
xr ^= f(xl+@key[4])
|
215
|
+
xl ^= f(xr+@key[5])
|
216
|
+
xr ^= f(xl+@key[6])
|
217
|
+
xl ^= f(xr+@key[7])
|
218
|
+
}
|
219
|
+
xr ^= f(xl+@key[7])
|
220
|
+
xl ^= f(xr+@key[6])
|
221
|
+
xr ^= f(xl+@key[5])
|
222
|
+
xl ^= f(xr+@key[4])
|
223
|
+
xr ^= f(xl+@key[3])
|
224
|
+
xl ^= f(xr+@key[2])
|
225
|
+
xr ^= f(xl+@key[1])
|
226
|
+
xl ^= f(xr+@key[0])
|
227
|
+
return([xr, xl])
|
228
|
+
end
|
229
|
+
|
230
|
+
#
|
231
|
+
def decrypt_pair(xl, xr)
|
232
|
+
xr ^= f(xl+@key[0])
|
233
|
+
xl ^= f(xr+@key[1])
|
234
|
+
xr ^= f(xl+@key[2])
|
235
|
+
xl ^= f(xr+@key[3])
|
236
|
+
xr ^= f(xl+@key[4])
|
237
|
+
xl ^= f(xr+@key[5])
|
238
|
+
xr ^= f(xl+@key[6])
|
239
|
+
xl ^= f(xr+@key[7])
|
240
|
+
3.times {
|
241
|
+
xr ^= f(xl+@key[7])
|
242
|
+
xl ^= f(xr+@key[6])
|
243
|
+
xr ^= f(xl+@key[5])
|
244
|
+
xl ^= f(xr+@key[4])
|
245
|
+
xr ^= f(xl+@key[3])
|
246
|
+
xl ^= f(xr+@key[2])
|
247
|
+
xr ^= f(xl+@key[1])
|
248
|
+
xl ^= f(xr+@key[0])
|
249
|
+
}
|
250
|
+
return([xr, xl])
|
251
|
+
end
|
252
|
+
|
253
|
+
#
|
254
|
+
def f(longWord)
|
255
|
+
longWord = longWord % ULONG
|
256
|
+
a, b, c, d = [longWord].pack('L').unpack('CCCC')
|
257
|
+
return(sTable[3][d] ^ sTable[2][c] ^ sTable[1][b] ^ sTable[0][a])
|
258
|
+
end
|
259
|
+
|
260
|
+
#
|
261
|
+
def generate_initialization_vector(words)
|
262
|
+
srand(Time.now.to_i)
|
263
|
+
vector = ""
|
264
|
+
words.times {
|
265
|
+
vector << [rand(ULONG)].pack('N')
|
266
|
+
}
|
267
|
+
return(vector)
|
268
|
+
end
|
269
|
+
|
270
|
+
#
|
271
|
+
def carefully_open_file(filename, mode)
|
272
|
+
begin
|
273
|
+
aFile = File.new(filename, mode)
|
274
|
+
rescue
|
275
|
+
puts "Sorry. There was a problem opening the file <#{filename}>."
|
276
|
+
aFile.close() unless aFile.nil?
|
277
|
+
raise
|
278
|
+
end
|
279
|
+
return(aFile)
|
280
|
+
end
|
267
281
|
|
268
282
|
# Binary XOR of two strings.
|
269
283
|
#
|
@@ -275,17 +289,21 @@ class String
|
|
275
289
|
# "\000\001\001\000"
|
276
290
|
# "\003\002\001"
|
277
291
|
#
|
278
|
-
|
279
|
-
|
280
|
-
|
292
|
+
#--
|
293
|
+
# NOTE: This used to be a String#^ extension in v1.0. So if
|
294
|
+
# an uncaught bug should arise check this first.
|
295
|
+
#++
|
296
|
+
def xor(str1, str2)
|
297
|
+
a = str1.unpack('C'*(str1.length)) #.bytes.to_a
|
298
|
+
b = str2.unpack('C'*(str2.length)) #.bytes.to_a
|
281
299
|
if (b.length < a.length)
|
282
300
|
(a.length - b.length).times { b << 0 }
|
283
301
|
end
|
284
302
|
xor = ""
|
285
|
-
0.upto(a.length-1)
|
303
|
+
0.upto(a.length - 1) do |pos|
|
286
304
|
x = a[pos] ^ b[pos]
|
287
305
|
xor << x.chr()
|
288
|
-
|
306
|
+
end
|
289
307
|
return(xor)
|
290
308
|
end
|
291
309
|
|