ruby-aes-cext 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/CHANGELOG +6 -0
- data/COPYING +20 -0
- data/README +77 -0
- data/Rakefile +154 -0
- data/doc/rdoc/classes/Aes.html +494 -0
- data/doc/rdoc/created.rid +1 -0
- data/doc/rdoc/files/CHANGELOG.html +117 -0
- data/doc/rdoc/files/COPYING.html +129 -0
- data/doc/rdoc/files/README.html +235 -0
- data/doc/rdoc/files/lib/ruby-aes_rb.html +108 -0
- data/doc/rdoc/fr_class_index.html +27 -0
- data/doc/rdoc/fr_file_index.html +30 -0
- data/doc/rdoc/fr_method_index.html +39 -0
- data/doc/rdoc/index.html +24 -0
- data/doc/rdoc/rdoc-style.css +208 -0
- data/examples/encrypt_block.rb +22 -0
- data/examples/encrypt_buffer.rb +24 -0
- data/examples/encrypt_stream.rb +39 -0
- data/examples/example_helper.rb +27 -0
- data/ext/ruby-aes/aes_alg.c +812 -0
- data/ext/ruby-aes/aes_gencons.rb +118 -0
- data/ext/ruby-aes/extconf.rb +7 -0
- data/lib/ruby-aes.rb +162 -0
- data/test/KAT_MCT/aes_kat_mct.rb +386 -0
- data/test/KAT_MCT/rijndael-vals.zip +0 -0
- data/test/KAT_MCT/table.128 +128 -0
- data/test/KAT_MCT/table.192 +128 -0
- data/test/KAT_MCT/table.256 +128 -0
- data/test/test_helper.rb +14 -0
- data/test/test_ruby-aes.rb +113 -0
- metadata +95 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
=begin
|
|
4
|
+
This file is a part of ruby-aes <http://rubyforge.org/projects/ruby-aes>
|
|
5
|
+
Written by Alex Boussinet <alex.boussinet@gmail.com>
|
|
6
|
+
|
|
7
|
+
This script generates the constant arrays needed by ruby-aes
|
|
8
|
+
=end
|
|
9
|
+
|
|
10
|
+
module AesCons
|
|
11
|
+
|
|
12
|
+
ALOG = []
|
|
13
|
+
LOG = []
|
|
14
|
+
j = 1
|
|
15
|
+
256.times do |i|
|
|
16
|
+
ALOG[i] = ALOG[i+255] = j
|
|
17
|
+
LOG[j] = i
|
|
18
|
+
j = (j ^ (j << 1) ^ (j & 0x80 != 0 ? 0x01b : 0)) & 0xff
|
|
19
|
+
end
|
|
20
|
+
LOG[1] = 0
|
|
21
|
+
|
|
22
|
+
def self.mul(a, b)
|
|
23
|
+
(a.zero? || b.zero?) ? 0 : ALOG[LOG[a] + LOG[b]]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
RCON = []
|
|
27
|
+
j = 1
|
|
28
|
+
10.times do |i|
|
|
29
|
+
RCON[i] = j << 24 & 0xff000000
|
|
30
|
+
j = mul(2, j)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
S = []
|
|
34
|
+
Si = []
|
|
35
|
+
256.times do |i|
|
|
36
|
+
x = (i != 0) ? ALOG[255 - LOG[i]] : 0
|
|
37
|
+
x ^= (x << 1) ^ (x << 2) ^ (x << 3) ^ (x << 4)
|
|
38
|
+
x = 0x63 ^ (x ^ (x >> 8))
|
|
39
|
+
S[i] = x & 0xff
|
|
40
|
+
Si[x & 0xff] = i
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.mul4(a, b)
|
|
44
|
+
return 0 if (a.zero?)
|
|
45
|
+
a = LOG[a & 0xFF]
|
|
46
|
+
a0 = (b[0] != 0) ? ALOG[(a + LOG[b[0] & 0xff]) % 255] & 0xff : 0
|
|
47
|
+
a1 = (b[1] != 0) ? ALOG[(a + LOG[b[1] & 0xff]) % 255] & 0xff : 0
|
|
48
|
+
a2 = (b[2] != 0) ? ALOG[(a + LOG[b[2] & 0xff]) % 255] & 0xff : 0
|
|
49
|
+
a3 = (b[3] != 0) ? ALOG[(a + LOG[b[3] & 0xff]) % 255] & 0xff : 0
|
|
50
|
+
return a0 << 24 | a1 << 16 | a2 << 8 | a3
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
G = [
|
|
54
|
+
[2, 1, 1, 3],[3, 2, 1, 1],[1, 3, 2, 1],[1, 1, 3, 2],
|
|
55
|
+
[0, 0, 0, 1],[0, 0, 1, 0],[0, 1, 0, 0],[1, 0, 0, 0]
|
|
56
|
+
]
|
|
57
|
+
Gi = [
|
|
58
|
+
[14, 9, 13, 11], [11, 14, 9, 13], [13, 11, 14, 9],[9, 13, 11, 14],
|
|
59
|
+
[0, 0, 0, 1],[0, 0, 1, 0],[0, 1, 0, 0],[1, 0, 0, 0]
|
|
60
|
+
]
|
|
61
|
+
Te0, Te1, Te2, Te3 = [], [], [], []
|
|
62
|
+
S0, S1, S2, S3 = [], [], [], []
|
|
63
|
+
Td0, Td1, Td2, Td3 = [], [], [], []
|
|
64
|
+
Si0, Si1, Si2, Si3 = [], [], [], []
|
|
65
|
+
256.times do |t|
|
|
66
|
+
s = S[t]
|
|
67
|
+
Te0[t] = mul4(s, G[0])
|
|
68
|
+
Te1[t] = mul4(s, G[1])
|
|
69
|
+
Te2[t] = mul4(s, G[2])
|
|
70
|
+
Te3[t] = mul4(s, G[3])
|
|
71
|
+
S0[t] = mul4(s, G[4])
|
|
72
|
+
S1[t] = mul4(s, G[5])
|
|
73
|
+
S2[t] = mul4(s, G[6])
|
|
74
|
+
S3[t] = mul4(s, G[7])
|
|
75
|
+
s = Si[t]
|
|
76
|
+
Td0[t] = mul4(s, Gi[0])
|
|
77
|
+
Td1[t] = mul4(s, Gi[1])
|
|
78
|
+
Td2[t] = mul4(s, Gi[2])
|
|
79
|
+
Td3[t] = mul4(s, Gi[3])
|
|
80
|
+
Si0[t] = mul4(s, Gi[4])
|
|
81
|
+
Si1[t] = mul4(s, Gi[5])
|
|
82
|
+
Si2[t] = mul4(s, Gi[6])
|
|
83
|
+
Si3[t] = mul4(s, Gi[7])
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
File.open("aes_cons.h" , "w+") do |f|
|
|
87
|
+
f.write <<-STOP
|
|
88
|
+
/*
|
|
89
|
+
* This file is a part of ruby-aes <http://rubyforge.org/projects/ruby-aes>
|
|
90
|
+
* Written by Alex Boussinet <alex.boussinet@gmail.com>
|
|
91
|
+
*
|
|
92
|
+
* aes_cons.h - AES Constant Arrays for ruby-aes
|
|
93
|
+
*/
|
|
94
|
+
|
|
95
|
+
#ifndef __AES_CONS__
|
|
96
|
+
#define __AES_CONS__
|
|
97
|
+
|
|
98
|
+
STOP
|
|
99
|
+
["RCON", "Te0", "Te1", "Te2", "Te3", "S0", "S1", "S2", "S3",
|
|
100
|
+
"Td0", "Td1", "Td2", "Td3", "Si0", "Si1", "Si2", "Si3"].each do |x|
|
|
101
|
+
f.write "uint " + x + "[] = {\n"
|
|
102
|
+
line = " " * 4
|
|
103
|
+
module_eval(x).each do |y|
|
|
104
|
+
z = "0x%08x" % y
|
|
105
|
+
line << ", " if line.length > 4
|
|
106
|
+
if (line.length + z.length) > 79
|
|
107
|
+
f.write line.chop + "\n"
|
|
108
|
+
line = " " * 4
|
|
109
|
+
end
|
|
110
|
+
line << z
|
|
111
|
+
end
|
|
112
|
+
f.write line unless line.length == 4
|
|
113
|
+
f.write "\n};\n\n"
|
|
114
|
+
end
|
|
115
|
+
f.write "#endif\n"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
end # AesCons
|
data/lib/ruby-aes.rb
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
This file is a part of ruby-aes <http://rubyforge.org/projects/ruby-aes>
|
|
3
|
+
Written by Alex Boussinet <alex.boussinet@gmail.com>
|
|
4
|
+
|
|
5
|
+
==Valid modes are:
|
|
6
|
+
* ECB (Electronic Code Book)
|
|
7
|
+
* CBC (Cipher Block Chaining)
|
|
8
|
+
* OFB (Output Feedback)
|
|
9
|
+
* CFB (Cipher Feedback)
|
|
10
|
+
|
|
11
|
+
==Valid key length:
|
|
12
|
+
* 128 bits
|
|
13
|
+
* 192 bits
|
|
14
|
+
* 256 bits
|
|
15
|
+
|
|
16
|
+
==API calls:
|
|
17
|
+
Default key_length: 128
|
|
18
|
+
Default mode: 'ECB'
|
|
19
|
+
Default IV: 16 null chars ("00" * 16 in hex format)
|
|
20
|
+
Default key: 16 null chars ("00" * 16 in hex format)
|
|
21
|
+
Default input text: "PLAINTEXT"
|
|
22
|
+
|
|
23
|
+
Aes.check_key(key_string, key_length)
|
|
24
|
+
Aes.check_iv(iv_string)
|
|
25
|
+
Aes.check_kl(key_length)
|
|
26
|
+
Aes.check_mode(mode)
|
|
27
|
+
Aes.init(key_length, mode, key, iv)
|
|
28
|
+
Aes.encrypt_block(key_length, mode, key, iv, block) # no padding
|
|
29
|
+
Aes.decrypt_block(key_length, mode, key, iv, block) # no padding
|
|
30
|
+
Aes.encrypt_buffer(key_length, mode, key, iv, block) # padding
|
|
31
|
+
Aes.decrypt_buffer(key_length, mode, key, iv, block) # padding
|
|
32
|
+
Aes.encrypt_stream(key_length, mode, key, iv, sin, sout)
|
|
33
|
+
Aes.decrypt_stream(key_length, mode, key, iv, sin, sout)
|
|
34
|
+
Aes.bs() # block size for read operations (stream)
|
|
35
|
+
Aes.bs=(bs)
|
|
36
|
+
=end
|
|
37
|
+
|
|
38
|
+
module Aes
|
|
39
|
+
|
|
40
|
+
require 'ruby-aes/aes_alg'
|
|
41
|
+
|
|
42
|
+
@@aes = nil
|
|
43
|
+
@@bs = 4096
|
|
44
|
+
|
|
45
|
+
def Aes.bs(); return @@bs end
|
|
46
|
+
def Aes.bs=(bs); @@bs = bs.to_i; @@bs==0 ? 4096 : @@bs = @@bs - @@bs%16 end
|
|
47
|
+
|
|
48
|
+
def Aes.check_key(key_string, kl = 128)
|
|
49
|
+
kl = Aes.check_kl(kl)
|
|
50
|
+
k = key_string.length
|
|
51
|
+
raise "Bad key string or bad key length" if (k != kl/8) && (k != kl/4)
|
|
52
|
+
hex = (key_string =~ /[a-f0-9A-F]{#{k}}/) == 0 && (k == kl/4)
|
|
53
|
+
bin = ! hex
|
|
54
|
+
if ! (([32, 48, 64].include?(k) && hex) ||
|
|
55
|
+
([16, 24, 32].include?(k) && bin))
|
|
56
|
+
raise "Bad key string"
|
|
57
|
+
end
|
|
58
|
+
hex ? [key_string].pack("H*") : key_string
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def Aes.check_iv(iv_string)
|
|
62
|
+
k = iv_string.length
|
|
63
|
+
hex = (iv_string =~ /[a-f0-9A-F]{#{k}}/) == 0
|
|
64
|
+
bin = ! hex
|
|
65
|
+
if k == 32 && hex
|
|
66
|
+
return [iv_string].pack("H*")
|
|
67
|
+
elsif k == 16 && bin
|
|
68
|
+
return iv_string
|
|
69
|
+
else
|
|
70
|
+
raise "Bad IV string"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def Aes.check_mode (mode)
|
|
75
|
+
case mode
|
|
76
|
+
when 'ECB', 'CBC', 'OFB', 'CFB'
|
|
77
|
+
else raise "Bad cipher mode"
|
|
78
|
+
end
|
|
79
|
+
mode
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def Aes.check_kl(key_length)
|
|
83
|
+
case key_length
|
|
84
|
+
when 128, 192, 256
|
|
85
|
+
else raise "Bad key length"
|
|
86
|
+
end
|
|
87
|
+
key_length
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def Aes.init(keyl, mode, key, iv)
|
|
91
|
+
unless @@aes
|
|
92
|
+
@@aes = AesAlg.new(Aes.check_kl(keyl), Aes.check_mode(mode),
|
|
93
|
+
Aes.check_key(key, keyl), iv ? Aes.check_iv(iv) : nil)
|
|
94
|
+
else
|
|
95
|
+
@@aes.init(Aes.check_kl(keyl), Aes.check_mode(mode),
|
|
96
|
+
Aes.check_key(key, keyl), iv ? Aes.check_iv(iv) : nil)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def Aes.encrypt_block(keyl, mode, key, iv, block = "DEFAULT PLAINTXT")
|
|
101
|
+
raise "Bad Block size" if block.length < 16 || block.length > 16
|
|
102
|
+
Aes.init(keyl, mode, key, iv)
|
|
103
|
+
@@aes.encrypt_block(block)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def Aes.decrypt_block(keyl, mode, key, iv, block = "DEFAULT PLAINTXT")
|
|
107
|
+
Aes.init(keyl, mode, key, iv)
|
|
108
|
+
@@aes.decrypt_block(block)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def Aes.encrypt_buffer(keyl, mode, key, iv, buffer = "PLAINTEXT")
|
|
112
|
+
Aes.init(keyl, mode, key, iv)
|
|
113
|
+
@@aes.encrypt_buffer(buffer)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def Aes.decrypt_buffer(keyl, mode, key, iv, buffer = "DEFAULT PLAINTXT")
|
|
117
|
+
raise "Bad Block size" if buffer.length < 16
|
|
118
|
+
Aes.init(keyl, mode, key, iv)
|
|
119
|
+
@@aes.decrypt_buffer(buffer)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def Aes.encrypt_stream(keyl, mode, key, iv, sin = STDIN, sout = STDOUT)
|
|
123
|
+
Aes.init(keyl, mode, key, iv)
|
|
124
|
+
case sout
|
|
125
|
+
when String, Array, IO
|
|
126
|
+
else
|
|
127
|
+
raise "Bad output stream (String, Array, IO)"
|
|
128
|
+
end
|
|
129
|
+
case sin
|
|
130
|
+
when String
|
|
131
|
+
sout << @@aes.encrypt_buffer(sin)
|
|
132
|
+
when IO
|
|
133
|
+
while buf = sin.read(@@bs)
|
|
134
|
+
sout << ((buf.length % 16).zero? ? @@aes.encrypt_blocks(buf) :
|
|
135
|
+
@@aes.encrypt_buffer(buf))
|
|
136
|
+
end
|
|
137
|
+
else
|
|
138
|
+
raise "Bad input stream (String, IO)"
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def Aes.decrypt_stream(keyl, mode, key, iv, sin = STDIN, sout = STDOUT)
|
|
143
|
+
Aes.init(keyl, mode, key, iv)
|
|
144
|
+
case sout
|
|
145
|
+
when String, Array, IO
|
|
146
|
+
else
|
|
147
|
+
raise "Bad output stream (String, Array, IO)"
|
|
148
|
+
end
|
|
149
|
+
case sin
|
|
150
|
+
when String
|
|
151
|
+
sout << @@aes.decrypt_buffer(sin)
|
|
152
|
+
when IO
|
|
153
|
+
while buf = sin.read(@@bs)
|
|
154
|
+
sout << (sin.eof? ? @@aes.decrypt_buffer(buf) :
|
|
155
|
+
@@aes.decrypt_blocks(buf))
|
|
156
|
+
end
|
|
157
|
+
else
|
|
158
|
+
raise "Bad input stream (String, IO)"
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
end # end Aes
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
=begin
|
|
4
|
+
This file is a part of ruby-aes <http://rubyforge.org/projects/ruby-aes>
|
|
5
|
+
Written by Alex Boussinet <alex.boussinet@gmail.com>
|
|
6
|
+
|
|
7
|
+
KAT Tests and MCT tests according to katmct.pdf file.
|
|
8
|
+
<http://csrc.nist.gov/encryption/aes/katmct/katmct.htm>
|
|
9
|
+
See rijndael-vals.zip
|
|
10
|
+
=end
|
|
11
|
+
|
|
12
|
+
require File.dirname(__FILE__) + '/../test_helper.rb'
|
|
13
|
+
|
|
14
|
+
def cbc_decrypt_mct(output)
|
|
15
|
+
output.write <<EOT
|
|
16
|
+
|
|
17
|
+
=========================
|
|
18
|
+
|
|
19
|
+
FILENAME: "cbc_d_m.txt"
|
|
20
|
+
|
|
21
|
+
Cipher Block Chaining (CBC) Mode - DECRYPTION
|
|
22
|
+
Monte Carlo Test
|
|
23
|
+
|
|
24
|
+
Algorithm Name: Rijndael
|
|
25
|
+
|
|
26
|
+
==========
|
|
27
|
+
|
|
28
|
+
EOT
|
|
29
|
+
[128, 192, 256].each { |kl|
|
|
30
|
+
output.write "KEYSIZE=#{kl}\n\n"
|
|
31
|
+
key = "0" * (kl/4)
|
|
32
|
+
ct = iv = "0" * 32
|
|
33
|
+
opt = pt = nil
|
|
34
|
+
400.times { |i|
|
|
35
|
+
output.write "I=#{i}\nKEY=#{key}\nIV=#{iv}\nCT=#{ct}\n"
|
|
36
|
+
10000.times { |j|
|
|
37
|
+
opt = pt
|
|
38
|
+
pt = Aes.decrypt_block(kl, 'ECB', key, iv,
|
|
39
|
+
[ct].pack("H*")).unpack("H*")[0]
|
|
40
|
+
pt = "%032X" % (pt.hex ^ iv.hex)
|
|
41
|
+
iv = ct
|
|
42
|
+
ct = pt
|
|
43
|
+
}
|
|
44
|
+
case kl
|
|
45
|
+
when 128
|
|
46
|
+
npt = pt
|
|
47
|
+
when 192, 256
|
|
48
|
+
x = -(kl/4-32)
|
|
49
|
+
npt = opt[x..-1] + pt
|
|
50
|
+
end
|
|
51
|
+
key = "%0#{kl/4}X" % (key.hex ^ npt.hex)
|
|
52
|
+
output.write "PT=#{pt}\n\n"
|
|
53
|
+
}
|
|
54
|
+
output.write "=========================\n\n"
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def cbc_encrypt_mct(output)
|
|
59
|
+
output.write <<EOT
|
|
60
|
+
|
|
61
|
+
=========================
|
|
62
|
+
|
|
63
|
+
FILENAME: "cbc_e_m.txt"
|
|
64
|
+
|
|
65
|
+
Cipher Block Chaining (CBC) Mode - ENCRYPTION
|
|
66
|
+
Monte Carlo Test
|
|
67
|
+
|
|
68
|
+
Algorithm Name: Rijndael
|
|
69
|
+
|
|
70
|
+
==========
|
|
71
|
+
|
|
72
|
+
EOT
|
|
73
|
+
[128, 192, 256].each { |kl|
|
|
74
|
+
output.write "KEYSIZE=#{kl}\n\n"
|
|
75
|
+
key = "0" * (kl/4)
|
|
76
|
+
pt = iv = "0" * 32
|
|
77
|
+
oct = ct = nil
|
|
78
|
+
400.times { |i|
|
|
79
|
+
output.write "I=#{i}\nKEY=#{key}\nIV=#{iv}\nPT=#{pt}\n"
|
|
80
|
+
10000.times { |j|
|
|
81
|
+
oct = ct
|
|
82
|
+
pt = "%032X" % (pt.hex ^ iv.hex)
|
|
83
|
+
ct = Aes.encrypt_block(kl, 'ECB', key, iv,
|
|
84
|
+
[pt].pack("H*")).unpack("H*")[0]
|
|
85
|
+
if j == 0 then pt = iv else pt = oct end
|
|
86
|
+
iv = ct
|
|
87
|
+
}
|
|
88
|
+
case kl
|
|
89
|
+
when 128
|
|
90
|
+
nct = ct
|
|
91
|
+
when 192, 256
|
|
92
|
+
x = -(kl/4-32)
|
|
93
|
+
nct = oct[x..-1] + ct
|
|
94
|
+
end
|
|
95
|
+
key = "%0#{kl/4}X" % (key.hex ^ nct.hex)
|
|
96
|
+
output.write "CT=#{ct}\n\n"
|
|
97
|
+
}
|
|
98
|
+
output.write "=========================\n\n"
|
|
99
|
+
}
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def ecb_decrypt_mct(output)
|
|
103
|
+
output.write <<EOT
|
|
104
|
+
|
|
105
|
+
=========================
|
|
106
|
+
|
|
107
|
+
FILENAME: "ecb_d_m.txt"
|
|
108
|
+
|
|
109
|
+
Electronic Codebook (ECB) Mode - DECRYPTION
|
|
110
|
+
Monte Carlo Test
|
|
111
|
+
|
|
112
|
+
Algorithm Name: Rijndael
|
|
113
|
+
|
|
114
|
+
=========================
|
|
115
|
+
|
|
116
|
+
EOT
|
|
117
|
+
[128, 192, 256].each { |kl|
|
|
118
|
+
output.write "KEYSIZE=#{kl}\n\n"
|
|
119
|
+
key = "0" * (kl/4)
|
|
120
|
+
ct = "0" * 32
|
|
121
|
+
opt = pt = nil
|
|
122
|
+
400.times { |i|
|
|
123
|
+
output.write "I=#{i}\nKEY=#{key}\nCT=#{ct}\n"
|
|
124
|
+
10000.times { |j|
|
|
125
|
+
opt = pt
|
|
126
|
+
pt = Aes.decrypt_block(kl, 'ECB', key, nil,
|
|
127
|
+
[ct].pack("H*")).unpack("H*")[0]
|
|
128
|
+
ct = pt
|
|
129
|
+
}
|
|
130
|
+
case kl
|
|
131
|
+
when 128
|
|
132
|
+
npt = pt
|
|
133
|
+
when 192, 256
|
|
134
|
+
x = -(kl/4-32)
|
|
135
|
+
npt = opt[x..-1] + pt
|
|
136
|
+
end
|
|
137
|
+
key = "%0#{kl/4}X" % (key.hex ^ npt.hex)
|
|
138
|
+
ct = pt
|
|
139
|
+
output.write "PT=#{pt}\n\n"
|
|
140
|
+
}
|
|
141
|
+
output.write "=========================\n\n"
|
|
142
|
+
}
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def ecb_encrypt_mct(output)
|
|
146
|
+
output.write <<EOT
|
|
147
|
+
|
|
148
|
+
=========================
|
|
149
|
+
|
|
150
|
+
FILENAME: "ecb_e_m.txt"
|
|
151
|
+
|
|
152
|
+
Electronic Codebook (ECB) Mode - ENCRYPTION
|
|
153
|
+
Monte Carlo Test
|
|
154
|
+
|
|
155
|
+
Algorithm Name: Rijndael
|
|
156
|
+
|
|
157
|
+
=========================
|
|
158
|
+
|
|
159
|
+
EOT
|
|
160
|
+
[128, 192, 256].each { |kl|
|
|
161
|
+
output.write "KEYSIZE=#{kl}\n\n"
|
|
162
|
+
key = "0" * (kl/4)
|
|
163
|
+
pt = "0" * 32
|
|
164
|
+
oct = ct = nil
|
|
165
|
+
400.times { |i|
|
|
166
|
+
output.write "I=#{i}\nKEY=#{key}\nPT=#{pt}\n"
|
|
167
|
+
10000.times { |j|
|
|
168
|
+
oct = ct
|
|
169
|
+
ct = Aes.encrypt_block(kl, 'ECB', key, nil,
|
|
170
|
+
[pt].pack("H*")).unpack("H*")[0]
|
|
171
|
+
pt = ct
|
|
172
|
+
}
|
|
173
|
+
case kl
|
|
174
|
+
when 128
|
|
175
|
+
nct = ct
|
|
176
|
+
when 192, 256
|
|
177
|
+
x = -(kl/4-32)
|
|
178
|
+
nct = oct[x..-1] + ct
|
|
179
|
+
end
|
|
180
|
+
key = "%0#{kl/4}X" % (key.hex ^ nct.hex)
|
|
181
|
+
pt = ct
|
|
182
|
+
output.write "CT=#{ct}\n\n"
|
|
183
|
+
}
|
|
184
|
+
output.write "=========================\n\n"
|
|
185
|
+
}
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def ecb_iv(output)
|
|
189
|
+
output.write <<EOT
|
|
190
|
+
|
|
191
|
+
=========================
|
|
192
|
+
|
|
193
|
+
FILENAME: "ecb_iv.txt"
|
|
194
|
+
|
|
195
|
+
Electronic Codebook (ECB) Mode
|
|
196
|
+
Intermediate Value Known Answer Tests
|
|
197
|
+
|
|
198
|
+
Algorithm Name: Rijndael
|
|
199
|
+
|
|
200
|
+
==========
|
|
201
|
+
|
|
202
|
+
EOT
|
|
203
|
+
if (AesAlg.respond_to? :c_extension)
|
|
204
|
+
@output.write <<EOT
|
|
205
|
+
Not Implemented
|
|
206
|
+
|
|
207
|
+
==========
|
|
208
|
+
|
|
209
|
+
EOT
|
|
210
|
+
else
|
|
211
|
+
$output = output
|
|
212
|
+
AesAlg.class_eval do
|
|
213
|
+
alias :encrypt_block_original :_encrypt_block
|
|
214
|
+
alias :decrypt_original_block :_decrypt_block
|
|
215
|
+
def _encrypt_block
|
|
216
|
+
addRoundKey 0
|
|
217
|
+
1.upto(@nr) { |n|
|
|
218
|
+
subBytes
|
|
219
|
+
shiftRows
|
|
220
|
+
mixColumns unless n == @nr
|
|
221
|
+
addRoundKey n
|
|
222
|
+
$output.puts "CT#{n}=#{@state.unpack("H*")[0]}" unless (@nr-n).zero?
|
|
223
|
+
}
|
|
224
|
+
@state
|
|
225
|
+
end
|
|
226
|
+
def _decrypt_block
|
|
227
|
+
addRoundKey @nr
|
|
228
|
+
(@nr-1).downto(0) { |n|
|
|
229
|
+
ishiftRows
|
|
230
|
+
isubBytes
|
|
231
|
+
$output.puts "PT#{@nr-n}=#{@state.unpack("H*")[0]}" unless n.zero?
|
|
232
|
+
addRoundKey n
|
|
233
|
+
imixColumns unless n == 0
|
|
234
|
+
}
|
|
235
|
+
@state
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
[128, 192, 256].each { |kl|
|
|
239
|
+
output.write "KEYSIZE=#{kl}\n"
|
|
240
|
+
key = ""
|
|
241
|
+
(kl/8).times do |n| key << n.chr end
|
|
242
|
+
output.write "KEY=#{key.unpack("H*")[0]}\n\n"
|
|
243
|
+
output.write "Intermediate Ciphertext Values (Encryption)\n\n"
|
|
244
|
+
pt = ""
|
|
245
|
+
16.times do |n| pt << n.chr end
|
|
246
|
+
output.write "PT=#{pt.unpack("H*")[0]}\n"
|
|
247
|
+
ct = Aes.encrypt_block(kl, 'ECB', key, nil, pt)
|
|
248
|
+
output.write "CT=#{ct.unpack("H*")[0]}\n\n"
|
|
249
|
+
|
|
250
|
+
output.write "Intermediate Ciphertext Values (Decryption)\n\n"
|
|
251
|
+
output.write "CT=#{ct.unpack("H*")[0]}\n"
|
|
252
|
+
npt = Aes.decrypt_block(kl, 'ECB', key, nil, ct)
|
|
253
|
+
output.write "PT=#{npt.unpack("H*")[0]}\n\n"
|
|
254
|
+
|
|
255
|
+
output.write "==========\n\n"
|
|
256
|
+
}
|
|
257
|
+
AesAlg.class_eval do
|
|
258
|
+
alias :_block_encrypt :encrypt_block_original
|
|
259
|
+
alias :_block_decrypt :decrypt_block_original
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def ecb_tbl(output)
|
|
265
|
+
output.write <<EOT
|
|
266
|
+
|
|
267
|
+
=========================
|
|
268
|
+
|
|
269
|
+
FILENAME: "ecb_tbl.txt"
|
|
270
|
+
|
|
271
|
+
Electronic Codebook (ECB) Mode
|
|
272
|
+
Tables Known Answer Tests
|
|
273
|
+
|
|
274
|
+
Algorithm Name: Rijndael
|
|
275
|
+
Tables tested: S, Si, LOG, ALOG, RCON, Te0-4 Td0-4
|
|
276
|
+
|
|
277
|
+
==========
|
|
278
|
+
|
|
279
|
+
EOT
|
|
280
|
+
[128, 192, 256].each { |kl|
|
|
281
|
+
output.write "KEYSIZE=#{kl}\n\n"
|
|
282
|
+
File.open("table.#{kl}", "r") { |f|
|
|
283
|
+
begin
|
|
284
|
+
1.upto(64) { |i|
|
|
285
|
+
key, *pt = f.readline.split(" ")
|
|
286
|
+
pt = pt.join
|
|
287
|
+
ct = Aes.encrypt_block(kl, 'ECB', key, nil, [pt].pack("H*"))
|
|
288
|
+
output.write "I=#{i}\nKEY=#{key}\nPT=#{pt}\nCT=#{ct.unpack("H*")[0]}\n\n"
|
|
289
|
+
}
|
|
290
|
+
65.upto(128) { |i|
|
|
291
|
+
key, *ct = f.readline.split(" ")
|
|
292
|
+
ct = ct.join
|
|
293
|
+
pt = Aes.encrypt_block(kl, 'ECB', key, nil, [ct].pack("H*"))
|
|
294
|
+
output.write "I=#{i}\nKEY=#{key}\nPT=#{pt.unpack("H*")[0]}\nCT=#{ct}\n\n"
|
|
295
|
+
}
|
|
296
|
+
rescue
|
|
297
|
+
raise "Bad Table File"
|
|
298
|
+
end
|
|
299
|
+
}
|
|
300
|
+
output.write "==========\n\n"
|
|
301
|
+
}
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def ecb_vt(output)
|
|
305
|
+
output.write <<EOT
|
|
306
|
+
|
|
307
|
+
=========================
|
|
308
|
+
|
|
309
|
+
FILENAME: "ecb_vt.txt"
|
|
310
|
+
|
|
311
|
+
Electronic Codebook (ECB) Mode
|
|
312
|
+
Variable Text Known Answer Tests
|
|
313
|
+
|
|
314
|
+
Algorithm Name: Rijndael
|
|
315
|
+
|
|
316
|
+
==========
|
|
317
|
+
|
|
318
|
+
EOT
|
|
319
|
+
[128, 192, 256].each { |kl|
|
|
320
|
+
key = "0" * (kl/4)
|
|
321
|
+
output.write "KEYSIZE=#{kl}\n\nKEY=#{key}\n\n"
|
|
322
|
+
(127).downto(0) { |b|
|
|
323
|
+
i = 128 - b
|
|
324
|
+
pt = "%032X" % (1 << b)
|
|
325
|
+
ct = Aes.encrypt_block(kl, 'ECB', key, nil, [pt].pack("H*"))
|
|
326
|
+
output.write "I=#{i}\nPT=#{pt}\nCT=#{ct.unpack("H*")[0]}\n\n"
|
|
327
|
+
}
|
|
328
|
+
output.write "==========\n\n"
|
|
329
|
+
}
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def ecb_vk(output)
|
|
333
|
+
pt = "00000000000000000000000000000000"
|
|
334
|
+
output.write <<EOT
|
|
335
|
+
|
|
336
|
+
=========================
|
|
337
|
+
|
|
338
|
+
FILENAME: "ecb_vk.txt"
|
|
339
|
+
|
|
340
|
+
Electronic Codebook (ECB) Mode
|
|
341
|
+
Variable Key Known Answer Tests
|
|
342
|
+
|
|
343
|
+
Algorithm Name: Rijndael
|
|
344
|
+
|
|
345
|
+
==========
|
|
346
|
+
EOT
|
|
347
|
+
[128, 192, 256].each { |kl|
|
|
348
|
+
output.write "KEYSIZE=#{kl}\n\nPT=#{pt}\n\n"
|
|
349
|
+
(kl-1).downto(0) { |b|
|
|
350
|
+
i = kl - b
|
|
351
|
+
key = "%0#{kl/4}X" % (1 << b)
|
|
352
|
+
ct = Aes.encrypt_block(kl, 'ECB', key, nil, [pt].pack("H*"))
|
|
353
|
+
output.write "I=#{i}\nKEY=#{key}\nCT=#{ct.unpack("H*")[0]}\n\n"
|
|
354
|
+
}
|
|
355
|
+
output.write "==========\n\n"
|
|
356
|
+
}
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def kat_tests
|
|
360
|
+
puts "Writing ecb_vk.txt..."
|
|
361
|
+
File.open("ecb_vk.txt") { |f| ecb_vk f }
|
|
362
|
+
puts "Writing ecb_vt.txt..."
|
|
363
|
+
File.open("ecb_vt.txt") { |f| ecb_vt f }
|
|
364
|
+
puts "Writing ecb_tbl.txt..."
|
|
365
|
+
File.open("ecb_tbl.txt") { |f| ecb_tbl f }
|
|
366
|
+
puts "Writing ecb_iv.txt..."
|
|
367
|
+
File.open("ecb_iv.txt") { |f| ecb_iv f }
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
def mct_tests
|
|
371
|
+
puts "Writing ecb_e_m.txt..."
|
|
372
|
+
File.open("ecb_e_m.txt") { |f| ecb_encrypt_mct f }
|
|
373
|
+
puts "Writing ecb_d_m.txt..."
|
|
374
|
+
File.open("ecb_d_m.txt") { |f| ecb_decrypt_mct f }
|
|
375
|
+
puts "Writing cbc_e_m.txt..."
|
|
376
|
+
File.open("cbc_e_m.txt") { |f| cbc_encrypt_mct f }
|
|
377
|
+
puts "Writing cbc_d_m.txt..."
|
|
378
|
+
File.open("cbc_d_m.txt") { |f| cbc_decrypt_mct f }
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
if __FILE__ == $0
|
|
382
|
+
puts "Performing KAT Tests..."
|
|
383
|
+
kat_tests
|
|
384
|
+
puts "Performing MCT Tests... VERY time consuming !"
|
|
385
|
+
mct_tests
|
|
386
|
+
end
|
|
Binary file
|