aes 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. data/README.rdoc +24 -15
  2. data/VERSION +1 -1
  3. data/aes.gemspec +3 -2
  4. data/lib/aes.rb +1 -128
  5. data/lib/aes/aes.rb +150 -0
  6. data/test/test_aes.rb +14 -5
  7. metadata +5 -4
@@ -1,28 +1,37 @@
1
1
  = aes
2
2
 
3
- An AES encrypt/decrypt gem built ontop of OpenSSL. Not as quick as FastAES, but it doesn't require building native extensions and supports Base64 encoded input and output.
3
+ An AES encrypt/decrypt gem built on top of OpenSSL. Not as quick as FastAES but doesn't require building native extensions - also supports Base64 encoded input and output.
4
4
 
5
5
  Usage:
6
6
 
7
- require 'aes'
7
+ require 'aes'
8
8
 
9
- # Generate a random key
10
- key = AES.key(32)
11
- => "290c3c5d812a4ba7ce33adf09598a462"
9
+ # Generate a random key
10
+ key = AES.key
11
+ => "290c3c5d812a4ba7ce33adf09598a462"
12
+
13
+ # Encrypt a string. Default output is base_64 encoded, init_vector and cipher_text are joined with "$"
14
+ b64 = AES.encrypt("A super secret message", key)
15
+ => "IJjbgbv/OvPIAf4R5qAWyg==$fy0v7JwRX4kyAWflgouQlt9XGmiDKvbQMRHmQ+vy1fA="
12
16
 
13
- # Encrypt something, default output is base_64 encoded. init_vector and cipher_text are joined with "$"
14
- b64 = AES.encrypt(key, "A super secret message")
15
- => "IJjbgbv/OvPIAf4R5qAWyg==$fy0v7JwRX4kyAWflgouQlt9XGmiDKvbQMRHmQ+vy1fA="
17
+ # Same as above but minus the base64 encoding, init_vector and cipher_text are shoved into an array
18
+ plain = AES.encrypt("A super secret message", key, {:format => :plain}) #
19
+ => [";\202\222\306\376<\206\343\023\245\312\225\214KAm",
20
+ "C\343\023\323U~W>\023y\217\341\201\371\352\334\311^\307\352{\020 H(DVw\3224N\223"]
16
21
 
17
- # Same as above but minus the base64 encoding, initialization vector and cipher_text are shoved into an array
18
- plain = AES.encrypt(key, "A super secret message", {:format => :plain}) #
19
- => [";\202\222\306\376<\206\343\023\245\312\225\214KAm", "C\343\023\323U~W>\023y\217\341\201\371\352\334\311^\307\352{\020 H(DVw\3224N\223"]
22
+ # Generate a random initialization vector
23
+ iv = AES.iv(:base_64)
24
+ => "IJjbgbv/OvPIAf4R5qAWyg=="
20
25
 
21
- AES.decrypt(key, b64)
22
- => "A super secret message"
26
+ # Encrypt a string, with a provided key and init_vector.
27
+ b64_iv = AES.encrypt("A super secret message", key, {:iv => iv})
28
+ => "IJjbgbv/OvPIAf4R5qAWyg==$fy0v7JwRX4kyAWflgouQlt9XGmiDKvbQMRHmQ+vy1fA="
23
29
 
24
- AES.decrypt(key, plain, {:format => :plain})
25
- => "A super secret message"
30
+ AES.decrypt(b64, key)
31
+ => "A super secret message"
32
+
33
+ AES.decrypt(plain, key, {:format => :plain})
34
+ => "A super secret message"
26
35
 
27
36
  == Contributing to aes
28
37
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{aes}
8
- s.version = "0.3.0"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Carl Hicks"]
12
- s.date = %q{2010-12-05}
12
+ s.date = %q{2011-01-03}
13
13
  s.description = %q{An AES encrypt/decrypt gem built ontop of OpenSSL. Not as quick as FastAES, but it doesn't require building
14
14
  native extensions and supports Base64 encoded input and output.}
15
15
  s.email = %q{carl.hicks@gmail.com}
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
26
26
  "VERSION",
27
27
  "aes.gemspec",
28
28
  "lib/aes.rb",
29
+ "lib/aes/aes.rb",
29
30
  "test/helper.rb",
30
31
  "test/test_aes.rb"
31
32
  ]
data/lib/aes.rb CHANGED
@@ -1,130 +1,3 @@
1
1
  require 'openssl'
2
2
  require 'base64'
3
-
4
- class AES
5
- class << self
6
- # Encrypts the plain_text with the provided key
7
- def encrypt(key, plain_text, opts={})
8
- AES.new(key,opts).encrypt(plain_text)
9
- end
10
- # Decrypts the cipher_text with the provided key
11
- def decrypt(key, cipher_text, opts={})
12
- AES.new(key,opts).decrypt(cipher_text)
13
- end
14
- # Generates a random key of the specified length in bits
15
- # Default output is
16
- def key(length=256,format=:plain)
17
- key = AES.new("").random_key(256)
18
- case format
19
- when :base_64
20
- Base64.encode64(key)
21
- else
22
- key
23
- end
24
- end
25
- end
26
-
27
- attr :options
28
- attr :key
29
- attr :cipher
30
- attr :cipher_text
31
- attr :plain_text
32
-
33
- def initialize(key, opts={})
34
- merge_options opts
35
- @key = key
36
- self
37
- end
38
-
39
- # Encrypts
40
- def encrypt(plain_text)
41
- @plain_text = plain_text
42
- _setup(:encrypt)
43
- case @options[:format]
44
- when :base_64
45
- @cipher_text = b64_e(_iv) << "$" << b64_e(_encrypt)
46
- else
47
- @cipher_text = [_iv, _encrypt]
48
- end
49
- @cipher_text
50
- end
51
-
52
- # Decrypts
53
- def decrypt(cipher_text)
54
- @cipher_text = cipher_text
55
- _setup(:decrypt)
56
- case @options[:format]
57
- when :base_64
58
- ctext = b64_d(@cipher_text)
59
- else
60
- ctext = @cipher_text
61
- end
62
- @cipher.iv = ctext[0]
63
- @plain_text = @cipher.update(ctext[1]) + @cipher.final
64
- end
65
-
66
- # Generate a random initialization vector
67
- def random_iv
68
- _setup(:encrypt)
69
- _iv
70
- end
71
-
72
- # Generate a random key
73
- def random_key(length=256)
74
- _random_seed.unpack('H*')[0][0..((length/8)-1)]
75
- #Digest::SHA256.digest(_random_seed)[0..(length / 8)]
76
- end
77
-
78
- private
79
-
80
- # Generates a random seed value
81
- def _random_seed(size=32)
82
- if defined? OpenSSL::Random
83
- return OpenSSL::Random.random_bytes(size)
84
- else
85
- chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
86
- (1..size).collect{|a| chars[rand(chars.size)] }.join
87
- end
88
- end
89
-
90
- # Un-Base64's the IV and CipherText
91
- # Returns an array containing the IV, and CipherText
92
- def b64_d(data)
93
- iv_ctext = []
94
- data.split('$').each do |part|
95
- iv_ctext << Base64.decode64(part)
96
- end
97
- iv_ctext
98
- end
99
-
100
- # Base64 Encodes a string
101
- def b64_e(data)
102
- Base64.encode64(data).chomp
103
- end
104
-
105
- # Generates and returns a random initialization vector
106
- def _iv
107
- @cipher.random_iv
108
- end
109
-
110
- # Encrypts @plain_text
111
- def _encrypt
112
- @cipher.update(@plain_text) + @cipher.final
113
- end
114
-
115
- # Merge init options with defaults
116
- def merge_options(opts)
117
- @options = {
118
- :format => :base_64,
119
- :cipher => "AES-256-CBC"
120
- }.merge! opts
121
- end
122
-
123
- # Create a new cipher using the cipher type specified
124
- def _setup(action)
125
- @cipher = OpenSSL::Cipher::Cipher.new(@options[:cipher])
126
- # Toggles encryption mode
127
- @cipher.send(action)
128
- @cipher.key = @key.unpack('a2'*32).map{|x| x.hex}.pack('c'*32)
129
- end
130
- end
3
+ require 'aes/aes'
@@ -0,0 +1,150 @@
1
+ module AES
2
+ class << self
3
+ # Encrypts the plain_text with the provided key
4
+ def encrypt(plain_text, key, opts={})
5
+ ::AES::AES.new(key, opts).encrypt(plain_text)
6
+ end
7
+ # Decrypts the cipher_text with the provided key
8
+ def decrypt(cipher_text, key, opts={})
9
+ ::AES::AES.new(key, opts).decrypt(cipher_text)
10
+ end
11
+ # Generates a random key of the specified length in bits
12
+ # Default format is :plain
13
+ def key(length=256,format=:plain)
14
+ key = ::AES::AES.new("").random_key(256)
15
+ case format
16
+ when :base_64
17
+ Base64.encode64(key).chomp
18
+ else
19
+ key
20
+ end
21
+ end
22
+ # Generates a random iv
23
+ # Default format is :plain
24
+ def iv(format=:plain)
25
+ iv = ::AES::AES.new("").random_iv
26
+ case format
27
+ when :base_64
28
+ Base64.encode64(iv).chomp
29
+ else
30
+ iv
31
+ end
32
+ end
33
+ end
34
+
35
+ class AES
36
+ attr :options
37
+ attr :key
38
+ attr :iv
39
+ attr :cipher
40
+ attr :cipher_text
41
+ attr :plain_text
42
+
43
+ def initialize(key, opts={})
44
+ merge_options opts
45
+ @cipher = nil
46
+ @key = key
47
+ @iv ||= random_iv
48
+ self
49
+ end
50
+
51
+ # Encrypts
52
+ def encrypt(plain_text)
53
+ @plain_text = plain_text
54
+ _setup(:encrypt)
55
+ @cipher.iv = @iv
56
+ case @options[:format]
57
+ when :base_64
58
+ @cipher_text = b64_e(@iv) << "$" << b64_e(_encrypt)
59
+ else
60
+ @cipher_text = [@iv, _encrypt]
61
+ end
62
+ @cipher_text
63
+ end
64
+
65
+ # Decrypts
66
+ def decrypt(cipher_text)
67
+ @cipher_text = cipher_text
68
+ _setup(:decrypt)
69
+ case @options[:format]
70
+ when :base_64
71
+ ctext = b64_d(@cipher_text)
72
+ else
73
+ ctext = @cipher_text
74
+ end
75
+ @cipher.iv = ctext[0]
76
+ @plain_text = @cipher.update(ctext[1]) + @cipher.final
77
+ end
78
+
79
+ # Generate a random initialization vector
80
+ def random_iv
81
+ _setup(:encrypt)
82
+ @cipher.random_iv
83
+ end
84
+
85
+ # Generate a random key
86
+ def random_key(length=256)
87
+ _random_seed.unpack('H*')[0][0..((length/8)-1)]
88
+ end
89
+
90
+ private
91
+
92
+ # Generates a random seed value
93
+ def _random_seed(size=32)
94
+ if defined? OpenSSL::Random
95
+ return OpenSSL::Random.random_bytes(size)
96
+ else
97
+ chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
98
+ (1..size).collect{|a| chars[rand(chars.size)] }.join
99
+ end
100
+ end
101
+
102
+ # Un-Base64's the IV and CipherText
103
+ # Returns an array containing the IV, and CipherText
104
+ def b64_d(data)
105
+ iv_and_ctext = []
106
+ data.split('$').each do |part|
107
+ iv_and_ctext << Base64.decode64(part)
108
+ end
109
+ iv_and_ctext
110
+ end
111
+
112
+ # Base64 Encodes a string
113
+ def b64_e(data)
114
+ Base64.encode64(data).chomp
115
+ end
116
+
117
+ # Encrypts @plain_text
118
+ def _encrypt
119
+ @cipher.update(@plain_text) + @cipher.final
120
+ end
121
+
122
+ # Merge init options with defaults
123
+ def merge_options(opts)
124
+ @options = {
125
+ :format => :base_64,
126
+ :cipher => "AES-256-CBC",
127
+ :iv => nil,
128
+ }.merge! opts
129
+ _handle_iv
130
+ end
131
+
132
+ def _handle_iv
133
+ @iv = @options[:iv]
134
+ return if @iv.nil?
135
+
136
+ case @options[:format]
137
+ when :base_64
138
+ @iv = Base64.decode64(@options[:iv])
139
+ end
140
+ end
141
+
142
+ # Create a new cipher using the cipher type specified
143
+ def _setup(action)
144
+ @cipher ||= OpenSSL::Cipher::Cipher.new(@options[:cipher])
145
+ # Toggles encryption mode
146
+ @cipher.send(action)
147
+ @cipher.key = @key.unpack('a2'*32).map{|x| x.hex}.pack('c'*32)
148
+ end
149
+ end
150
+ end
@@ -5,15 +5,24 @@ class TestAES < Test::Unit::TestCase
5
5
  should "encrypt and decrypt a string" do
6
6
  key = "01234567890123456789012345678901"
7
7
  msg = "This is a message that nobody should ever see"
8
- enc = AES.encrypt(key, msg)
9
- assert_equal msg, AES.decrypt(key, enc)
10
- enc = AES.encrypt(key, msg, {:format => :plain})
11
- assert_equal msg, AES.decrypt(key, enc, {:format => :plain})
8
+ enc = AES.encrypt(msg, key)
9
+ assert_equal msg, AES.decrypt(enc, key)
10
+ enc = AES.encrypt(msg, key, {:format => :plain})
11
+ assert_equal msg, AES.decrypt(enc, key, {:format => :plain})
12
+ end
13
+
14
+ should "produce the same encrypted string when provided an identical key and iv" do
15
+ key = "01234567890123456789012345678901"
16
+ msg = "This is a message that nobody should ever see"
17
+ iv = AES.iv(:base_64)
18
+ enc1 = AES.encrypt(msg, key, {:iv => iv})
19
+ enc2 = AES.encrypt(msg, key, {:iv => iv})
20
+ assert_equal enc1, enc2
12
21
  end
13
22
 
14
23
  should "generate a new key when AES#key" do
15
24
  assert_equal 32, AES.key.length
16
- assert_equal 45, AES.key(256, :base_64).length
25
+ assert_equal 44, AES.key(256, :base_64).length
17
26
  end
18
27
 
19
28
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aes
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 0.3.0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Carl Hicks
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-05 00:00:00 -08:00
18
+ date: 2011-01-03 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -98,6 +98,7 @@ files:
98
98
  - VERSION
99
99
  - aes.gemspec
100
100
  - lib/aes.rb
101
+ - lib/aes/aes.rb
101
102
  - test/helper.rb
102
103
  - test/test_aes.rb
103
104
  has_rdoc: true