aes 0.3.0 → 0.4.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.
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