ruby-des 1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|