From 1e6e88933cb0be13405e2ba375270a2130331e16 Mon Sep 17 00:00:00 2001 From: Leonid Morozov Date: Fri, 23 Feb 2018 19:07:27 +0300 Subject: [PATCH 1/2] fixes by PRs against original repo + style fixes --- Gemfile | 11 +-- README.rdoc | 13 ++- Rakefile | 24 +++--- aes.gemspec | 77 +++++++++-------- lib/aes/aes.rb | 211 ++++++++++++++++++++++++----------------------- test/helper.rb | 4 +- test/test_aes.rb | 57 +++++++------ 7 files changed, 205 insertions(+), 192 deletions(-) diff --git a/Gemfile b/Gemfile index 652ab35..9e5137c 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,4 @@ -source "http://rubygems.org" +source 'http://rubygems.org' # Add dependencies required to use your gem here. # Example: # gem "activesupport", ">= 2.3.5" @@ -6,8 +6,9 @@ source "http://rubygems.org" # Add dependencies to develop your gem here. # Include everything needed to run rake, tests, features, etc. group :development do - gem "shoulda" - gem "bundler" - gem "jeweler" - gem "simplecov" + gem 'bundler' + gem 'jeweler' + gem 'shoulda' + gem 'simplecov' + gem 'test-unit' end diff --git a/README.rdoc b/README.rdoc index 1451d53..3856bbe 100644 --- a/README.rdoc +++ b/README.rdoc @@ -8,24 +8,23 @@ Usage: # Generate a random key key = AES.key - => "290c3c5d812a4ba7ce33adf09598a462" + => "3a45d76fa5f0bd21f8dfd3f4e98fc4effe59e503857618cf58a11a31a276177b" # Encrypt a string. Default output is base_64 encoded, init_vector and cipher_text are joined with "$" b64 = AES.encrypt("A super secret message", key) - => "IJjbgbv/OvPIAf4R5qAWyg==$fy0v7JwRX4kyAWflgouQlt9XGmiDKvbQMRHmQ+vy1fA=" + => "IuTX8xX2XrrTVsq6SwWtFw==$+A8IiuUgPE+nRFVinA0vd5LUInd3QM3rGViNJIq3mx4=" # Same as above but minus the base64 encoding, init_vector and cipher_text are shoved into an array plain = AES.encrypt("A super secret message", key, {:format => :plain}) # - => [";\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"] + => ["xF.^\x80ML'6\x10F2Z\xF8\x9Ep", "r\xA8P\xEBP\x10_\xC1\xD3B\xC3\xAB\xB3_qy\x91Q\x8C~\x1Ec\x9FD'\x8D\xB8\xBF\xB0\xA6\a\x9A"] # Generate a random initialization vector iv = AES.iv(:base_64) - => "IJjbgbv/OvPIAf4R5qAWyg==" + => "G8iY1e3Yvf6OqFAD4w2ZVw==" # Encrypt a string, with a provided key and init_vector. b64_iv = AES.encrypt("A super secret message", key, {:iv => iv}) - => "IJjbgbv/OvPIAf4R5qAWyg==$fy0v7JwRX4kyAWflgouQlt9XGmiDKvbQMRHmQ+vy1fA=" + => "G8iY1e3Yvf6OqFAD4w2ZVw==$B68lzBMXyOLXBSbPg4BgLBQRf68xVmS2oK4r2Xb+tXc=" AES.decrypt(b64, key) => "A super secret message" @@ -40,7 +39,7 @@ Usage: # the following example the message is exactly 16 bytes long, so no # error aries. msg = AES.encrypt("A secret message", key, {:padding => false}) - => "SnD+WIfEfjZRrl+WAM/9pw==$89sGGZsu973j8Gl6aXC8Uw==" + => "3orl0zsORP06B8+eyM+XsQ==$bqsvFPjTOzccKA/N3IEnug==" # Be sure to pass the same padding option when decrypting the # message, as it will fail if you try to decrypt unpadded data and diff --git a/Rakefile b/Rakefile index 06486db..153c088 100644 --- a/Rakefile +++ b/Rakefile @@ -3,8 +3,8 @@ require 'bundler' begin Bundler.setup(:default, :development) rescue Bundler::BundlerError => e - $stderr.puts e.message - $stderr.puts "Run `bundle install` to install missing gems" + warn e.message + warn 'Run `bundle install` to install missing gems' exit e.status_code end require 'rake' @@ -12,14 +12,14 @@ require 'rake' require 'jeweler' Jeweler::Tasks.new do |gem| # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options - gem.name = "aes" - gem.homepage = "http://github.com/chicks/aes" - gem.license = "MIT" - gem.summary = %Q{AES#encrypt(key, data), AES#decrypt(key, data). Capiche?} - gem.description = %Q{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.} - gem.email = "carl.hicks@gmail.com" - gem.authors = ["Carl Hicks"] + gem.name = 'aes' + gem.homepage = 'http://github.com/chicks/aes' + gem.license = 'MIT' + gem.summary = %{AES#encrypt(key, data), AES#decrypt(key, data). Capiche?} + gem.description = %(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.) + gem.email = 'carl.hicks@gmail.com' + gem.authors = ['Carl Hicks'] # Include your dependencies below. Runtime dependencies are required when using your gem, # and development dependencies are only needed for development (ie running rake tasks, tests, etc) # gem.add_runtime_dependency 'jabber4r', '> 0.1' @@ -34,11 +34,11 @@ Rake::TestTask.new(:test) do |test| test.verbose = true end -task :default => :test +task default: :test require 'rdoc/task' Rake::RDocTask.new do |rdoc| - version = File.exist?('VERSION') ? File.read('VERSION') : "" + version = File.exist?('VERSION') ? File.read('VERSION') : '' rdoc.rdoc_dir = 'rdoc' rdoc.title = "aes #{version}" diff --git a/aes.gemspec b/aes.gemspec index 1fd4ac3..6e96a00 100644 --- a/aes.gemspec +++ b/aes.gemspec @@ -4,56 +4,55 @@ # -*- encoding: utf-8 -*- Gem::Specification.new do |s| - s.name = "aes" - s.version = "0.5.0" + s.name = 'aes' + s.version = '0.5.0' - s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= - s.authors = ["Carl Hicks"] - s.date = "2012-05-01" + s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version= + s.authors = ['Carl Hicks'] + s.date = '2012-05-01' s.description = "An AES encrypt/decrypt gem built ontop of OpenSSL. Not as quick as FastAES, but it doesn't require building\n native extensions and supports Base64 encoded input and output." - s.email = "carl.hicks@gmail.com" + s.email = 'carl.hicks@gmail.com' s.extra_rdoc_files = [ - "LICENSE.txt", - "README.rdoc" + 'LICENSE.txt', + 'README.rdoc' ] s.files = [ - ".document", - "Gemfile", - "LICENSE.txt", - "README.rdoc", - "Rakefile", - "VERSION", - "aes.gemspec", - "lib/aes.rb", - "lib/aes/aes.rb", - "test/helper.rb", - "test/test_aes.rb" + '.document', + 'Gemfile', + 'LICENSE.txt', + 'README.rdoc', + 'Rakefile', + 'VERSION', + 'aes.gemspec', + 'lib/aes.rb', + 'lib/aes/aes.rb', + 'test/helper.rb', + 'test/test_aes.rb' ] - s.homepage = "http://github.com/chicks/aes" - s.licenses = ["MIT"] - s.require_paths = ["lib"] - s.rubygems_version = "1.8.12" - s.summary = "AES#encrypt(key, data), AES#decrypt(key, data). Capiche?" + s.homepage = 'http://github.com/chicks/aes' + s.licenses = ['MIT'] + s.require_paths = ['lib'] + s.rubygems_version = '1.8.12' + s.summary = 'AES#encrypt(key, data), AES#decrypt(key, data). Capiche?' - if s.respond_to? :specification_version then + if s.respond_to? :specification_version s.specification_version = 3 - if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') + s.add_development_dependency('bundler', ['>= 0']) + s.add_development_dependency('jeweler', ['>= 0']) + s.add_development_dependency('shoulda', ['>= 0']) + s.add_development_dependency('simplecov', ['>= 0']) else - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) + s.add_dependency('bundler', ['>= 0']) + s.add_dependency('jeweler', ['>= 0']) + s.add_dependency('shoulda', ['>= 0']) + s.add_dependency('simplecov', ['>= 0']) end else - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) + s.add_dependency('shoulda', ['>= 0']) + s.add_dependency('shoulda', ['>= 0']) + s.add_dependency('shoulda', ['>= 0']) + s.add_dependency('simplecov', ['>= 0']) end end - diff --git a/lib/aes/aes.rb b/lib/aes/aes.rb index 0c09c89..148de1a 100644 --- a/lib/aes/aes.rb +++ b/lib/aes/aes.rb @@ -1,17 +1,23 @@ module AES + DEFAULT_AES_CIPHER = 'AES-256-CBC'.freeze + class << self # Encrypts the plain_text with the provided key - def encrypt(plain_text, key, opts={}) + def encrypt(plain_text, key, opts = {}) ::AES::AES.new(key, opts).encrypt(plain_text) end + # Decrypts the cipher_text with the provided key - def decrypt(cipher_text, key, opts={}) + def decrypt(cipher_text, key, opts = {}) ::AES::AES.new(key, opts).decrypt(cipher_text) end + # Generates a random key of the specified length in bits # Default format is :plain - def key(length=256,format=:plain) - key = ::AES::AES.new("").random_key(length) + def key(length = 256, format = :plain) + bytes = OpenSSL::Random.random_bytes(length / 8) + key = bytes.unpack('H*')[0] + case format when :base_64 Base64.encode64(key).chomp @@ -19,140 +25,139 @@ def key(length=256,format=:plain) key end end - # Generates a random iv + + # Generates a random iv # Default format is :plain - def iv(format=:plain) - iv = ::AES::AES.new("").random_iv + def iv(format = :plain) + cipher = OpenSSL::Cipher.new(DEFAULT_AES_CIPHER) + cipher.encrypt + iv = cipher.random_iv + case format when :base_64 Base64.encode64(iv).chomp else iv - end + end end end - + class AES - attr :options - attr :key - attr :iv - attr :cipher - attr :cipher_text - attr :plain_text - - def initialize(key, opts={}) + attr_reader :options + attr_reader :key + attr_reader :iv + attr_reader :cipher + attr_reader :cipher_text + attr_reader :plain_text + + def initialize(key, opts = {}) merge_options opts + unless key =~ /\A[A-F0-9]{64}\z/i + raise ArgumentError, 'AES Key must be a 64 character hex string' + end @cipher = nil @key = key - @iv ||= random_iv + @iv ||= ::AES.iv self end - + # Encrypts def encrypt(plain_text) @plain_text = plain_text _setup(:encrypt) - @cipher.iv = @iv - case @options[:format] - when :base_64 - @cipher_text = b64_e(@iv) << "$" << b64_e(_encrypt) - else - @cipher_text = [@iv, _encrypt] - end + @cipher.iv = @iv + @cipher_text = case @options[:format] + when :base_64 + b64_e(@iv) << '$' << b64_e(_encrypt) + else + [@iv, _encrypt] + end @cipher_text end - # Decrypts + # Decrypts def decrypt(cipher_text) @cipher_text = cipher_text _setup(:decrypt) - case @options[:format] - when :base_64 - ctext = b64_d(@cipher_text) - else - ctext = @cipher_text - end + ctext = case @options[:format] + when :base_64 + b64_d(@cipher_text) + else + @cipher_text + end @cipher.iv = ctext[0] - @plain_text = @cipher.update(ctext[1]) + @cipher.final + @plain_text = @cipher.update(ctext[1]) + @cipher.final end # Generate a random initialization vector + # There's no reason to call random_iv on an instance + # This has been left for backwards compatibility, + # but it now just delegates to the class method def random_iv - _setup(:encrypt) - @cipher.random_iv + ::AES.iv(@options[:format]) end - + # Generate a random key - def random_key(length=256) - _random_seed.unpack('H*')[0][0..((length/8)-1)] + def random_key(length = 256) + ::AES.key(length) end - + private - - # Generates a random seed value - def _random_seed(size=32) - if defined? OpenSSL::Random - return OpenSSL::Random.random_bytes(size) - else - chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a - (1..size).collect{|a| chars[rand(chars.size)] }.join - end - end - - # Un-Base64's the IV and CipherText - # Returns an array containing the IV, and CipherText - def b64_d(data) - iv_and_ctext = [] - data.split('$').each do |part| - iv_and_ctext << Base64.decode64(part) - end - iv_and_ctext - end - - # Base64 Encodes a string - def b64_e(data) - Base64.encode64(data).chomp - end - - # Encrypts @plain_text - def _encrypt - @cipher.update(@plain_text) + @cipher.final - end - # Merge init options with defaults - def merge_options(opts) - @options = { - :format => :base_64, - :cipher => "AES-256-CBC", - :iv => nil, - :padding => true, # use cipher padding by default - }.merge! opts - _handle_iv - _handle_padding - end - - def _handle_iv - @iv = @options[:iv] - return if @iv.nil? - - case @options[:format] - when :base_64 - @iv = Base64.decode64(@options[:iv]) - end - end - - def _handle_padding - # convert value to what OpenSSL module format expects - @options[:padding] = @options[:padding] ? 1 : 0 + # Un-Base64's the IV and CipherText + # Returns an array containing the IV, and CipherText + def b64_d(data) + iv_and_ctext = [] + data.split('$').each do |part| + iv_and_ctext << Base64.decode64(part) end - - # Create a new cipher using the cipher type specified - def _setup(action) - @cipher ||= OpenSSL::Cipher::Cipher.new(@options[:cipher]) - # Toggles encryption mode - @cipher.send(action) - @cipher.padding = @options[:padding] - @cipher.key = @key.unpack('a2'*32).map{|x| x.hex}.pack('c'*32) + iv_and_ctext + end + + # Base64 Encodes a string + def b64_e(data) + Base64.encode64(data).chomp + end + + # Encrypts @plain_text + def _encrypt + @cipher.update(@plain_text) + @cipher.final + end + + # Merge init options with defaults + def merge_options(opts) + @options = { + format: :base_64, + cipher: ::AES::DEFAULT_AES_CIPHER, + iv: nil, + padding: true, # use cipher padding by default + }.merge! opts + _handle_iv + _handle_padding + end + + def _handle_iv + @iv = @options[:iv] + return if @iv.nil? + + case @options[:format] + when :base_64 + @iv = Base64.decode64(@options[:iv]) end + end + + def _handle_padding + # convert value to what OpenSSL module format expects + @options[:padding] = @options[:padding] ? 1 : 0 + end + + # Create a new cipher using the cipher type specified + def _setup(action) + @cipher ||= OpenSSL::Cipher.new(@options[:cipher]) + # Toggles encryption mode + @cipher.send(action) + @cipher.padding = @options[:padding] + @cipher.key = [@key].pack('H*') + end end end diff --git a/test/helper.rb b/test/helper.rb index 680d151..76d0f0a 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -3,8 +3,8 @@ begin Bundler.setup(:default, :development) rescue Bundler::BundlerError => e - $stderr.puts e.message - $stderr.puts "Run `bundle install` to install missing gems" + warn e.message + warn 'Run `bundle install` to install missing gems' exit e.status_code end require 'test/unit' diff --git a/test/test_aes.rb b/test/test_aes.rb index 527d0a2..961f81e 100644 --- a/test/test_aes.rb +++ b/test/test_aes.rb @@ -1,39 +1,48 @@ require 'helper' class TestAES < Test::Unit::TestCase - - should "encrypt and decrypt a string" do - key = "01234567890123456789012345678901" - msg = "This is a message that nobody should ever see" + test_key = '66c2454a167226f132098cfeb18eac31ec2a66104fc3c2187816baaba2d8ed39' + + should 'encrypt and decrypt a string' do + key = test_key + msg = 'This is a message that nobody should ever see' enc = AES.encrypt(msg, key) assert_equal msg, AES.decrypt(enc, key) - enc = AES.encrypt(msg, key, {:format => :plain}) - assert_equal msg, AES.decrypt(enc, key, {:format => :plain}) + enc = AES.encrypt(msg, key, format: :plain) + assert_equal msg, AES.decrypt(enc, key, format: :plain) end - - should "produce the same encrypted string when provided an identical key and iv" do - key = "01234567890123456789012345678901" - msg = "This is a message that nobody should ever see" + + should 'produce the same encrypted string when provided an identical key and iv' do + key = test_key + msg = 'This is a message that nobody should ever see' iv = AES.iv(:base_64) - enc1 = AES.encrypt(msg, key, {:iv => iv}) - enc2 = AES.encrypt(msg, key, {:iv => iv}) + enc1 = AES.encrypt(msg, key, iv: iv) + enc2 = AES.encrypt(msg, key, iv: iv) assert_equal enc1, enc2 end - - should "handle padding option" do - key = "01234567890123456789012345678901" - msg = "This is a message that nobody should ever see" + + should 'handle padding option' do + key = test_key + msg = 'This is a message that nobody should ever see' # unpadded message length should be a multiple of cipher block # length (16 bytes) - msg += " "*(16 - (msg.length % 16)) + msg += ' ' * (16 - (msg.length % 16)) - enc = AES.encrypt(msg, key, {:padding => false}) - assert_equal msg, AES.decrypt(enc, key, {:padding => false}) + enc = AES.encrypt(msg, key, padding: false) + assert_equal msg, AES.decrypt(enc, key, padding: false) end - - should "generate a new key when AES#key" do - assert_equal 32, AES.key.length - assert_equal 44, AES.key(256, :base_64).length + + should 'generate a new key when AES#key' do + assert_equal 64, AES.key.length + assert_equal 89, AES.key(256, :base_64).length + end + + should 'not accept a non-hex key' do + key = 'NotHexEvenThoughItsSixtyFourCharactersLongSoAnErrorIsExpectedNow' + msg = 'This is the plaintext message' + + assert_raise ArgumentError do + AES.encrypt(msg, key) + end end - end From ead129eb8297c3478cd8117c56de666985fa8e85 Mon Sep 17 00:00:00 2001 From: Leonid Morozov Date: Wed, 4 Apr 2018 00:15:20 +0300 Subject: [PATCH 2/2] less useless style fixes --- Gemfile | 12 ++++---- Rakefile | 38 ++++++++++++------------ aes.gemspec | 76 ++++++++++++++++++++++++------------------------ lib/aes.rb | 6 ++-- lib/aes/aes.rb | 12 ++++---- test/helper.rb | 14 ++++----- test/test_aes.rb | 26 ++++++++--------- 7 files changed, 92 insertions(+), 92 deletions(-) diff --git a/Gemfile b/Gemfile index 9e5137c..d628766 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,4 @@ -source 'http://rubygems.org' +source "http://rubygems.org" # Add dependencies required to use your gem here. # Example: # gem "activesupport", ">= 2.3.5" @@ -6,9 +6,9 @@ source 'http://rubygems.org' # Add dependencies to develop your gem here. # Include everything needed to run rake, tests, features, etc. group :development do - gem 'bundler' - gem 'jeweler' - gem 'shoulda' - gem 'simplecov' - gem 'test-unit' + gem "bundler" + gem "jeweler" + gem "shoulda" + gem "simplecov" + gem "test-unit" end diff --git a/Rakefile b/Rakefile index 153c088..bc7fee2 100644 --- a/Rakefile +++ b/Rakefile @@ -1,25 +1,25 @@ -require 'rubygems' -require 'bundler' +require "rubygems" +require "bundler" begin Bundler.setup(:default, :development) rescue Bundler::BundlerError => e warn e.message - warn 'Run `bundle install` to install missing gems' + warn "Run `bundle install` to install missing gems" exit e.status_code end -require 'rake' +require "rake" -require 'jeweler' +require "jeweler" Jeweler::Tasks.new do |gem| # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options - gem.name = 'aes' - gem.homepage = 'http://github.com/chicks/aes' - gem.license = 'MIT' + gem.name = "aes" + gem.homepage = "http://github.com/chicks/aes" + gem.license = "MIT" gem.summary = %{AES#encrypt(key, data), AES#decrypt(key, data). Capiche?} - gem.description = %(An AES encrypt/decrypt gem built ontop of OpenSSL. Not as quick as FastAES, but it doesn't require building + gem.description = %(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.) - gem.email = 'carl.hicks@gmail.com' - gem.authors = ['Carl Hicks'] + gem.email = "carl.hicks@gmail.com" + gem.authors = ["Carl Hicks"] # Include your dependencies below. Runtime dependencies are required when using your gem, # and development dependencies are only needed for development (ie running rake tasks, tests, etc) # gem.add_runtime_dependency 'jabber4r', '> 0.1' @@ -27,21 +27,21 @@ Jeweler::Tasks.new do |gem| end Jeweler::RubygemsDotOrgTasks.new -require 'rake/testtask' +require "rake/testtask" Rake::TestTask.new(:test) do |test| - test.libs << 'lib' << 'test' - test.pattern = 'test/**/test_*.rb' + test.libs << "lib" << "test" + test.pattern = "test/**/test_*.rb" test.verbose = true end task default: :test -require 'rdoc/task' +require "rdoc/task" Rake::RDocTask.new do |rdoc| - version = File.exist?('VERSION') ? File.read('VERSION') : '' + version = File.exist?("VERSION") ? File.read("VERSION") : "" - rdoc.rdoc_dir = 'rdoc' + rdoc.rdoc_dir = "rdoc" rdoc.title = "aes #{version}" - rdoc.rdoc_files.include('README*') - rdoc.rdoc_files.include('lib/**/*.rb') + rdoc.rdoc_files.include("README*") + rdoc.rdoc_files.include("lib/**/*.rb") end diff --git a/aes.gemspec b/aes.gemspec index 6e96a00..77b073c 100644 --- a/aes.gemspec +++ b/aes.gemspec @@ -4,55 +4,55 @@ # -*- encoding: utf-8 -*- Gem::Specification.new do |s| - s.name = 'aes' - s.version = '0.5.0' + s.name = "aes" + s.version = "0.5.0" - s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version= - s.authors = ['Carl Hicks'] - s.date = '2012-05-01' - s.description = "An AES encrypt/decrypt gem built ontop of OpenSSL. Not as quick as FastAES, but it doesn't require building\n native extensions and supports Base64 encoded input and output." - s.email = 'carl.hicks@gmail.com' + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Carl Hicks"] + s.date = "2012-05-01" + s.description = "An AES encrypt/decrypt gem built ontop of OpenSSL. Not as quick as FastAES, but it doesn't require building\n native extensions and supports Base64 encoded input and output." + s.email = "carl.hicks@gmail.com" s.extra_rdoc_files = [ - 'LICENSE.txt', - 'README.rdoc' + "LICENSE.txt", + "README.rdoc" ] s.files = [ - '.document', - 'Gemfile', - 'LICENSE.txt', - 'README.rdoc', - 'Rakefile', - 'VERSION', - 'aes.gemspec', - 'lib/aes.rb', - 'lib/aes/aes.rb', - 'test/helper.rb', - 'test/test_aes.rb' + ".document", + "Gemfile", + "LICENSE.txt", + "README.rdoc", + "Rakefile", + "VERSION", + "aes.gemspec", + "lib/aes.rb", + "lib/aes/aes.rb", + "test/helper.rb", + "test/test_aes.rb" ] - s.homepage = 'http://github.com/chicks/aes' - s.licenses = ['MIT'] - s.require_paths = ['lib'] - s.rubygems_version = '1.8.12' - s.summary = 'AES#encrypt(key, data), AES#decrypt(key, data). Capiche?' + s.homepage = "http://github.com/chicks/aes" + s.licenses = ["MIT"] + s.require_paths = ["lib"] + s.rubygems_version = "1.8.12" + s.summary = "AES#encrypt(key, data), AES#decrypt(key, data). Capiche?" if s.respond_to? :specification_version s.specification_version = 3 - if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') - s.add_development_dependency('bundler', ['>= 0']) - s.add_development_dependency('jeweler', ['>= 0']) - s.add_development_dependency('shoulda', ['>= 0']) - s.add_development_dependency('simplecov', ['>= 0']) + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new("1.2.0") + s.add_development_dependency("bundler", [">= 0"]) + s.add_development_dependency("jeweler", [">= 0"]) + s.add_development_dependency("shoulda", [">= 0"]) + s.add_development_dependency("simplecov", [">= 0"]) else - s.add_dependency('bundler', ['>= 0']) - s.add_dependency('jeweler', ['>= 0']) - s.add_dependency('shoulda', ['>= 0']) - s.add_dependency('simplecov', ['>= 0']) + s.add_dependency("bundler", [">= 0"]) + s.add_dependency("jeweler", [">= 0"]) + s.add_dependency("shoulda", [">= 0"]) + s.add_dependency("simplecov", [">= 0"]) end else - s.add_dependency('shoulda', ['>= 0']) - s.add_dependency('shoulda', ['>= 0']) - s.add_dependency('shoulda', ['>= 0']) - s.add_dependency('simplecov', ['>= 0']) + s.add_dependency("shoulda", [">= 0"]) + s.add_dependency("shoulda", [">= 0"]) + s.add_dependency("shoulda", [">= 0"]) + s.add_dependency("simplecov", [">= 0"]) end end diff --git a/lib/aes.rb b/lib/aes.rb index 2bbeb01..92b3607 100644 --- a/lib/aes.rb +++ b/lib/aes.rb @@ -1,3 +1,3 @@ -require 'openssl' -require 'base64' -require 'aes/aes' +require "openssl" +require "base64" +require "aes/aes" diff --git a/lib/aes/aes.rb b/lib/aes/aes.rb index 148de1a..4fbc221 100644 --- a/lib/aes/aes.rb +++ b/lib/aes/aes.rb @@ -1,5 +1,5 @@ module AES - DEFAULT_AES_CIPHER = 'AES-256-CBC'.freeze + DEFAULT_AES_CIPHER = "AES-256-CBC".freeze class << self # Encrypts the plain_text with the provided key @@ -16,7 +16,7 @@ def decrypt(cipher_text, key, opts = {}) # Default format is :plain def key(length = 256, format = :plain) bytes = OpenSSL::Random.random_bytes(length / 8) - key = bytes.unpack('H*')[0] + key = bytes.unpack("H*")[0] case format when :base_64 @@ -53,7 +53,7 @@ class AES def initialize(key, opts = {}) merge_options opts unless key =~ /\A[A-F0-9]{64}\z/i - raise ArgumentError, 'AES Key must be a 64 character hex string' + raise ArgumentError, "AES Key must be a 64 character hex string" end @cipher = nil @key = key @@ -68,7 +68,7 @@ def encrypt(plain_text) @cipher.iv = @iv @cipher_text = case @options[:format] when :base_64 - b64_e(@iv) << '$' << b64_e(_encrypt) + b64_e(@iv) << "$" << b64_e(_encrypt) else [@iv, _encrypt] end @@ -108,7 +108,7 @@ def random_key(length = 256) # Returns an array containing the IV, and CipherText def b64_d(data) iv_and_ctext = [] - data.split('$').each do |part| + data.split("$").each do |part| iv_and_ctext << Base64.decode64(part) end iv_and_ctext @@ -157,7 +157,7 @@ def _setup(action) # Toggles encryption mode @cipher.send(action) @cipher.padding = @options[:padding] - @cipher.key = [@key].pack('H*') + @cipher.key = [@key].pack("H*") end end end diff --git a/test/helper.rb b/test/helper.rb index 76d0f0a..4f412fe 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -1,18 +1,18 @@ -require 'rubygems' -require 'bundler' +require "rubygems" +require "bundler" begin Bundler.setup(:default, :development) rescue Bundler::BundlerError => e warn e.message - warn 'Run `bundle install` to install missing gems' + warn "Run `bundle install` to install missing gems" exit e.status_code end -require 'test/unit' -require 'shoulda' +require "test/unit" +require "shoulda" -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib")) $LOAD_PATH.unshift(File.dirname(__FILE__)) -require 'aes' +require "aes" class Test::Unit::TestCase end diff --git a/test/test_aes.rb b/test/test_aes.rb index 961f81e..74c5c43 100644 --- a/test/test_aes.rb +++ b/test/test_aes.rb @@ -1,45 +1,45 @@ -require 'helper' +require "helper" class TestAES < Test::Unit::TestCase - test_key = '66c2454a167226f132098cfeb18eac31ec2a66104fc3c2187816baaba2d8ed39' + test_key = "66c2454a167226f132098cfeb18eac31ec2a66104fc3c2187816baaba2d8ed39" - should 'encrypt and decrypt a string' do + should "encrypt and decrypt a string" do key = test_key - msg = 'This is a message that nobody should ever see' + msg = "This is a message that nobody should ever see" enc = AES.encrypt(msg, key) assert_equal msg, AES.decrypt(enc, key) enc = AES.encrypt(msg, key, format: :plain) assert_equal msg, AES.decrypt(enc, key, format: :plain) end - should 'produce the same encrypted string when provided an identical key and iv' do + should "produce the same encrypted string when provided an identical key and iv" do key = test_key - msg = 'This is a message that nobody should ever see' + msg = "This is a message that nobody should ever see" iv = AES.iv(:base_64) enc1 = AES.encrypt(msg, key, iv: iv) enc2 = AES.encrypt(msg, key, iv: iv) assert_equal enc1, enc2 end - should 'handle padding option' do + should "handle padding option" do key = test_key - msg = 'This is a message that nobody should ever see' + msg = "This is a message that nobody should ever see" # unpadded message length should be a multiple of cipher block # length (16 bytes) - msg += ' ' * (16 - (msg.length % 16)) + msg += " " * (16 - (msg.length % 16)) enc = AES.encrypt(msg, key, padding: false) assert_equal msg, AES.decrypt(enc, key, padding: false) end - should 'generate a new key when AES#key' do + should "generate a new key when AES#key" do assert_equal 64, AES.key.length assert_equal 89, AES.key(256, :base_64).length end - should 'not accept a non-hex key' do - key = 'NotHexEvenThoughItsSixtyFourCharactersLongSoAnErrorIsExpectedNow' - msg = 'This is the plaintext message' + should "not accept a non-hex key" do + key = "NotHexEvenThoughItsSixtyFourCharactersLongSoAnErrorIsExpectedNow" + msg = "This is the plaintext message" assert_raise ArgumentError do AES.encrypt(msg, key)