ruby-des 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/.gitignore +2 -0
- data/MIT-LICENSE +22 -0
- data/README.markdown +53 -0
- data/Rakefile +9 -0
- data/lib/ruby-des.rb +91 -0
- data/lib/ruby-des/feistel.rb +89 -0
- data/lib/ruby-des/key_schedule.rb +51 -0
- data/lib/ruby-des/xor.rb +11 -0
- data/test/ctx.yml +17 -0
- data/test/ctx_test.rb +20 -0
- data/test/feistel.yml +18 -0
- data/test/feistel_test.rb +9 -0
- data/test/key_schedule.yml +152 -0
- data/test/key_schedule_test.rb +38 -0
- data/test/test_helper.rb +19 -0
- data/test/xor.yml +26 -0
- data/test/xor_test.rb +9 -0
- metadata +90 -0
data/.gitignore
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2009 Robert Sosinski (http://www.robertsosinski.com)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
RubyDES
|
2
|
+
=======
|
3
|
+
|
4
|
+
RubyDES is a full Ruby implementation of the Data Encryption Standard. The purpose of this
|
5
|
+
project was to allow Ruby programmers interested in cryptography a glimpse of how a robust
|
6
|
+
cryptographic algorithm functions in a language they understand.
|
7
|
+
|
8
|
+
The best way to understand the RubyDES source code is by following along with a FIPS 46,
|
9
|
+
which you can find at http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
|
10
|
+
|
11
|
+
NOTE: DES is deprecated, and as such, you should not use this implementation in any project you
|
12
|
+
are developing. I highly recommend the AES, TwoFish or Serpent algorithms through the OpenSSL
|
13
|
+
library instead.
|
14
|
+
|
15
|
+
Running RubyDES
|
16
|
+
===============
|
17
|
+
|
18
|
+
Using RubyDES is pretty easy. First, construct a new data and key block.
|
19
|
+
|
20
|
+
data = RubyDES::Block.new('mysecret')
|
21
|
+
key = RubyDES::Block.new('hushhush')
|
22
|
+
|
23
|
+
Then, build a new `RubyDES::Ctx` object and supply the data and key block.
|
24
|
+
|
25
|
+
des = RubyDES::Ctx.new(data, key)
|
26
|
+
|
27
|
+
Finally, let it go.
|
28
|
+
|
29
|
+
encrypted_data = des.encrypt
|
30
|
+
|
31
|
+
You will then be returned a DES encrypted block that is completely secure against eavesdropping
|
32
|
+
(if it were still 1997).
|
33
|
+
|
34
|
+
To decrypt an encrypted data block, just build a new `RubyDES::Ctx` object in similar
|
35
|
+
fashion as before.
|
36
|
+
|
37
|
+
un_des = RubyDES::Ctx.new(encrypted_data, key)
|
38
|
+
|
39
|
+
And run the DES with the key schedule reversed.
|
40
|
+
|
41
|
+
decrypted_data = un_des.decrypt
|
42
|
+
|
43
|
+
You can then check to see if it all worked.
|
44
|
+
|
45
|
+
data.bit_array.eql?(decrypted_data.bit_array)
|
46
|
+
|
47
|
+
Enjoy!
|
48
|
+
|
49
|
+
Feedback
|
50
|
+
========
|
51
|
+
|
52
|
+
If you have any questions, comments or just want to talk shop about crypto, feel free to reach me
|
53
|
+
through my website at http://www.robertsosinski.com.
|
data/Rakefile
ADDED
data/lib/ruby-des.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'ruby-des/feistel'
|
4
|
+
require 'ruby-des/key_schedule'
|
5
|
+
require 'ruby-des/xor'
|
6
|
+
|
7
|
+
module RubyDES
|
8
|
+
IP_L = [0x3a, 0x32, 0x2a, 0x22, 0x1a, 0x12, 0x0a, 0x02,
|
9
|
+
0x3c, 0x34, 0x2c, 0x24, 0x1c, 0x14, 0x0c, 0x04,
|
10
|
+
0x3e, 0x36, 0x2e, 0x26, 0x1e, 0x16, 0x0e, 0x06,
|
11
|
+
0x40, 0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x08]
|
12
|
+
|
13
|
+
IP_R = [0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09, 0x01,
|
14
|
+
0x3b, 0x33, 0x2b, 0x23, 0x1b, 0x13, 0x0b, 0x03,
|
15
|
+
0x3d, 0x35, 0x2d, 0x25, 0x1d, 0x15, 0x0d, 0x05,
|
16
|
+
0x3f, 0x37, 0x2f, 0x27, 0x1f, 0x17, 0x0f, 0x07]
|
17
|
+
|
18
|
+
FP = [0x28, 0x08, 0x30, 0x10, 0x38, 0x18, 0x40, 0x20,
|
19
|
+
0x27, 0x07, 0x2f, 0x0f, 0x37, 0x17, 0x3f, 0x1f,
|
20
|
+
0x26, 0x06, 0x2e, 0x0e, 0x36, 0x16, 0x3e, 0x1e,
|
21
|
+
0x25, 0x05, 0x2d, 0x0d, 0x35, 0x15, 0x3d, 0x1d,
|
22
|
+
0x24, 0x04, 0x2c, 0x0c, 0x34, 0x14, 0x3c, 0x1c,
|
23
|
+
0x23, 0x03, 0x2b, 0x0b, 0x33, 0x13, 0x3b, 0x1b,
|
24
|
+
0x22, 0x02, 0x2a, 0x0a, 0x32, 0x12, 0x3a, 0x1a,
|
25
|
+
0x21, 0x01, 0x29, 0x09, 0x31, 0x11, 0x39, 0x19]
|
26
|
+
|
27
|
+
class Ctx
|
28
|
+
attr_reader :data, :key
|
29
|
+
|
30
|
+
def initialize(data, key)
|
31
|
+
unless data.is_a?(RubyDES::Block) and key.is_a?(RubyDES::Block)
|
32
|
+
raise "RubyDES::InvalidBlockFormat: Data and key must be a Block object."
|
33
|
+
end
|
34
|
+
|
35
|
+
@data = data
|
36
|
+
@key = key
|
37
|
+
end
|
38
|
+
|
39
|
+
def encrypt
|
40
|
+
self.run(:encrypt)
|
41
|
+
end
|
42
|
+
|
43
|
+
def decrypt
|
44
|
+
self.run(:decrypt)
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def run(operation)
|
50
|
+
l = [] # l[0] is the IP_1_L permutation of the data block, l[1..16] are the results of each round of encryption.
|
51
|
+
r = [] # r[0] is the IP_1_R permutation of the data block, r[1..16] are the results of each round of encryption.
|
52
|
+
|
53
|
+
l << IP_L.collect{|p| data.bit_array[p - 1]}
|
54
|
+
r << IP_R.collect{|p| data.bit_array[p - 1]}
|
55
|
+
|
56
|
+
case operation
|
57
|
+
when :encrypt
|
58
|
+
k = KeySchedule.new(key.bit_array).sub_keys
|
59
|
+
when :decrypt
|
60
|
+
k = KeySchedule.new(key.bit_array).sub_keys.reverse
|
61
|
+
end
|
62
|
+
|
63
|
+
16.times do |i|
|
64
|
+
l << r[i]
|
65
|
+
r << XOR.run(Feistel.run(r[i], k[i]), l[i])
|
66
|
+
end
|
67
|
+
|
68
|
+
return RubyDES::Block.new(FP.collect{|p| (r.last + l.last)[p - 1]})
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class Block
|
73
|
+
attr_reader :string, :bit_array
|
74
|
+
|
75
|
+
def initialize(input)
|
76
|
+
if input.is_a?(String)
|
77
|
+
raise "RubyDES::InvalidStringLength: Input String must contain (8) characters." unless input.length.eql?(8)
|
78
|
+
|
79
|
+
@string = input
|
80
|
+
@bit_array = input.unpack('B*').join.split('').collect{|b| b.to_i}
|
81
|
+
elsif input.is_a?(Array)
|
82
|
+
raise "RubyDES::InvalidArraySize: Input Array must contain (64) bits." unless input.size.eql?(64)
|
83
|
+
|
84
|
+
@string = input.join.to_a.pack('B*')
|
85
|
+
@bit_array = input
|
86
|
+
else
|
87
|
+
raise "RubyDES::InvalidFormat: Input must be a String or an Array."
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Feistel
|
2
|
+
E = [0x20, 0x01, 0x02, 0x03, 0x04, 0x05,
|
3
|
+
0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
|
4
|
+
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
|
5
|
+
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
|
6
|
+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
|
7
|
+
0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
|
8
|
+
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
|
9
|
+
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x01]
|
10
|
+
|
11
|
+
P = [0x10, 0x07, 0x14, 0x15,
|
12
|
+
0x1d, 0x0c, 0x1c, 0x11,
|
13
|
+
0x01, 0x0f, 0x17, 0x1a,
|
14
|
+
0x05, 0x12, 0x1f, 0x0a,
|
15
|
+
0x02, 0x08, 0x18, 0x0e,
|
16
|
+
0x20, 0x1b, 0x03, 0x09,
|
17
|
+
0x13, 0x0d, 0x1e, 0x06,
|
18
|
+
0x16, 0x0b, 0x04, 0x19]
|
19
|
+
|
20
|
+
S1 = [0x0e, 0x04, 0x0d, 0x01, 0x02, 0x0f, 0x0b, 0x08, 0x03, 0x0a, 0x06, 0x0c, 0x05, 0x09, 0x00, 0x07,
|
21
|
+
0x00, 0x0f, 0x07, 0x04, 0x0e, 0x02, 0x0d, 0x01, 0x0a, 0x06, 0x0c, 0x0b, 0x09, 0x05, 0x03, 0x08,
|
22
|
+
0x04, 0x01, 0x0e, 0x08, 0x0d, 0x06, 0x02, 0x0b, 0x0f, 0x0c, 0x09, 0x07, 0x03, 0x0a, 0x05, 0x00,
|
23
|
+
0x0f, 0x0c, 0x08, 0x02, 0x04, 0x09, 0x01, 0x07, 0x05, 0x0b, 0x03, 0x0e, 0x0a, 0x00, 0x06, 0x0d]
|
24
|
+
|
25
|
+
S2 = [0x0f, 0x01, 0x08, 0x0e, 0x06, 0x0b, 0x03, 0x04, 0x09, 0x07, 0x02, 0x0d, 0x0c, 0x00, 0x05, 0x0a,
|
26
|
+
0x03, 0x0d, 0x04, 0x07, 0x0f, 0x02, 0x08, 0x0e, 0x0c, 0x00, 0x01, 0x0a, 0x06, 0x09, 0x0b, 0x05,
|
27
|
+
0x00, 0x0e, 0x07, 0x0b, 0x0a, 0x04, 0x0d, 0x01, 0x05, 0x08, 0x0c, 0x06, 0x09, 0x03, 0x02, 0x0f,
|
28
|
+
0x0d, 0x08, 0x0a, 0x01, 0x03, 0x0f, 0x04, 0x02, 0x0b, 0x06, 0x07, 0x0c, 0x00, 0x05, 0x0e, 0x09]
|
29
|
+
|
30
|
+
S3 = [0x0a, 0x00, 0x09, 0x0e, 0x06, 0x03, 0x0f, 0x05, 0x01, 0x0d, 0x0c, 0x07, 0x0b, 0x04, 0x02, 0x08,
|
31
|
+
0x0d, 0x07, 0x00, 0x09, 0x03, 0x04, 0x06, 0x0a, 0x02, 0x08, 0x05, 0x0e, 0x0c, 0x0b, 0x0f, 0x01,
|
32
|
+
0x0d, 0x06, 0x04, 0x09, 0x08, 0x0f, 0x03, 0x00, 0x0b, 0x01, 0x02, 0x0c, 0x05, 0x0a, 0x0e, 0x07,
|
33
|
+
0x01, 0x0a, 0x0d, 0x00, 0x06, 0x09, 0x08, 0x07, 0x04, 0x0f, 0x0e, 0x03, 0x0b, 0x05, 0x02, 0x0c]
|
34
|
+
|
35
|
+
S4 = [0x07, 0x0d, 0x0e, 0x03, 0x00, 0x06, 0x09, 0x0a, 0x01, 0x02, 0x08, 0x05, 0x0b, 0x0c, 0x04, 0x0f,
|
36
|
+
0x0d, 0x08, 0x0b, 0x05, 0x06, 0x0f, 0x00, 0x03, 0x04, 0x07, 0x02, 0x0c, 0x01, 0x0a, 0x0e, 0x09,
|
37
|
+
0x0a, 0x06, 0x09, 0x00, 0x0c, 0x0b, 0x07, 0x0d, 0x0f, 0x01, 0x03, 0x0e, 0x05, 0x02, 0x08, 0x04,
|
38
|
+
0x03, 0x0f, 0x00, 0x06, 0x0a, 0x01, 0x0d, 0x08, 0x09, 0x04, 0x05, 0x0b, 0x0c, 0x07, 0x02, 0x0e]
|
39
|
+
|
40
|
+
S5 = [0x02, 0x0c, 0x04, 0x01, 0x07, 0x0a, 0x0b, 0x06, 0x08, 0x05, 0x03, 0x0f, 0x0d, 0x00, 0x0e, 0x09,
|
41
|
+
0x0e, 0x0b, 0x02, 0x0c, 0x04, 0x07, 0x0d, 0x01, 0x05, 0x00, 0x0f, 0x0a, 0x03, 0x09, 0x08, 0x06,
|
42
|
+
0x04, 0x02, 0x01, 0x0b, 0x0a, 0x0d, 0x07, 0x08, 0x0f, 0x09, 0x0c, 0x05, 0x06, 0x03, 0x00, 0x0e,
|
43
|
+
0x0b, 0x08, 0x0c, 0x07, 0x01, 0x0e, 0x02, 0x0d, 0x06, 0x0f, 0x00, 0x09, 0x0a, 0x04, 0x05, 0x03]
|
44
|
+
|
45
|
+
S6 = [0x0c, 0x01, 0x0a, 0x0f, 0x09, 0x02, 0x06, 0x08, 0x00, 0x0d, 0x03, 0x04, 0x0e, 0x07, 0x05, 0x0b,
|
46
|
+
0x0a, 0x0f, 0x04, 0x02, 0x07, 0x0c, 0x09, 0x05, 0x06, 0x01, 0x0d, 0x0e, 0x00, 0x0b, 0x03, 0x08,
|
47
|
+
0x09, 0x0e, 0x0f, 0x05, 0x02, 0x08, 0x0c, 0x03, 0x07, 0x00, 0x04, 0x0a, 0x01, 0x0d, 0x0b, 0x06,
|
48
|
+
0x04, 0x03, 0x02, 0x0c, 0x09, 0x05, 0x0f, 0x0a, 0x0b, 0x0e, 0x01, 0x07, 0x06, 0x00, 0x08, 0x0d]
|
49
|
+
|
50
|
+
S7 = [0x04, 0x0b, 0x02, 0x0e, 0x0f, 0x00, 0x08, 0x0d, 0x03, 0x0c, 0x09, 0x07, 0x05, 0x0a, 0x06, 0x01,
|
51
|
+
0x0d, 0x00, 0x0b, 0x07, 0x04, 0x09, 0x01, 0x0a, 0x0e, 0x03, 0x05, 0x0c, 0x02, 0x0f, 0x08, 0x06,
|
52
|
+
0x01, 0x04, 0x0b, 0x0d, 0x0c, 0x03, 0x07, 0x0e, 0x0a, 0x0f, 0x06, 0x08, 0x00, 0x05, 0x09, 0x02,
|
53
|
+
0x06, 0x0b, 0x0d, 0x08, 0x01, 0x04, 0x0a, 0x07, 0x09, 0x05, 0x00, 0x0f, 0x0e, 0x02, 0x03, 0x0c]
|
54
|
+
|
55
|
+
S8 = [0x0d, 0x02, 0x08, 0x04, 0x06, 0x0f, 0x0b, 0x01, 0x0a, 0x09, 0x03, 0x0e, 0x05, 0x00, 0x0c, 0x07,
|
56
|
+
0x01, 0x0f, 0x0d, 0x08, 0x0a, 0x03, 0x07, 0x04, 0x0c, 0x05, 0x06, 0x0b, 0x00, 0x0e, 0x09, 0x02,
|
57
|
+
0x07, 0x0b, 0x04, 0x01, 0x09, 0x0c, 0x0e, 0x02, 0x00, 0x06, 0x0a, 0x0d, 0x0f, 0x03, 0x05, 0x08,
|
58
|
+
0x02, 0x01, 0x0e, 0x07, 0x04, 0x0a, 0x08, 0x0d, 0x0f, 0x0c, 0x09, 0x00, 0x03, 0x05, 0x06, 0x0b]
|
59
|
+
|
60
|
+
S = [S1, S2, S3, S4, S5, S6, S7, S8]
|
61
|
+
|
62
|
+
def self.run(r, k)
|
63
|
+
b = [] # b[0..7] is e_xor_k prepped as 8 6-bit arrays for s-box substitution.
|
64
|
+
m = [] # m[0..7] is the row of the value when performing a s-box lookup.
|
65
|
+
n = [] # n[0..7] is the column of the value when performing a s-box lookup.
|
66
|
+
|
67
|
+
e = E.collect{|p| r[p - 1]} # Expand r (right half data block) using E.
|
68
|
+
|
69
|
+
e_xor_k = XOR.run(e, k) # X-or e (expanded r) with k (the sub key).
|
70
|
+
|
71
|
+
# Break e_xor_k into 8 6-bit arrays and find both m (s-box row) and n (s-box column) for the s-box lookup.
|
72
|
+
8.times do |i|
|
73
|
+
b << []
|
74
|
+
6.times do
|
75
|
+
b[i] << e_xor_k.shift
|
76
|
+
end
|
77
|
+
|
78
|
+
m << [b[i].first, b[i].last].join.to_i(2) * 16 # [1, 0, 1, 0, 1, 0] => [1, 0] => 2 => 32 => 3rd row.
|
79
|
+
n << b[i][1..4].join.to_i(2) # [1, 0, 1, 0, 1, 0] => [0, 1, 0, 1] => 5 => 6th column.
|
80
|
+
end
|
81
|
+
|
82
|
+
# Substitute every 6-bit array with the 4-bit array specified by the appropriate s-box.
|
83
|
+
8.times do |i|
|
84
|
+
b[i] = S[i][m[i] + n[i]].to_s(2).rjust(4, '0').split('').collect{|bit| bit.to_i}
|
85
|
+
end
|
86
|
+
|
87
|
+
return P.collect{|p| b.flatten[p - 1]}
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class KeySchedule
|
2
|
+
attr_accessor :sub_keys
|
3
|
+
attr_reader :key
|
4
|
+
|
5
|
+
PC_1_L = [0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09,
|
6
|
+
0x01, 0x3a, 0x32, 0x2a, 0x22, 0x1a, 0x12,
|
7
|
+
0x0a, 0x02, 0x3b, 0x33, 0x2b, 0x23, 0x1b,
|
8
|
+
0x13, 0x0b, 0x03, 0x3c, 0x34, 0x2c, 0x24]
|
9
|
+
|
10
|
+
PC_1_R = [0x3f, 0x37, 0x2f, 0x27, 0x1f, 0x17, 0x0f,
|
11
|
+
0x07, 0x3e, 0x36, 0x2e, 0x26, 0x1e, 0x16,
|
12
|
+
0x0e, 0x06, 0x3d, 0x35, 0x2d, 0x25, 0x1d,
|
13
|
+
0x15, 0x0d, 0x05, 0x1c, 0x14, 0x0c, 0x04]
|
14
|
+
|
15
|
+
PC_2 = [0x0e, 0x11, 0x0b, 0x18, 0x01, 0x05,
|
16
|
+
0x03, 0x1c, 0x0f, 0x06, 0x15, 0x0a,
|
17
|
+
0x17, 0x13, 0x0c, 0x04, 0x1a, 0x08,
|
18
|
+
0x10, 0x07, 0x1b, 0x14, 0x0d, 0x02,
|
19
|
+
0x29, 0x34, 0x1f, 0x25, 0x2f, 0x37,
|
20
|
+
0x1e, 0x28, 0x33, 0x2d, 0x21, 0x30,
|
21
|
+
0x2c, 0x31, 0x27, 0x38, 0x22, 0x35,
|
22
|
+
0x2e, 0x2a, 0x32, 0x24, 0x1d, 0x20]
|
23
|
+
|
24
|
+
ROTATIONS = [1, 1, 2, 2, 2, 2, 2, 2,
|
25
|
+
1, 2, 2, 2, 2, 2, 2, 1]
|
26
|
+
|
27
|
+
def initialize(key)
|
28
|
+
@key = key
|
29
|
+
|
30
|
+
c = [] # c[0] is the PC_1_L permutation of the key, c[1..16] are the results of each left shift.
|
31
|
+
d = [] # d[0] is the PC_1_R permutation of the key, d[1..16] are the results of each left shift.
|
32
|
+
k = [] # k[0..15] are the sub keys created by combining c[i] and d[i] and permuting with PC_2.
|
33
|
+
|
34
|
+
c << PC_1_L.collect{|p| key[p - 1]}
|
35
|
+
d << PC_1_R.collect{|p| key[p - 1]}
|
36
|
+
|
37
|
+
16.times do |i|
|
38
|
+
c << c[i]
|
39
|
+
d << d[i]
|
40
|
+
|
41
|
+
ROTATIONS[i].times do
|
42
|
+
c[i + 1] << c[i + 1].shift
|
43
|
+
d[i + 1] << d[i + 1].shift
|
44
|
+
end
|
45
|
+
|
46
|
+
k << PC_2.collect{|p| (c[i + 1] + d[i + 1])[p - 1]}
|
47
|
+
end
|
48
|
+
|
49
|
+
@sub_keys = k
|
50
|
+
end
|
51
|
+
end
|
data/lib/ruby-des/xor.rb
ADDED
data/test/ctx.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
decrypted_bit_array: [0, 1, 1, 1, 0, 0, 1, 1,
|
2
|
+
0, 1, 1, 0, 0, 1, 0, 1,
|
3
|
+
0, 1, 1, 0, 0, 0, 1, 1,
|
4
|
+
0, 1, 1, 1, 0, 1, 0, 1,
|
5
|
+
0, 1, 1, 1, 0, 0, 1, 0,
|
6
|
+
0, 1, 1, 0, 1, 0, 0, 1,
|
7
|
+
0, 1, 1, 1, 0, 1, 0, 0,
|
8
|
+
0, 1, 1, 1, 1, 0, 0, 1]
|
9
|
+
|
10
|
+
encrypted_bit_array: [0, 0, 0, 0, 1, 0, 1, 0,
|
11
|
+
1, 1, 0, 1, 1, 1, 1, 0,
|
12
|
+
0, 1, 0, 1, 0, 0, 1, 0,
|
13
|
+
1, 0, 1, 0, 0, 1, 0, 0,
|
14
|
+
0, 1, 1, 1, 0, 0, 1, 0,
|
15
|
+
0, 0, 0, 0, 0, 1, 0, 1,
|
16
|
+
0, 0, 0, 0, 0, 0, 1, 0,
|
17
|
+
0, 1, 0, 1, 0, 0, 0, 1]
|
data/test/ctx_test.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CtxTest < Test::Unit::TestCase
|
4
|
+
fixtures :ctx
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@data = RubyDES::Block.new('security')
|
8
|
+
@key = RubyDES::Block.new('ruby-des')
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_run
|
12
|
+
encrypted_data = RubyDES::Ctx.new(@data, @key).encrypt
|
13
|
+
|
14
|
+
assert_equal ctx(:encrypted_bit_array), encrypted_data.bit_array
|
15
|
+
|
16
|
+
decrypted_data = RubyDES::Ctx.new(encrypted_data, @key).decrypt
|
17
|
+
|
18
|
+
assert_equal ctx(:decrypted_bit_array), decrypted_data.bit_array
|
19
|
+
end
|
20
|
+
end
|
data/test/feistel.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
half_block: [0, 0, 0, 0, 0, 0, 0, 0,
|
2
|
+
1, 1, 1, 1, 1, 1, 1, 1,
|
3
|
+
1, 0, 1, 0, 0, 0, 0, 0,
|
4
|
+
0, 0, 0, 1, 0, 1, 0, 1]
|
5
|
+
|
6
|
+
sub_key: [1, 0, 1, 0, 1, 1,
|
7
|
+
0, 1, 1, 1, 0, 1,
|
8
|
+
1, 0, 1, 1, 0, 1,
|
9
|
+
1, 1, 1, 1, 1, 1,
|
10
|
+
1, 1, 1, 0, 1, 0,
|
11
|
+
0, 0, 0, 1, 0, 0,
|
12
|
+
0, 0, 0, 1, 1, 0,
|
13
|
+
1, 0, 1, 1, 1, 1]
|
14
|
+
|
15
|
+
output: [1, 0, 0, 1, 1, 1, 0, 0,
|
16
|
+
0, 1, 1, 0, 0, 1, 0, 0,
|
17
|
+
0, 1, 0, 1, 1, 1, 1, 0,
|
18
|
+
1, 0, 1, 1, 0, 0, 0, 0]
|
@@ -0,0 +1,152 @@
|
|
1
|
+
test_key: [1, 1, 1, 0, 0, 1, 0, 1,
|
2
|
+
1, 1, 1, 0, 1, 0, 1, 0,
|
3
|
+
1, 1, 0, 0, 0, 1, 0, 0,
|
4
|
+
1, 1, 1, 1, 0, 0, 1, 0,
|
5
|
+
0, 1, 0, 1, 1, 0, 1, 1,
|
6
|
+
1, 1, 0, 0, 1, 0, 0, 0,
|
7
|
+
1, 1, 0, 0, 1, 0, 1, 1,
|
8
|
+
1, 1, 1, 0, 0, 1, 1, 0]
|
9
|
+
|
10
|
+
sub_key_1: [1, 0, 1, 0, 1, 1,
|
11
|
+
0, 1, 1, 1, 0, 1,
|
12
|
+
1, 0, 1, 1, 0, 1,
|
13
|
+
1, 1, 1, 1, 1, 1,
|
14
|
+
1, 1, 1, 0, 1, 0,
|
15
|
+
0, 0, 0, 1, 0, 0,
|
16
|
+
0, 0, 0, 1, 1, 0,
|
17
|
+
1, 0, 1, 1, 1, 1]
|
18
|
+
|
19
|
+
sub_key_2: [1, 0, 1, 0, 1, 1,
|
20
|
+
1, 1, 1, 1, 1, 1,
|
21
|
+
0, 1, 1, 1, 1, 1,
|
22
|
+
0, 1, 1, 0, 1, 0,
|
23
|
+
0, 0, 1, 0, 0, 1,
|
24
|
+
1, 1, 1, 1, 1, 0,
|
25
|
+
1, 1, 0, 1, 0, 0,
|
26
|
+
1, 1, 0, 0, 0, 0]
|
27
|
+
|
28
|
+
sub_key_3: [0, 1, 1, 1, 1, 1,
|
29
|
+
1, 0, 0, 1, 0, 1,
|
30
|
+
0, 1, 1, 1, 1, 1,
|
31
|
+
0, 1, 1, 1, 1, 1,
|
32
|
+
0, 0, 1, 0, 1, 0,
|
33
|
+
0, 1, 0, 0, 1, 0,
|
34
|
+
1, 1, 0, 1, 0, 1,
|
35
|
+
0, 1, 0, 0, 1, 0]
|
36
|
+
|
37
|
+
sub_key_4: [0, 1, 1, 1, 1, 1,
|
38
|
+
1, 1, 1, 1, 0, 1,
|
39
|
+
1, 0, 0, 1, 0, 1,
|
40
|
+
0, 1, 1, 0, 0, 1,
|
41
|
+
1, 1, 1, 0, 1, 1,
|
42
|
+
0, 1, 1, 1, 0, 0,
|
43
|
+
0, 0, 0, 0, 0, 0,
|
44
|
+
0, 1, 0, 1, 1, 0]
|
45
|
+
|
46
|
+
sub_key_5: [0, 0, 0, 0, 1, 1,
|
47
|
+
1, 1, 1, 1, 1, 0,
|
48
|
+
1, 0, 0, 1, 1, 1,
|
49
|
+
1, 1, 1, 1, 1, 1,
|
50
|
+
0, 1, 0, 0, 0, 1,
|
51
|
+
0, 1, 0, 1, 0, 0,
|
52
|
+
0, 1, 1, 0, 1, 1,
|
53
|
+
0, 0, 1, 1, 1, 0]
|
54
|
+
|
55
|
+
sub_key_6: [1, 0, 1, 1, 1, 1,
|
56
|
+
1, 1, 0, 1, 1, 0,
|
57
|
+
1, 1, 0, 1, 1, 0,
|
58
|
+
0, 1, 1, 1, 1, 1,
|
59
|
+
1, 0, 0, 1, 1, 1,
|
60
|
+
0, 0, 1, 0, 0, 1,
|
61
|
+
0, 0, 0, 0, 1, 1,
|
62
|
+
0, 0, 1, 1, 0, 1]
|
63
|
+
|
64
|
+
sub_key_7: [0, 1, 1, 1, 1, 1,
|
65
|
+
1, 1, 0, 0, 1, 0,
|
66
|
+
1, 1, 1, 1, 1, 0,
|
67
|
+
1, 0, 1, 0, 0, 1,
|
68
|
+
1, 0, 0, 0, 0, 0,
|
69
|
+
1, 0, 1, 1, 0, 1,
|
70
|
+
0, 1, 1, 0, 1, 1,
|
71
|
+
1, 0, 0, 1, 0, 1]
|
72
|
+
|
73
|
+
sub_key_8: [1, 1, 0, 1, 1, 0,
|
74
|
+
1, 1, 1, 0, 1, 1,
|
75
|
+
1, 1, 0, 0, 1, 0,
|
76
|
+
1, 1, 1, 1, 0, 1,
|
77
|
+
0, 0, 0, 1, 1, 0,
|
78
|
+
1, 0, 1, 0, 1, 0,
|
79
|
+
1, 1, 1, 1, 1, 0,
|
80
|
+
1, 0, 0, 0, 0, 1]
|
81
|
+
|
82
|
+
sub_key_9: [1, 0, 0, 1, 1, 0,
|
83
|
+
0, 1, 1, 1, 1, 0,
|
84
|
+
1, 1, 0, 0, 1, 1,
|
85
|
+
1, 0, 1, 1, 1, 1,
|
86
|
+
0, 0, 1, 0, 0, 1,
|
87
|
+
0, 0, 0, 1, 1, 1,
|
88
|
+
0, 0, 0, 0, 0, 0,
|
89
|
+
1, 1, 1, 1, 1, 1]
|
90
|
+
|
91
|
+
sub_key_10: [1, 1, 1, 1, 0, 0,
|
92
|
+
0, 1, 0, 1, 1, 0,
|
93
|
+
1, 1, 1, 1, 1, 0,
|
94
|
+
1, 1, 1, 1, 1, 0,
|
95
|
+
1, 0, 1, 0, 0, 1,
|
96
|
+
1, 1, 0, 0, 0, 1,
|
97
|
+
1, 0, 0, 0, 1, 1,
|
98
|
+
1, 0, 0, 1, 1, 0]
|
99
|
+
|
100
|
+
sub_key_11: [1, 1, 1, 1, 0, 1,
|
101
|
+
0, 0, 1, 0, 1, 1,
|
102
|
+
1, 1, 1, 1, 1, 0,
|
103
|
+
1, 0, 0, 1, 0, 1,
|
104
|
+
1, 0, 0, 0, 0, 1,
|
105
|
+
0, 0, 1, 0, 0, 0,
|
106
|
+
1, 0, 1, 1, 1, 1,
|
107
|
+
1, 1, 0, 0, 1, 1]
|
108
|
+
|
109
|
+
sub_key_12: [1, 1, 0, 1, 0, 0,
|
110
|
+
1, 1, 1, 0, 1, 1,
|
111
|
+
1, 1, 1, 0, 0, 1,
|
112
|
+
1, 1, 0, 1, 1, 1,
|
113
|
+
0, 0, 0, 1, 0, 1,
|
114
|
+
1, 1, 1, 0, 0, 0,
|
115
|
+
1, 1, 1, 0, 0, 1,
|
116
|
+
0, 1, 0, 1, 0, 1]
|
117
|
+
|
118
|
+
sub_key_13: [1, 1, 1, 0, 1, 1,
|
119
|
+
0, 1, 1, 1, 1, 1,
|
120
|
+
0, 1, 1, 0, 1, 1,
|
121
|
+
1, 1, 0, 1, 1, 0,
|
122
|
+
0, 1, 0, 1, 1, 0,
|
123
|
+
1, 1, 1, 0, 0, 0,
|
124
|
+
0, 1, 0, 1, 1, 1,
|
125
|
+
0, 1, 0, 0, 0, 0]
|
126
|
+
|
127
|
+
sub_key_14: [1, 1, 1, 1, 0, 1,
|
128
|
+
1, 0, 1, 1, 0, 1,
|
129
|
+
0, 1, 1, 1, 1, 1,
|
130
|
+
1, 0, 1, 1, 1, 0,
|
131
|
+
0, 0, 0, 0, 1, 0,
|
132
|
+
0, 1, 1, 1, 1, 0,
|
133
|
+
0, 1, 0, 1, 0, 0,
|
134
|
+
0, 0, 1, 1, 0, 1]
|
135
|
+
|
136
|
+
sub_key_15: [1, 1, 1, 1, 1, 0,
|
137
|
+
1, 0, 1, 1, 0, 1,
|
138
|
+
0, 0, 1, 1, 0, 1,
|
139
|
+
1, 1, 0, 0, 1, 1,
|
140
|
+
0, 1, 1, 0, 1, 0,
|
141
|
+
1, 0, 0, 1, 1, 1,
|
142
|
+
0, 1, 0, 0, 1, 0,
|
143
|
+
0, 0, 0, 1, 0, 0]
|
144
|
+
|
145
|
+
sub_key_16: [1, 1, 1, 1, 1, 1,
|
146
|
+
1, 1, 1, 1, 1, 1,
|
147
|
+
1, 0, 1, 0, 0, 1,
|
148
|
+
1, 1, 0, 0, 1, 1,
|
149
|
+
0, 0, 0, 1, 1, 0,
|
150
|
+
1, 0, 1, 0, 1, 1,
|
151
|
+
1, 0, 0, 0, 0, 1,
|
152
|
+
1, 1, 0, 0, 1, 1]
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class KeyScheduleTest < Test::Unit::TestCase
|
4
|
+
fixtures :key_schedule
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@key_schedule = KeySchedule.new(key_schedule(:test_key))
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_class
|
11
|
+
assert_kind_of KeySchedule, @key_schedule
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_test_key
|
15
|
+
assert_kind_of Array, @key_schedule.key
|
16
|
+
assert_equal key_schedule(:test_key), @key_schedule.key
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_sub_keys
|
20
|
+
assert_kind_of Array, @key_schedule.sub_keys
|
21
|
+
assert_equal key_schedule(:sub_key_1), @key_schedule.sub_keys[0]
|
22
|
+
assert_equal key_schedule(:sub_key_2), @key_schedule.sub_keys[1]
|
23
|
+
assert_equal key_schedule(:sub_key_3), @key_schedule.sub_keys[2]
|
24
|
+
assert_equal key_schedule(:sub_key_4), @key_schedule.sub_keys[3]
|
25
|
+
assert_equal key_schedule(:sub_key_5), @key_schedule.sub_keys[4]
|
26
|
+
assert_equal key_schedule(:sub_key_6), @key_schedule.sub_keys[5]
|
27
|
+
assert_equal key_schedule(:sub_key_7), @key_schedule.sub_keys[6]
|
28
|
+
assert_equal key_schedule(:sub_key_8), @key_schedule.sub_keys[7]
|
29
|
+
assert_equal key_schedule(:sub_key_9), @key_schedule.sub_keys[8]
|
30
|
+
assert_equal key_schedule(:sub_key_10), @key_schedule.sub_keys[9]
|
31
|
+
assert_equal key_schedule(:sub_key_11), @key_schedule.sub_keys[10]
|
32
|
+
assert_equal key_schedule(:sub_key_12), @key_schedule.sub_keys[11]
|
33
|
+
assert_equal key_schedule(:sub_key_13), @key_schedule.sub_keys[12]
|
34
|
+
assert_equal key_schedule(:sub_key_14), @key_schedule.sub_keys[13]
|
35
|
+
assert_equal key_schedule(:sub_key_15), @key_schedule.sub_keys[14]
|
36
|
+
assert_equal key_schedule(:sub_key_16), @key_schedule.sub_keys[15]
|
37
|
+
end
|
38
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + "../lib")
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'yaml'
|
5
|
+
require 'ruby-des'
|
6
|
+
|
7
|
+
class Test::Unit::TestCase
|
8
|
+
@@fixtures = {}
|
9
|
+
def self.fixtures(*list)
|
10
|
+
list.each do |fixture|
|
11
|
+
self.class_eval do
|
12
|
+
define_method(fixture) do |item|
|
13
|
+
@@fixtures[fixture] ||= File.exists?("#{fixture.to_s}.yml") ? YAML::load_file("#{fixture.to_s}.yml") : YAML::load_file("test/#{fixture.to_s}.yml")
|
14
|
+
@@fixtures[fixture][item.to_s]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/test/xor.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
e: [1, 0, 0, 0, 0, 0,
|
2
|
+
0, 0, 0, 0, 0, 1,
|
3
|
+
0, 1, 1, 1, 1, 1,
|
4
|
+
1, 1, 1, 1, 1, 1,
|
5
|
+
1, 1, 0, 1, 0, 0,
|
6
|
+
0, 0, 0, 0, 0, 0,
|
7
|
+
0, 0, 0, 0, 1, 0,
|
8
|
+
1, 0, 1, 0, 1, 0]
|
9
|
+
|
10
|
+
sub_key: [1, 0, 1, 0, 1, 1,
|
11
|
+
0, 1, 1, 1, 0, 1,
|
12
|
+
1, 0, 1, 1, 0, 1,
|
13
|
+
1, 1, 1, 1, 1, 1,
|
14
|
+
1, 1, 1, 0, 1, 0,
|
15
|
+
0, 0, 0, 1, 0, 0,
|
16
|
+
0, 0, 0, 1, 1, 0,
|
17
|
+
1, 0, 1, 1, 1, 1]
|
18
|
+
|
19
|
+
e_xor_sub_key: [0, 0, 1, 0, 1, 1,
|
20
|
+
0, 1, 1, 1, 0, 0,
|
21
|
+
1, 1, 0, 0, 1, 0,
|
22
|
+
0, 0, 0, 0, 0, 0,
|
23
|
+
0, 0, 1, 1, 1, 0,
|
24
|
+
0, 0, 0, 1, 0, 0,
|
25
|
+
0, 0, 0, 1, 0, 0,
|
26
|
+
0, 0, 0, 1, 0, 1]
|
data/test/xor_test.rb
ADDED
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-des
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: "1.0"
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Robert Sosinski
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2012-06-04 00:00:00 +08:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description:
|
22
|
+
email:
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- .gitignore
|
31
|
+
- MIT-LICENSE
|
32
|
+
- README.markdown
|
33
|
+
- Rakefile
|
34
|
+
- lib/ruby-des.rb
|
35
|
+
- lib/ruby-des/feistel.rb
|
36
|
+
- lib/ruby-des/key_schedule.rb
|
37
|
+
- lib/ruby-des/xor.rb
|
38
|
+
- test/ctx.yml
|
39
|
+
- test/ctx_test.rb
|
40
|
+
- test/feistel.yml
|
41
|
+
- test/feistel_test.rb
|
42
|
+
- test/key_schedule.yml
|
43
|
+
- test/key_schedule_test.rb
|
44
|
+
- test/test_helper.rb
|
45
|
+
- test/xor.yml
|
46
|
+
- test/xor_test.rb
|
47
|
+
has_rdoc: true
|
48
|
+
homepage:
|
49
|
+
licenses: []
|
50
|
+
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options: []
|
53
|
+
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 3
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
requirements: []
|
75
|
+
|
76
|
+
rubyforge_project: ruby-des
|
77
|
+
rubygems_version: 1.6.2
|
78
|
+
signing_key:
|
79
|
+
specification_version: 3
|
80
|
+
summary: This gem make use DES Data Encryption.
|
81
|
+
test_files:
|
82
|
+
- test/ctx.yml
|
83
|
+
- test/ctx_test.rb
|
84
|
+
- test/feistel.yml
|
85
|
+
- test/feistel_test.rb
|
86
|
+
- test/key_schedule.yml
|
87
|
+
- test/key_schedule_test.rb
|
88
|
+
- test/test_helper.rb
|
89
|
+
- test/xor.yml
|
90
|
+
- test/xor_test.rb
|