Skip to content

Commit

Permalink
New structure, Mifiel module should include all classes
Browse files Browse the repository at this point in the history
  • Loading branch information
aldosolorzano committed Nov 27, 2018
1 parent 322416a commit 0fea25a
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 140 deletions.
5 changes: 0 additions & 5 deletions lib/crypto.rb

This file was deleted.

67 changes: 0 additions & 67 deletions lib/crypto/aes.rb

This file was deleted.

50 changes: 0 additions & 50 deletions lib/crypto/pbe.rb

This file was deleted.

2 changes: 1 addition & 1 deletion lib/mifiel.rb
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require 'flexirest'
require_relative './crypto'

module Mifiel
require 'mifiel/errors'
Expand All @@ -9,6 +8,7 @@ module Mifiel
autoload :Template, 'mifiel/template'
autoload :Config, 'mifiel/config'
autoload :User, 'mifiel/user'
autoload :Crypto, 'mifiel/crypto'

BASE_URL = 'https://www.mifiel.com/api/v1'.freeze

Expand Down
17 changes: 17 additions & 0 deletions lib/mifiel/crypto.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module Mifiel::Crypto
autoload :PBE, 'mifiel/crypto/pbe'
autoload :Response, 'mifiel/crypto/response'
autoload :AES, 'mifiel/crypto/aes'
autoload :ECIES, 'mifiel/crypto/ecies'
end

class String
def bth
self.unpack('H*').first
end

def htb
Array(self).pack('H*')
end
end

68 changes: 68 additions & 0 deletions lib/mifiel/crypto/aes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
require 'openssl'
module Mifiel
module Crypto
class AES
CIPHER = 256
SIZE = 16

def self.random_iv(size = SIZE)
OpenSSL::Random.random_bytes(size)
end

def self.encrypt(args)
aes = Crypto::AES.new(args[:cipher] || CIPHER)
aes.encrypt(args)
end

def self.decrypt(args)
aes = Crypto::AES.new(args[:cipher] || CIPHER)
aes.decrypt(args)
end

attr_accessor :cipher, :require_args

def initialize(cipher_type = CIPHER)
@require_args = [:key, :iv, :data]
@cipher = OpenSSL::Cipher::AES.new(cipher_type, :CBC)
end

def random_iv(size = SIZE)
Crypto::AES.random_iv(size)
end

def encrypt(args)
validate_args(args)
cipher.encrypt
cipher.key = args[:key]
cipher.iv = args[:iv]
encrypted_data = cipher.update(args[:data]) + cipher.final
Encrypted.new(encrypted_data)
end

def decrypt(args)
validate_args(args)
cipher.decrypt
cipher.key = args[:key]
cipher.iv = args[:iv]
cipher.update(args[:data]) + cipher.final
end

private

def validate_args(args)
keys = args.keys
require_args.each do |a|
unless keys.include?(a)
raise ArgumentError, "Expected keys #{require_args}"
end
end
end
end

class Encrypted < Mifiel::Crypto::Response
def to_str
data
end
end
end
end
52 changes: 52 additions & 0 deletions lib/mifiel/crypto/pbe.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
require 'openssl'
require 'securerandom'

module Mifiel
module Crypto
class PBE
ALPHA_NUM = ('0'..'9').to_a + ('A'..'Z').to_a + ('a'..'z').to_a
SPECIALS = ['-', '_', '+', '=', '#', '&', '*', '.'].freeze
CHARS = ALPHA_NUM + SPECIALS

def self.generate
pbe = Crypto::PBE.new
password = pbe.random_password
salt = pbe.random_salt
pbe.derived_key(password, salt)
end

def initialize(i = 1000)
@iterations = i
@digest = OpenSSL::Digest::SHA256.new
end

def random_password(length = 32)
CHARS.sort_by { SecureRandom.random_number }.join[0...length]
end

def random_salt(size = 16)
SecureRandom.random_bytes(size)
end

def derived_key(password, salt, sizeKey = 24)
args = {
password: password,
salt: salt,
iterations: @iterations,
sizeKey: sizeKey,
digest: @digest
}
PKCS5.new(args)
end
end

class PKCS5 < Mifiel::Crypto::Response
attr_reader :key

def initialize(args)
@key = OpenSSL::PKCS5.pbkdf2_hmac(*args.values)
@data = key # key attribute is syntax sugar
end
end
end
end
4 changes: 3 additions & 1 deletion lib/crypto/response.rb → lib/mifiel/crypto/response.rb
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module Crypto
module Mifiel
module Crypto
class Response
attr_reader :data

Expand All @@ -14,4 +15,5 @@ def to_hex
data.unpack('H*').first
end
end
end
end
18 changes: 9 additions & 9 deletions spec/crypto/aes_spec.rb → spec/mifiel/crypto/aes_spec.rb
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
describe Crypto::AES do
describe Mifiel::Crypto::AES do
aes_fixture = JSON.parse(File.read('spec/fixtures/aes.json'), symbolize_names: true)

describe '#AES good' do
aes_fixture[:valid].each do |v|
describe v.slice(:algorithm, :key, :dataToEncrypt).to_s do
e_args = { data: v[:dataToEncrypt], key: v[:key], iv: v[:iv], cipher: v[:algorithm] }
d_args = e_args.clone
let(:aes) { Crypto::AES.new(e_args[:cipher]) }
let(:aes) { Mifiel::Crypto::AES.new(e_args[:cipher]) }
let(:encrypted) { aes.encrypt(e_args) }
it 'should return Encrypted instance' do
expect(encrypted).to be_a Crypto::Encrypted
expect(encrypted).to be_a Mifiel::Crypto::Encrypted
end
it 'should return encrypted hex' do
expect(encrypted.to_hex).to eq(v[:encrypted])
Expand All @@ -23,19 +23,19 @@
expect(aes.decrypt(d_args)).to eq(v[:dataToEncrypt])
end
it 'should encrypt & decrypt with static method' do
encrypted_data = Crypto::AES.encrypt(e_args)
encrypted_data = Mifiel::Crypto::AES.encrypt(e_args)
expect(encrypted_data == encrypted).to be true
expect(encrypted_data.to_hex).to eq(v[:encrypted])
d_args[:data] = encrypted_data
expect(Crypto::AES.decrypt(d_args)).to eq(v[:dataToEncrypt])
expect(Mifiel::Crypto::AES.decrypt(d_args)).to eq(v[:dataToEncrypt])
end
end
end

describe 'Generate random iv' do
let(:ivs) { Set.new }
5.times do
iv = Crypto::AES.random_iv.unpack('H*').first
iv = Mifiel::Crypto::AES.random_iv.unpack('H*').first
it "should be unique #{iv}" do
expect(ivs.include?(iv)).to be false
ivs.add(iv)
Expand All @@ -46,11 +46,11 @@

describe '#AES bad' do
describe 'ArgumentError, sending wrong data to decrypt' do
args = { data: 'bad-data', iv: Crypto::AES.random_iv, key: 'this-aSecure-key' }
let(:expected_error) { "Expected keys #{Crypto::AES.new.require_args}" }
args = { data: 'bad-data', iv: Mifiel::Crypto::AES.random_iv, key: 'this-aSecure-key' }
let(:expected_error) { "Expected keys #{Mifiel::Crypto::AES.new.require_args}" }
it 'should raise expected error' do
args = {}
expect { Crypto::AES.decrypt(args) }.to raise_error(ArgumentError, expected_error)
expect { Mifiel::Crypto::AES.decrypt(args) }.to raise_error(ArgumentError, expected_error)
end
end
end
Expand Down
14 changes: 7 additions & 7 deletions spec/crypto/pbe_spec.rb → spec/mifiel/crypto/pbe_spec.rb
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
describe Crypto::PBE do
describe Mifiel::Crypto::PBE do
pbe_fixture = JSON.parse(File.read('spec/fixtures/pbe.json'), symbolize_names: true)
let(:alpha_num) { ('0'..'9').to_a + ('A'..'Z').to_a + ('a'..'z').to_a }
let(:specials) { ['-', '_', '+', '=', '#', '&', '*', '.'] }
Expand All @@ -7,7 +7,7 @@
describe '#PBE good' do
pbe_fixture[:valid].each do |v|
describe v.slice(:key, :salt, :keylen, :iterations).to_s do
let(:pbe) { Crypto::PBE.new(v[:iterations]) }
let(:pbe) { Mifiel::Crypto::PBE.new(v[:iterations]) }
let(:key) { pbe.derived_key(v[:key], v[:salt], v[:keylen]) }
it 'should return a strong key' do
expect(key.to_hex).to eq(v[:result])
Expand All @@ -18,14 +18,14 @@
describe 'Generate random keys' do
let(:keys) { Set.new }
5.times do
key = Crypto::PBE.generate.to_hex
key = Mifiel::Crypto::PBE.generate.to_hex
it "should be unique #{key}" do
expect(keys.include?(key)).to be false
keys.add(key)
end
it 'should compare keys with def==(other)' do
key = Crypto::PBE.generate
key1 = Crypto::PBE.generate
key = Mifiel::Crypto::PBE.generate
key1 = Mifiel::Crypto::PBE.generate
expect(key == key1).to be false
end
end
Expand All @@ -36,7 +36,7 @@
key_lens = [32, 64, 40]
5.times do
size = key_lens.sample
pass = Crypto::PBE.new.random_password(size)
pass = Mifiel::Crypto::PBE.new.random_password(size)
it "should be unique #{pass}" do
expect(passwords.include?(pass)).to be false
passwords.add(pass)
Expand All @@ -55,7 +55,7 @@
describe '#PBE bad' do
pbe_fixture[:invalid].each do |v|
describe v[:description].to_s do
let(:pbe) { Crypto::PBE.new(v[:iterations]) }
let(:pbe) { Mifiel::Crypto::PBE.new(v[:iterations]) }
let(:error) { "integer #{v[:keylen]} too big to convert to `int'" }
it 'should raise key length error' do
expect { pbe.derived_key(v[:key], v[:salt], v[:keylen]) }.to raise_error(RangeError, error)
Expand Down

0 comments on commit 0fea25a

Please sign in to comment.