crypt 1.1.3 → 2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CREDITS +13 -0
- data/LICENSE +6 -0
- data/README +10 -0
- data/{crypt → lib/crypt}/blowfish-tables.rb +59 -3
- data/{crypt → lib/crypt}/blowfish.rb +27 -26
- data/{crypt → lib/crypt}/cbc.rb +33 -35
- data/{crypt → lib/crypt}/gost.rb +3 -4
- data/{crypt → lib/crypt}/idea.rb +25 -68
- data/{crypt → lib/crypt}/noise.rb +12 -12
- data/{crypt → lib/crypt}/rijndael-tables.rb +2 -3
- data/{crypt → lib/crypt}/rijndael.rb +57 -53
- data/lib/crypt/stringxor.rb +17 -0
- data/specs/blowfish.rb +80 -0
- data/specs/gost.rb +48 -0
- data/specs/idea.rb +156 -0
- data/specs/rijndael.rb +58 -0
- metadata +57 -42
- data/crypt/stringxor.rb +0 -27
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 07de2fdabf4cc3650b826ccac32ac579233f4af0
|
4
|
+
data.tar.gz: de13a85d6748f2a22fb8bdc52db8d1ae976f4242
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4690385b4b75cb6b991fa28ba778680efc3593af479be399ce2792f5d0ab7035fb7bf38ee3d2be443f34b1b545ac5e01a04f3a99d165d4f3d1c359be7e2c09e8
|
7
|
+
data.tar.gz: 63a59b1f09d8d8cd298f936960b4a7cca07e71a343a7a1f89342fec3f3cb452af7f14394292e12789f39ba65d4ac9aca78a9e8084da5bc87e449471c0dfbeb43
|
data/CREDITS
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# CREDITS
|
2
|
+
|
3
|
+
The Blowfish code was adapted from Bruce Schneier's reference C code
|
4
|
+
(http://www.schneier.com/blowfish-download.html)
|
5
|
+
|
6
|
+
The GOST code was adapted from Wei Dai's C++ code from the Crypto++ project
|
7
|
+
(http://sourceforge.net/projects/cryptopp).
|
8
|
+
|
9
|
+
The IDEA code was based on the reference C implementation once published by MediaCrypt
|
10
|
+
(http://web.archive.org/web/20000816173624/www.ascom.ch/infosec/downloads.html)
|
11
|
+
|
12
|
+
The Rijndael code was adapted from the reference ANSI C code by Paulo Barreto and Vincent Rijmen.
|
13
|
+
(http://www.esat.kuleuven.ac.be/~rijmen/rijndael/rijndael-fst-3.0.zip)
|
data/LICENSE
ADDED
data/README
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# README
|
2
|
+
|
3
|
+
The Crypt library is a pure-ruby implementation of a number of popular
|
4
|
+
encryption algorithms. Block cyphers currently include Blowfish, GOST, IDEA,
|
5
|
+
and Rijndael (AES). Cypher Block Chaining (CBC) has been implemented.
|
6
|
+
|
7
|
+
Crypt is written entirely in ruby so deployment is simple - no platform
|
8
|
+
concerns, no library dependencies, nothing to compile.
|
9
|
+
|
10
|
+
This work is placed in the public domain.
|
@@ -1,5 +1,61 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
#The Crypt library is a pure-ruby implementation of a number of popular encryption algorithms.
|
2
|
+
#Block cyphers currently available include Blowfish, GOST, IDEA, and Rijndael (AES).
|
3
|
+
#Cypher Block Chaining (CBC) has been implemented.
|
4
|
+
#
|
5
|
+
#Crypt is written entirely in ruby so deployment is simple - no platform concerns,
|
6
|
+
#no library dependencies, nothing to compile.
|
7
|
+
#
|
8
|
+
#Performance is what you would expect from a pure-ruby implementation: it is adequate for shorter messages
|
9
|
+
#but I wouldn't try to encrypt my whole disk with it. If performance is critical then you might want to try
|
10
|
+
#ezcrypto's (http://ezcrypto.rubyforge.org) interface to OpenSSL.
|
11
|
+
#
|
12
|
+
#v.2.2.0 released 23 Sep 2015 fixes a defect in IDEA and replaces tests with specs.
|
13
|
+
#
|
14
|
+
# require 'crypt/blowfish'
|
15
|
+
# blowfish = Crypt::Blowfish.new("A key up to 56 bytes long")
|
16
|
+
# plainBlock = "ABCD1234"
|
17
|
+
# encryptedBlock = blowfish.encrypt_block(plainBlock)
|
18
|
+
# decryptedBlock = blowfish.decrypt_block(encryptedBlock)
|
19
|
+
# string = "This is a string which is not a multiple of 8 characters long"
|
20
|
+
# encryptedString = bf.encrypt_string(string)
|
21
|
+
# decryptedString = bf.decrypt_string(encryptedString)
|
22
|
+
# bf.encrypt_file('plain.txt', 'crypt.txt')
|
23
|
+
# bf.decrypt_file('crypt.txt', 'decrypt.txt')
|
24
|
+
#
|
25
|
+
# require 'crypt/gost'
|
26
|
+
# # a key shorter than 32 bytes will be padded out with zeroes
|
27
|
+
# gost = Crypt::Gost.new("This is a contrived 32 byte key!")
|
28
|
+
# plainBlock = "ABCD1234"
|
29
|
+
# encryptedBlock = gost.encrypt_block(plainBlock)
|
30
|
+
# decryptedBlock = gost.decrypt_block(encryptedBlock)
|
31
|
+
#
|
32
|
+
# require 'crypt/idea'
|
33
|
+
# idea = Crypt::IDEA.new("A key up to 56 bytes long")
|
34
|
+
# plainBlock = "ABCD1234"
|
35
|
+
# encryptedBlock = idea.encrypt_block(plainBlock)
|
36
|
+
# decryptedBlock = idea.decrypt_block(encryptedBlock)
|
37
|
+
#
|
38
|
+
# require 'crypt/rijndael'
|
39
|
+
# rijndael = Crypt::Rijndael.new("A key 16, 24, or 32 bytes length")
|
40
|
+
# plainBlock = "ABCDEFGH12345678"
|
41
|
+
# encryptedBlock = rijndael.encrypt_block(plainBlock)
|
42
|
+
# decryptedBlock = rijndael.decrypt_block(encryptedBlock)
|
43
|
+
#
|
44
|
+
#Cipher-block chaining (CBC) is supported for each algorithm:
|
45
|
+
#
|
46
|
+
# blowfish = Crypt::Blowfish.new("A sample key better than this one")
|
47
|
+
# blowfish.encrypt_file('plain.txt', 'crypt.txt')
|
48
|
+
# blowfish.decrypt_file('crypt.txt', 'plain.txt')
|
49
|
+
#
|
50
|
+
#You can also read from a plain text stream,
|
51
|
+
#encrypt and write to an encrypted output stream, or treat a string as a stream:
|
52
|
+
#
|
53
|
+
# f = File.new('plain.txt', 'r')
|
54
|
+
# g = TCPSocket.new('encrypted.example.com', 2222)
|
55
|
+
# blowfish.encrypt_stream(f, g)
|
56
|
+
#
|
57
|
+
# plainText = "This is plain text."
|
58
|
+
# encrypted = blowfish.encrypt_string(plainText)
|
3
59
|
module Crypt
|
4
60
|
module BlowfishTables
|
5
61
|
|
@@ -187,4 +243,4 @@ module BlowfishTables
|
|
187
243
|
|
188
244
|
|
189
245
|
end
|
190
|
-
end
|
246
|
+
end
|
@@ -1,24 +1,18 @@
|
|
1
|
-
|
1
|
+
module Crypt
|
2
|
+
# blowfish.rb Richard Kernahan
|
2
3
|
#
|
3
4
|
# Blowfish algorithm by Bruce Schneider
|
4
5
|
# Ported by Richard Kernahan from the reference C code
|
5
|
-
|
6
|
-
module Crypt
|
7
6
|
class Blowfish
|
8
|
-
|
7
|
+
|
9
8
|
require 'crypt/cbc'
|
10
9
|
include Crypt::CBC
|
11
|
-
|
10
|
+
|
12
11
|
require 'crypt/blowfish-tables'
|
13
12
|
include Crypt::BlowfishTables
|
14
|
-
|
13
|
+
|
15
14
|
ULONG = 0x100000000
|
16
|
-
|
17
|
-
def block_size
|
18
|
-
return(8)
|
19
|
-
end
|
20
|
-
|
21
|
-
|
15
|
+
|
22
16
|
def initialize(key)
|
23
17
|
@key = key
|
24
18
|
raise "Bad key length: the key must be 1-56 bytes." unless (key.length.between?(1,56))
|
@@ -26,8 +20,11 @@ class Blowfish
|
|
26
20
|
@sBoxes = []
|
27
21
|
setup_blowfish()
|
28
22
|
end
|
29
|
-
|
30
|
-
|
23
|
+
|
24
|
+
def block_size()
|
25
|
+
8
|
26
|
+
end
|
27
|
+
|
31
28
|
def f(x)
|
32
29
|
a, b, c, d = [x].pack('N').unpack('CCCC')
|
33
30
|
y = (@sBoxes[0][a] + @sBoxes[1][b]) % ULONG
|
@@ -35,8 +32,8 @@ class Blowfish
|
|
35
32
|
y = (y + @sBoxes[3][d]) % ULONG
|
36
33
|
return(y)
|
37
34
|
end
|
38
|
-
|
39
|
-
|
35
|
+
|
36
|
+
|
40
37
|
def setup_blowfish()
|
41
38
|
@sBoxes = Array.new(4) { |i| INITIALSBOXES[i].clone }
|
42
39
|
@pArray = INITIALPARRAY.clone
|
@@ -44,7 +41,8 @@ class Blowfish
|
|
44
41
|
0.upto(17) { |i|
|
45
42
|
data = 0
|
46
43
|
4.times {
|
47
|
-
|
44
|
+
k = @key[keypos].ord() # ruby 2.0
|
45
|
+
data = ((data << 8) | k) % ULONG
|
48
46
|
keypos = (keypos.next) % @key.length
|
49
47
|
}
|
50
48
|
@pArray[i] = (@pArray[i] ^ data) % ULONG
|
@@ -64,7 +62,7 @@ class Blowfish
|
|
64
62
|
}
|
65
63
|
}
|
66
64
|
end
|
67
|
-
|
65
|
+
|
68
66
|
def encrypt_pair(xl, xr)
|
69
67
|
0.upto(15) { |i|
|
70
68
|
xl = (xl ^ @pArray[i]) % ULONG
|
@@ -76,8 +74,8 @@ class Blowfish
|
|
76
74
|
xl = (xl ^ @pArray[17]) % ULONG
|
77
75
|
return([xl, xr])
|
78
76
|
end
|
79
|
-
|
80
|
-
|
77
|
+
|
78
|
+
|
81
79
|
def decrypt_pair(xl, xr)
|
82
80
|
17.downto(2) { |i|
|
83
81
|
xl = (xl ^ @pArray[i]) % ULONG
|
@@ -89,22 +87,25 @@ class Blowfish
|
|
89
87
|
xl = (xl ^ @pArray[0]) % ULONG
|
90
88
|
return([xl, xr])
|
91
89
|
end
|
92
|
-
|
93
|
-
|
90
|
+
|
91
|
+
|
94
92
|
def encrypt_block(block)
|
93
|
+
block = block.force_encoding("ASCII-8BIT") # to treat unicode characters as two bytes
|
94
|
+
raise "block must be #{block_size()} bytes long" if (block.length() != block_size())
|
95
95
|
xl, xr = block.unpack('NN')
|
96
96
|
xl, xr = encrypt_pair(xl, xr)
|
97
97
|
encrypted = [xl, xr].pack('NN')
|
98
98
|
return(encrypted)
|
99
99
|
end
|
100
|
-
|
101
|
-
|
100
|
+
|
101
|
+
|
102
102
|
def decrypt_block(block)
|
103
|
+
raise "block must be #{block_size()} bytes long" if (block.length() != block_size())
|
103
104
|
xl, xr = block.unpack('NN')
|
104
105
|
xl, xr = decrypt_pair(xl, xr)
|
105
106
|
decrypted = [xl, xr].pack('NN')
|
106
107
|
return(decrypted)
|
107
108
|
end
|
108
|
-
|
109
|
+
|
110
|
+
end
|
109
111
|
end
|
110
|
-
end
|
data/{crypt → lib/crypt}/cbc.rb
RENAMED
@@ -1,59 +1,58 @@
|
|
1
|
-
# cbc.rb Richard Kernahan <kernighan_rich@rubyforge.org>
|
2
|
-
|
3
1
|
module Crypt
|
2
|
+
|
3
|
+
# cbc.rb Richard Kernahan
|
4
4
|
module CBC
|
5
|
-
|
5
|
+
|
6
6
|
require 'stringio'
|
7
7
|
require 'crypt/stringxor'
|
8
|
-
|
8
|
+
|
9
9
|
ULONG = 0x100000000
|
10
|
-
|
10
|
+
|
11
11
|
# When this module is mixed in with an encryption class, the class
|
12
12
|
# must provide three methods: encrypt_block(block) and decrypt_block(block)
|
13
13
|
# and block_size()
|
14
|
-
|
15
|
-
|
14
|
+
|
15
|
+
|
16
16
|
def generate_initialization_vector(words)
|
17
17
|
srand(Time.now.to_i)
|
18
|
-
vector = ""
|
18
|
+
vector = "".force_encoding("ASCII-8BIT") # stop ruby 2 using Unicode
|
19
19
|
words.times {
|
20
20
|
vector << [rand(ULONG)].pack('N')
|
21
21
|
}
|
22
22
|
return(vector)
|
23
23
|
end
|
24
|
-
|
25
|
-
|
24
|
+
|
25
|
+
|
26
26
|
def encrypt_stream(plainStream, cryptStream)
|
27
27
|
# Cypher-block-chain mode
|
28
|
-
|
28
|
+
|
29
29
|
initVector = generate_initialization_vector(block_size() / 4)
|
30
30
|
chain = encrypt_block(initVector)
|
31
31
|
cryptStream.write(chain)
|
32
32
|
|
33
33
|
while ((block = plainStream.read(block_size())) && (block.length == block_size()))
|
34
|
-
block = block ^ chain
|
34
|
+
block = block ^ chain
|
35
35
|
encrypted = encrypt_block(block)
|
36
36
|
cryptStream.write(encrypted)
|
37
37
|
chain = encrypted
|
38
38
|
end
|
39
|
-
|
40
39
|
# write the final block
|
41
|
-
# At most block_size()-1 bytes can be part of the message.
|
40
|
+
# At most block_size()-1 bytes can be part of the message.
|
42
41
|
# That means the final byte can be used to store the number of meaningful
|
43
42
|
# bytes in the final block
|
44
43
|
block = '' if block.nil?
|
45
44
|
buffer = block.split('')
|
46
45
|
remainingMessageBytes = buffer.length
|
46
|
+
# we use 7-bit characters to avoid possible strange behavior on the Mac
|
47
47
|
remainingMessageBytes.upto(block_size()-2) { buffer << rand(128).chr }
|
48
48
|
buffer << remainingMessageBytes.chr
|
49
49
|
block = buffer.join('')
|
50
50
|
block = block ^ chain
|
51
51
|
encrypted = encrypt_block(block)
|
52
52
|
cryptStream.write(encrypted)
|
53
|
-
chain = encrypted
|
54
53
|
end
|
55
|
-
|
56
|
-
|
54
|
+
|
55
|
+
|
57
56
|
def decrypt_stream(cryptStream, plainStream)
|
58
57
|
# Cypher-block-chain mode
|
59
58
|
chain = cryptStream.read(block_size())
|
@@ -64,44 +63,43 @@ module CBC
|
|
64
63
|
plainStream.write(plainText) unless cryptStream.eof?
|
65
64
|
chain = block
|
66
65
|
end
|
67
|
-
|
68
66
|
# write the final block, omitting the padding
|
69
67
|
buffer = plainText.split('')
|
70
68
|
remainingMessageBytes = buffer.last.unpack('C').first
|
71
69
|
remainingMessageBytes.times { plainStream.write(buffer.shift) }
|
72
70
|
end
|
73
|
-
|
74
|
-
|
71
|
+
|
72
|
+
|
75
73
|
def carefully_open_file(filename, mode)
|
76
74
|
begin
|
77
75
|
aFile = File.new(filename, mode)
|
78
76
|
rescue
|
79
77
|
puts "Sorry. There was a problem opening the file <#{filename}>."
|
80
|
-
aFile.close unless aFile.closed?
|
78
|
+
aFile.close() unless aFile.nil? || aFile.closed?
|
81
79
|
raise
|
82
80
|
end
|
83
81
|
return(aFile)
|
84
82
|
end
|
85
|
-
|
86
|
-
|
83
|
+
|
84
|
+
|
87
85
|
def encrypt_file(plainFilename, cryptFilename)
|
88
|
-
plainFile = carefully_open_file(plainFilename, '
|
89
|
-
cryptFile = carefully_open_file(cryptFilename, '
|
86
|
+
plainFile = carefully_open_file(plainFilename, 'rb')
|
87
|
+
cryptFile = carefully_open_file(cryptFilename, 'wb+')
|
90
88
|
encrypt_stream(plainFile, cryptFile)
|
91
89
|
plainFile.close unless plainFile.closed?
|
92
90
|
cryptFile.close unless cryptFile.closed?
|
93
91
|
end
|
94
|
-
|
95
|
-
|
92
|
+
|
93
|
+
|
96
94
|
def decrypt_file(cryptFilename, plainFilename)
|
97
|
-
cryptFile = carefully_open_file(cryptFilename, '
|
98
|
-
plainFile = carefully_open_file(plainFilename, '
|
95
|
+
cryptFile = carefully_open_file(cryptFilename, 'rb')
|
96
|
+
plainFile = carefully_open_file(plainFilename, 'wb+')
|
99
97
|
decrypt_stream(cryptFile, plainFile)
|
100
98
|
cryptFile.close unless cryptFile.closed?
|
101
99
|
plainFile.close unless plainFile.closed?
|
102
100
|
end
|
103
|
-
|
104
|
-
|
101
|
+
|
102
|
+
|
105
103
|
def encrypt_string(plainText)
|
106
104
|
plainStream = StringIO.new(plainText)
|
107
105
|
cryptStream = StringIO.new('')
|
@@ -109,8 +107,8 @@ module CBC
|
|
109
107
|
cryptText = cryptStream.string
|
110
108
|
return(cryptText)
|
111
109
|
end
|
112
|
-
|
113
|
-
|
110
|
+
|
111
|
+
|
114
112
|
def decrypt_string(cryptText)
|
115
113
|
cryptStream = StringIO.new(cryptText)
|
116
114
|
plainStream = StringIO.new('')
|
@@ -118,6 +116,6 @@ module CBC
|
|
118
116
|
plainText = plainStream.string
|
119
117
|
return(plainText)
|
120
118
|
end
|
121
|
-
|
119
|
+
|
120
|
+
end
|
122
121
|
end
|
123
|
-
end
|
data/{crypt → lib/crypt}/gost.rb
RENAMED
@@ -1,9 +1,8 @@
|
|
1
|
+
module Crypt
|
1
2
|
# gost.rb
|
2
|
-
# Adapted by Richard Kernahan
|
3
|
+
# Adapted by Richard Kernahan
|
3
4
|
# from C++ code written by Wei Dai
|
4
5
|
# of the Crypto++ project http://www.eskimo.com/~weidai/cryptlib.html
|
5
|
-
|
6
|
-
module Crypt
|
7
6
|
class Gost
|
8
7
|
|
9
8
|
require 'crypt/cbc'
|
@@ -137,4 +136,4 @@ class Gost
|
|
137
136
|
|
138
137
|
|
139
138
|
end
|
140
|
-
end
|
139
|
+
end
|
data/{crypt → lib/crypt}/idea.rb
RENAMED
@@ -1,59 +1,55 @@
|
|
1
|
-
|
1
|
+
module Crypt
|
2
|
+
# idea.rb Richard Kernahan
|
2
3
|
|
3
|
-
# IDEA (International Data Encryption Algorithm) by
|
4
|
-
# Xuejia Lai and James Massey (1992).
|
5
|
-
# Ported by Richard Kernahan 2005
|
4
|
+
# IDEA (International Data Encryption Algorithm) by
|
5
|
+
# Xuejia Lai and James Massey (1992). Ported by Richard Kernahan 2005
|
6
6
|
|
7
|
-
module Crypt
|
8
7
|
class IDEA
|
9
|
-
|
8
|
+
|
10
9
|
require 'crypt/cbc'
|
11
10
|
include Crypt::CBC
|
12
11
|
|
13
12
|
require 'digest/md5'
|
14
|
-
|
15
|
-
ULONG = 0x100000000
|
13
|
+
|
16
14
|
USHORT = 0x10000
|
17
|
-
|
15
|
+
|
18
16
|
ENCRYPT = 0
|
19
17
|
DECRYPT = 1
|
20
18
|
|
21
|
-
|
19
|
+
attr_accessor(:subkeys)
|
20
|
+
|
22
21
|
def block_size
|
23
22
|
return(8)
|
24
23
|
end
|
25
|
-
|
26
|
-
|
24
|
+
|
27
25
|
def initialize(key128, mode)
|
28
26
|
# IDEA is subject to attack unless the key is sufficiently random, so we
|
29
27
|
# 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).
|
32
|
-
key128 = digest.unpack('
|
28
|
+
if (key128.class == String)
|
29
|
+
digest = Digest::MD5.new().digest(key128.b).b()
|
30
|
+
key128 = digest.unpack('n8')
|
33
31
|
end
|
34
32
|
raise "Key must be 128 bits (8 words)" unless (key128.class == Array) && (key128.length == 8)
|
35
33
|
raise "Mode must be IDEA::ENCRYPT or IDEA::DECRYPT" unless ((mode == ENCRYPT) | (mode == DECRYPT))
|
36
34
|
if (mode == ENCRYPT)
|
37
35
|
@subkeys = generate_encryption_subkeys(key128)
|
38
|
-
else
|
36
|
+
else
|
39
37
|
@subkeys = generate_decryption_subkeys(key128)
|
40
38
|
end
|
41
39
|
end
|
42
40
|
|
43
|
-
|
44
41
|
def mul(a, b)
|
45
42
|
modulus = 0x10001
|
46
43
|
return((1 - b) % USHORT) if (a == 0)
|
47
44
|
return((1 - a) % USHORT) if (b == 0)
|
48
|
-
return((a * b) % modulus)
|
45
|
+
return((a * b) % modulus % USHORT) # fixed with % USHORT
|
49
46
|
end
|
50
|
-
|
51
|
-
|
47
|
+
|
52
48
|
def mulInv(x)
|
53
49
|
modulus = 0x10001
|
54
|
-
x = x.to_i %
|
50
|
+
x = x.to_i % 0x10000
|
55
51
|
return(x) if (x <= 1)
|
56
|
-
t1 =
|
52
|
+
t1 = modulus / x
|
57
53
|
y = modulus % x
|
58
54
|
if (y == 1)
|
59
55
|
inv = (1 - t1) & 0xFFFF
|
@@ -72,11 +68,10 @@ class IDEA
|
|
72
68
|
inv = (1 - t1) & 0xFFFF
|
73
69
|
return(inv)
|
74
70
|
end
|
75
|
-
|
76
|
-
|
71
|
+
|
77
72
|
def generate_encryption_subkeys(key)
|
78
73
|
encrypt_keys = []
|
79
|
-
encrypt_keys[0..7] = key
|
74
|
+
encrypt_keys[0..7] = key.dup
|
80
75
|
8.upto(51) { |i|
|
81
76
|
a = ((i + 1) % 8 > 0) ? (i-7) : (i-15)
|
82
77
|
b = ((i + 2) % 8 < 2) ? (i-14) : (i-6)
|
@@ -84,8 +79,7 @@ class IDEA
|
|
84
79
|
}
|
85
80
|
return(encrypt_keys)
|
86
81
|
end
|
87
|
-
|
88
|
-
|
82
|
+
|
89
83
|
def generate_decryption_subkeys(key)
|
90
84
|
encrypt_keys = generate_encryption_subkeys(key)
|
91
85
|
decrypt_keys = []
|
@@ -97,7 +91,7 @@ class IDEA
|
|
97
91
|
decrypt_keys[i+4] = encrypt_keys.shift % USHORT
|
98
92
|
decrypt_keys[i+5] = encrypt_keys.shift % USHORT
|
99
93
|
decrypt_keys[i] = mulInv(encrypt_keys.shift)
|
100
|
-
if (i ==0)
|
94
|
+
if (i == 0)
|
101
95
|
decrypt_keys[1] = (-encrypt_keys.shift) % USHORT
|
102
96
|
decrypt_keys[2] = (-encrypt_keys.shift) % USHORT
|
103
97
|
else
|
@@ -108,8 +102,7 @@ class IDEA
|
|
108
102
|
}
|
109
103
|
return(decrypt_keys)
|
110
104
|
end
|
111
|
-
|
112
|
-
|
105
|
+
|
113
106
|
def crypt_pair(l, r)
|
114
107
|
word = [l, r].pack('NN').unpack('nnnn')
|
115
108
|
k = @subkeys[0..51]
|
@@ -137,15 +130,14 @@ class IDEA
|
|
137
130
|
twoLongs = result.pack('nnnn').unpack('NN')
|
138
131
|
return(twoLongs)
|
139
132
|
end
|
140
|
-
|
133
|
+
|
141
134
|
def encrypt_block(block)
|
142
135
|
xl, xr = block.unpack('NN')
|
143
136
|
xl, xr = crypt_pair(xl, xr)
|
144
137
|
encrypted = [xl, xr].pack('NN')
|
145
138
|
return(encrypted)
|
146
139
|
end
|
147
|
-
|
148
|
-
|
140
|
+
|
149
141
|
def decrypt_block(block)
|
150
142
|
xl, xr = block.unpack('NN')
|
151
143
|
xl, xr = crypt_pair(xl, xr)
|
@@ -153,41 +145,6 @@ class IDEA
|
|
153
145
|
return(decrypted)
|
154
146
|
end
|
155
147
|
|
156
|
-
|
157
148
|
end
|
158
149
|
end
|
159
150
|
|
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
|
-
|
@@ -1,9 +1,9 @@
|
|
1
|
-
|
1
|
+
module Crypt
|
2
|
+
# crypt/noise.rb Richard Kernahan
|
2
3
|
|
3
4
|
# add_noise - take a message and intersperse noise to make a new noisy message of given byte-length
|
4
5
|
# remove_noise - take a noisy message and extract the message
|
5
6
|
|
6
|
-
module Crypt
|
7
7
|
module Noise
|
8
8
|
|
9
9
|
def add_noise(newLength)
|
@@ -17,7 +17,7 @@ module Noise
|
|
17
17
|
puts "is #{minimumNewLength} bytes which allows for no noise in the message."
|
18
18
|
puts "You should choose an obscured length of at least double the clear text"
|
19
19
|
puts "length, such as #{message.length / 8 * 32} bytes"
|
20
|
-
raise "Insufficient length for noisy message"
|
20
|
+
raise "Insufficient length for noisy message"
|
21
21
|
end
|
22
22
|
bitmap = []
|
23
23
|
usableNoisyMessageLength.times { bitmap << false }
|
@@ -32,8 +32,8 @@ module Noise
|
|
32
32
|
positionsSelected = positionsSelected.next
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
36
|
-
noisyMessage = ""
|
35
|
+
|
36
|
+
noisyMessage = "".force_encoding("ASCII-8BIT") # stop ruby 2 using Unicode
|
37
37
|
0.upto(bitmapSize-1) { |byte|
|
38
38
|
c = 0
|
39
39
|
0.upto(7) { |bit|
|
@@ -58,17 +58,17 @@ module Noise
|
|
58
58
|
}
|
59
59
|
return(noisyMessage)
|
60
60
|
end
|
61
|
-
|
62
|
-
|
61
|
+
|
62
|
+
|
63
63
|
def remove_noise
|
64
64
|
noisyMessage = self
|
65
65
|
bitmapSize = noisyMessage.length / 9
|
66
66
|
actualMessageLength = bitmapSize * 8
|
67
|
-
|
67
|
+
|
68
68
|
actualMessageStart = bitmapSize
|
69
69
|
actualMessageFinish = bitmapSize + actualMessageLength - 1
|
70
70
|
actualMessage = noisyMessage[actualMessageStart..actualMessageFinish]
|
71
|
-
|
71
|
+
|
72
72
|
bitmap = []
|
73
73
|
0.upto(bitmapSize - 1) { |byte|
|
74
74
|
c = noisyMessage[byte]
|
@@ -76,7 +76,7 @@ module Noise
|
|
76
76
|
bitmap[byte * 8 + bit] = (c[bit] == 1)
|
77
77
|
}
|
78
78
|
}
|
79
|
-
clearMessage = ""
|
79
|
+
clearMessage = "".force_encoding("ASCII-8BIT") # stop ruby 2 using Unicode
|
80
80
|
0.upto(actualMessageLength) { |pos|
|
81
81
|
meaningful = bitmap[pos]
|
82
82
|
if meaningful
|
@@ -85,10 +85,10 @@ module Noise
|
|
85
85
|
}
|
86
86
|
return(clearMessage)
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
92
|
class String
|
93
93
|
include Crypt::Noise
|
94
|
-
end
|
94
|
+
end
|