ruby-aes-normal 1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/lib/ruby-aes.rb +162 -0
- data/lib/ruby-aes/aes_alg.rb +277 -0
- data/lib/ruby-aes/aes_cons.rb +216 -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 +93 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'ruby-aes'
|
4
|
+
require 'example_helper'
|
5
|
+
|
6
|
+
class RubyAES_buffer
|
7
|
+
|
8
|
+
include RubyAES_helper
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
setup
|
12
|
+
puts "Using #{@kl}-#{@mode} encryption/decryption"
|
13
|
+
pt = "The quick brown fox jumps over the lazy dog"
|
14
|
+
puts "Plaintext is: '#{pt}'"
|
15
|
+
puts "(a buffer will be padded so that its length will be a multiple of 16)"
|
16
|
+
ct = Aes.encrypt_buffer(@kl, @mode, @keys[@kl], @iv, pt)
|
17
|
+
puts "Ciphertext (unpacked) is: #{ct.unpack("H*").first}"
|
18
|
+
npt = Aes.decrypt_buffer(@kl, @mode, @keys[@kl], @iv, ct)
|
19
|
+
puts "Decrypted ciphertext is: '#{npt}'"
|
20
|
+
puts "(should be: '#{pt}')"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
RubyAES_buffer.new
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'ruby-aes'
|
4
|
+
require 'example_helper'
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
class RubyAES_stream
|
8
|
+
|
9
|
+
include RubyAES_helper
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
setup
|
13
|
+
puts "Using #{@kl}-#{@mode} encryption/decryption"
|
14
|
+
file = "_ruby-aes_encrypt_stream_"
|
15
|
+
|
16
|
+
sin = File.open(file, "w+b")
|
17
|
+
sin.puts "The quick brown fox jumps over the lazy dog"
|
18
|
+
sin.rewind
|
19
|
+
sout = File.open("#{file}.aes", "w+b")
|
20
|
+
Aes.encrypt_stream(@kl, @mode, @keys[@kl], @iv, sin, sout)
|
21
|
+
sin.close
|
22
|
+
sout.close
|
23
|
+
|
24
|
+
sin = File.open("#{file}.aes", "rb")
|
25
|
+
sout = File.open("#{file}.plain", "w+b")
|
26
|
+
Aes.decrypt_stream(@kl, @mode, @keys[@kl], @iv, sin, sout)
|
27
|
+
sin.close
|
28
|
+
sout.close
|
29
|
+
|
30
|
+
if IO.read(file) == IO.read("#{file}.plain")
|
31
|
+
puts "The decrypted file is exactly the same as the original one"
|
32
|
+
else
|
33
|
+
puts "The decrypted file differs from the orginal one"
|
34
|
+
end
|
35
|
+
FileUtils.rm_f [ file, "#{file}.aes", "#{file}.plain" ]
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
RubyAES_stream.new
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module RubyAES_helper
|
4
|
+
|
5
|
+
KEY_LENGTH = [128,192,256].freeze
|
6
|
+
MODES = ['ECB','CBC','OFB','CFB'].freeze
|
7
|
+
|
8
|
+
def random_fill(n, buffer)
|
9
|
+
n.times do
|
10
|
+
buffer << rand(256).chr
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def setup
|
15
|
+
@keys = {}
|
16
|
+
KEY_LENGTH.each do |kl|
|
17
|
+
@keys[kl] = ""
|
18
|
+
random_fill(kl/8, @keys[kl])
|
19
|
+
end
|
20
|
+
|
21
|
+
@iv = ""; random_fill(16, @iv)
|
22
|
+
@pt = ""; random_fill(64, @pt)
|
23
|
+
@kl = KEY_LENGTH[(rand * KEY_LENGTH.length).to_i]
|
24
|
+
@mode = MODES[(rand * MODES.length).to_i]
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
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,277 @@
|
|
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
|
+
ruby-aes (non-optimized version)
|
6
|
+
Adapted from the Rijndael Specifications (dfips-AES.pdf)
|
7
|
+
=end
|
8
|
+
|
9
|
+
require 'ruby-aes/aes_cons'
|
10
|
+
|
11
|
+
class AesAlg
|
12
|
+
include AesCons
|
13
|
+
|
14
|
+
def subBytes
|
15
|
+
i = 0
|
16
|
+
@state.each_byte do |b|
|
17
|
+
@state[i] = S_BOX[b]
|
18
|
+
i+=1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
protected :subBytes
|
22
|
+
|
23
|
+
def isubBytes
|
24
|
+
i = 0
|
25
|
+
@state.each_byte do |b|
|
26
|
+
@state[i] = IS_BOX[b]
|
27
|
+
i+=1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
protected :isubBytes
|
31
|
+
|
32
|
+
def shiftRows
|
33
|
+
@state[1], @state[5], @state[9], @state[13] =
|
34
|
+
@state[5], @state[9], @state[13], @state[1]
|
35
|
+
@state[2], @state[6], @state[10], @state[14] =
|
36
|
+
@state[10], @state[14], @state[2], @state[6]
|
37
|
+
@state[3], @state[7], @state[11], @state[15] =
|
38
|
+
@state[15], @state[3], @state[7], @state[11]
|
39
|
+
end
|
40
|
+
protected :shiftRows
|
41
|
+
|
42
|
+
def ishiftRows
|
43
|
+
@state[1], @state[5], @state[9], @state[13] =
|
44
|
+
@state[13], @state[1], @state[5], @state[9]
|
45
|
+
@state[2], @state[6], @state[10], @state[14] =
|
46
|
+
@state[10], @state[14], @state[2], @state[6]
|
47
|
+
@state[3], @state[7], @state[11], @state[15] =
|
48
|
+
@state[7], @state[11], @state[15], @state[3]
|
49
|
+
end
|
50
|
+
protected :ishiftRows
|
51
|
+
|
52
|
+
def mixColumns
|
53
|
+
t = "\000" * 16
|
54
|
+
4.times do |c|
|
55
|
+
t[c*4] = G2X.at(@state[c*4]) ^ G3X.at(@state[1+c*4]) ^
|
56
|
+
@state[2+c*4] ^ @state[3+c*4]
|
57
|
+
t[1+c*4] = @state[c*4] ^ G2X.at(@state[1+c*4]) ^
|
58
|
+
G3X.at(@state[2+c*4]) ^ @state[3+c*4]
|
59
|
+
t[2+c*4] = @state[c*4] ^ @state[1+c*4] ^
|
60
|
+
G2X.at(@state[2+c*4]) ^ G3X.at(@state[3+c*4])
|
61
|
+
t[3+c*4] = G3X.at(@state[c*4]) ^ @state[1+c*4] ^
|
62
|
+
@state[2+c*4] ^ G2X.at(@state[3+c*4])
|
63
|
+
end
|
64
|
+
@state = t
|
65
|
+
end
|
66
|
+
protected :mixColumns
|
67
|
+
|
68
|
+
def imixColumns
|
69
|
+
t = "\000" * 16
|
70
|
+
4.times do |c|
|
71
|
+
t[c*4] = GEX.at(@state[c*4]) ^ GBX.at(@state[1+c*4]) ^
|
72
|
+
GDX.at(@state[2+c*4]) ^ G9X.at(@state[3+c*4])
|
73
|
+
t[1+c*4] = G9X.at(@state[c*4]) ^ GEX.at(@state[1+c*4]) ^
|
74
|
+
GBX.at(@state[2+c*4]) ^ GDX.at(@state[3+c*4])
|
75
|
+
t[2+c*4] = GDX.at(@state[c*4]) ^ G9X.at(@state[1+c*4]) ^
|
76
|
+
GEX.at(@state[2+c*4]) ^ GBX.at(@state[3+c*4])
|
77
|
+
t[3+c*4] = GBX.at(@state[c*4]) ^ GDX.at(@state[1+c*4]) ^
|
78
|
+
G9X.at(@state[2+c*4]) ^ GEX.at(@state[3+c*4])
|
79
|
+
end
|
80
|
+
@state = t
|
81
|
+
end
|
82
|
+
protected :imixColumns
|
83
|
+
|
84
|
+
def addRoundKey(n)
|
85
|
+
j = n*16
|
86
|
+
16.times do |i|
|
87
|
+
@state[i] ^= @w[i+j]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
protected :addRoundKey
|
91
|
+
|
92
|
+
def key_expansion(key)
|
93
|
+
0.upto(@nk*4-1) do |i|
|
94
|
+
@w[i] = key[i]
|
95
|
+
end
|
96
|
+
@nk.upto(@nb*(@nr+1)-1) do |i|
|
97
|
+
j = i*4
|
98
|
+
k = j-(@nk*4)
|
99
|
+
t0, t1, t2, t3 = @w[j-4], @w[j-3], @w[j-2], @w[j-1]
|
100
|
+
if (i % @nk == 0)
|
101
|
+
t0, t1, t2, t3 =
|
102
|
+
S_BOX[t1] ^ RCON[i/@nk - 1], S_BOX[t2], S_BOX[t3], S_BOX[t0]
|
103
|
+
elsif (@nk > 6) && (i % @nk == 4)
|
104
|
+
t0, t1, t2, t3 = S_BOX[t0], S_BOX[t1], S_BOX[t2], S_BOX[t3]
|
105
|
+
end
|
106
|
+
@w[j], @w[j+1], @w[j+2], @w[j+3] =
|
107
|
+
@w[k] ^ t0, @w[k+1] ^ t1, @w[k+2] ^ t2, @w[k+3] ^ t3
|
108
|
+
end
|
109
|
+
end
|
110
|
+
protected :key_expansion
|
111
|
+
|
112
|
+
def _encrypt_block
|
113
|
+
addRoundKey 0
|
114
|
+
1.upto(@nr) do |n|
|
115
|
+
subBytes
|
116
|
+
shiftRows
|
117
|
+
mixColumns unless n == @nr
|
118
|
+
addRoundKey n
|
119
|
+
end
|
120
|
+
@state
|
121
|
+
end
|
122
|
+
protected :_encrypt_block
|
123
|
+
|
124
|
+
def _decrypt_block
|
125
|
+
addRoundKey @nr
|
126
|
+
(@nr-1).downto(0) do |n|
|
127
|
+
ishiftRows
|
128
|
+
isubBytes
|
129
|
+
addRoundKey n
|
130
|
+
imixColumns unless n == 0
|
131
|
+
end
|
132
|
+
@state
|
133
|
+
end
|
134
|
+
protected :_decrypt_block
|
135
|
+
|
136
|
+
def xor(a,b)
|
137
|
+
c = ""
|
138
|
+
16.times do |i|
|
139
|
+
c << (a[i] ^ b[i]).chr
|
140
|
+
end
|
141
|
+
c
|
142
|
+
end
|
143
|
+
protected :xor
|
144
|
+
|
145
|
+
def encrypt_block(block)
|
146
|
+
@state = block.dup
|
147
|
+
case @mode
|
148
|
+
when 'ECB'
|
149
|
+
_encrypt_block
|
150
|
+
when 'CBC'
|
151
|
+
@state = xor(block, @iv)
|
152
|
+
@iv = _encrypt_block
|
153
|
+
when 'OFB'
|
154
|
+
@state = @iv.dup
|
155
|
+
@iv = _encrypt_block
|
156
|
+
xor(@iv, block)
|
157
|
+
when 'CFB'
|
158
|
+
@state = @iv.dup
|
159
|
+
@iv = xor(_encrypt_block, block)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def decrypt_block(block)
|
164
|
+
@state = block.dup
|
165
|
+
case @mode
|
166
|
+
when 'ECB'
|
167
|
+
_decrypt_block
|
168
|
+
when 'CBC'
|
169
|
+
o = xor(_decrypt_block, @iv)
|
170
|
+
@iv = block
|
171
|
+
o
|
172
|
+
when 'OFB'
|
173
|
+
@state = @iv.dup
|
174
|
+
@iv = _encrypt_block
|
175
|
+
xor(@iv, block)
|
176
|
+
when 'CFB'
|
177
|
+
@state = @iv.dup
|
178
|
+
o = xor(_encrypt_block, block)
|
179
|
+
@iv = block
|
180
|
+
o
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def encrypt_blocks(buffer)
|
185
|
+
raise "Bad block length" unless (buffer.length % 16).zero?
|
186
|
+
ct = ""
|
187
|
+
block = ""
|
188
|
+
buffer.each_byte do |char|
|
189
|
+
block << char
|
190
|
+
if block.length == 16
|
191
|
+
ct << encrypt_block(block)
|
192
|
+
block = ""
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def decrypt_blocks(buffer)
|
198
|
+
raise "Bad block length" unless (buffer.length % 16).zero?
|
199
|
+
pt = ""
|
200
|
+
block = ""
|
201
|
+
buffer.each_byte do |char|
|
202
|
+
block << char
|
203
|
+
if block.length == 16
|
204
|
+
pt << decrypt_block(block)
|
205
|
+
block = ""
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def encrypt_buffer(buffer)
|
211
|
+
ct = ""
|
212
|
+
block = ""
|
213
|
+
buffer.each_byte do |char|
|
214
|
+
block << char
|
215
|
+
if block.length == 16
|
216
|
+
ct << encrypt_block(block)
|
217
|
+
block = ""
|
218
|
+
end
|
219
|
+
end
|
220
|
+
m = 16 - block.length % 16
|
221
|
+
ct << (m == 16 ? 0 : encrypt_block(block << m.chr * m))
|
222
|
+
end
|
223
|
+
|
224
|
+
def decrypt_buffer(buffer)
|
225
|
+
pt = ""
|
226
|
+
block = ""
|
227
|
+
buffer.each_byte do |char|
|
228
|
+
block << char
|
229
|
+
if block.length == 16
|
230
|
+
pt << decrypt_block(block)
|
231
|
+
block = ""
|
232
|
+
end
|
233
|
+
end
|
234
|
+
if block.length == 0
|
235
|
+
c = pt[-1]
|
236
|
+
c.chr * c == pt[-c..-1] ? pt[0..-(c+1)] : (raise "Bad Block Padding")
|
237
|
+
else
|
238
|
+
pt
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def init(key_length, mode, key, iv = nil)
|
243
|
+
@iv = "\000" * 16
|
244
|
+
@iv = iv if iv
|
245
|
+
@nb = 4
|
246
|
+
@nk = 4
|
247
|
+
@nr = 10
|
248
|
+
@mode = 'ECB'
|
249
|
+
@state = nil
|
250
|
+
@w = []
|
251
|
+
case key_length
|
252
|
+
when 128
|
253
|
+
@nk = 4
|
254
|
+
@nr = 10
|
255
|
+
when 192
|
256
|
+
@nk = 6
|
257
|
+
@nr = 12
|
258
|
+
when 256
|
259
|
+
@nk = 8
|
260
|
+
@nr = 14
|
261
|
+
else
|
262
|
+
raise 'Bad Key length'
|
263
|
+
end
|
264
|
+
case mode
|
265
|
+
when 'ECB', 'CBC', 'OFB', 'CFB'
|
266
|
+
@mode = mode
|
267
|
+
else
|
268
|
+
raise 'Bad AES mode'
|
269
|
+
end
|
270
|
+
key_expansion key
|
271
|
+
end
|
272
|
+
|
273
|
+
def initialize(key_length, mode, key, iv = nil)
|
274
|
+
init(key_length, mode, key, iv)
|
275
|
+
end
|
276
|
+
|
277
|
+
end # class aes
|