crypt 1.1.3 → 2.2.1
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.
- 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
|