Skip to content

Commit

Permalink
Merge c2c3a9a into 5ab16e3
Browse files Browse the repository at this point in the history
  • Loading branch information
aldosolorzano committed Dec 4, 2018
2 parents 5ab16e3 + c2c3a9a commit 251d11a
Show file tree
Hide file tree
Showing 12 changed files with 397 additions and 15 deletions.
10 changes: 0 additions & 10 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,3 @@ source 'https://rubygems.org'

# Specify your gem's dependencies in mifiel.gemspec
gemspec

group :development, :test do
gem 'coveralls', require: false
gem 'guard', '2.13.0'
gem 'guard-rspec'
# compatible with ruby >= 1.9.3
gem 'guard-rubocop'
gem 'listen', '3.0.8'
gem 'terminal-notifier-guard'
end
1 change: 1 addition & 0 deletions lib/mifiel.rb
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -8,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
18 changes: 18 additions & 0 deletions lib/mifiel/crypto.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module Mifiel
module Crypto
autoload :PBE, 'mifiel/crypto/pbe'
autoload :Response, 'mifiel/crypto/response'
autoload :AES, 'mifiel/crypto/aes'
autoload :ECIES, 'mifiel/crypto/ecies'
end
end

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

def htb
Array(self).pack('H*')
end
end
58 changes: 58 additions & 0 deletions lib/mifiel/crypto/aes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
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(cipher: CIPHER, key: nil, iv: nil, data: nil)
aes = Mifiel::Crypto::AES.new(cipher)
args = { cipher: cipher, key: key, iv: iv, data: data }
aes.encrypt(args)
end

def self.decrypt(cipher: CIPHER, key: nil, iv: nil, data: nil)
aes = Mifiel::Crypto::AES.new(cipher)
args = { cipher: cipher, key: key, iv: iv, data: data }
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)
Mifiel::Crypto::AES.random_iv(size)
end

def encrypt(key: nil, iv: nil, data: nil)
iv ||= random_iv
Encrypted.new(cipher_final(key, iv, data, action: :encrypt))
end

def decrypt(key: nil, iv: nil, data: nil)
cipher_final(key, iv, data, action: :decrypt)
end

def cipher_final(key, iv, message, action: :encrypt)
@cipher.send(action)
@cipher.iv = iv
@cipher.key = key
@cipher.update(message) + @cipher.final
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
19 changes: 19 additions & 0 deletions lib/mifiel/crypto/response.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module Mifiel
module Crypto
class Response
attr_reader :data

def ==(other)
data == other.data
end

def initialize(data)
@data = data
end

def to_hex
data.unpack('H*').first
end
end
end
end
3 changes: 1 addition & 2 deletions mifiel.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ Gem::Specification.new do |spec|

spec.add_development_dependency 'bump', '~> 0.5', '>= 0.5.3'
spec.add_development_dependency 'bundler', '~> 1.6'
spec.add_development_dependency 'byebug', '~> 9.0', '< 9.0.6'
spec.add_development_dependency 'pry-byebug', '~> 3.4', '>= 3.3.0'
spec.add_development_dependency 'coveralls', '~> 0.8', '>= 0.8.22'
spec.add_development_dependency 'rake', '~> 10.0'
spec.add_development_dependency 'rspec', '~> 3.1', '>= 3.1.7'
spec.add_development_dependency 'rubocop', '0.47.1'
Expand Down
68 changes: 68 additions & 0 deletions spec/fixtures/aes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"valid": [
{
"algorithm":128,
"key": "1234567890123456",
"dataToEncrypt": "cifrado de Prueba",
"iv": "6976207465737469",
"encrypted": "e69522e578832e378221b541431e64e6e704c17d8b2bdda598ebd3c716836d03"
},
{
"algorithm":128,
"key": "derivedKEY234556",
"dataToEncrypt": "test de cifrado",
"iv": "3436353837383837",
"encrypted": "2b27f69570049490f5fee3bed8c045d9"
},
{
"algorithm":128,
"key": "a9r82*9rn5Flp3/o",
"dataToEncrypt": "test de cifrado",
"iv": "1353837383861646",
"encrypted": "1b6a81b3ce5eb6ae3a239d0ee51e2699"
},

{
"algorithm":192,
"key": "123456789012345678901234",
"dataToEncrypt": "cifrado de Prueba AES-192",
"iv": "6466736438373435",
"encrypted": "0cf4ea5765b42b9088c901064c07ba7a6eec3030609673830fcbd8ac5cc77edd"
},
{
"algorithm":192,
"key": "derivedKEY234556iksRtryr",
"dataToEncrypt": "test de cifrado AES-192",
"iv": "7266736438373435",
"encrypted": "fd0fec1268dbb111babc5b8a15397ad946af61561eb6d40c36068c04ddf5d008"
},
{
"algorithm":192,
"key": "*854FrGTH/hgf_4f6h9v4dfg",
"dataToEncrypt": "encrypted decrypted data",
"iv": "2e39746438373435",
"encrypted": "43e7e6f7a56a73a60d5b619e590b91de3c79e765a37f893f122a6b3e9497f8f6"
},
{
"algorithm": 256,
"key": "12345678901234567890123456789012",
"dataToEncrypt": "cifrado de Prueba AES-256",
"iv": "39382e2e2d6438rf",
"encrypted": "60ea45d407514d4e67ef0eb12b2df8e5ea02f156cdea71eeafda0b0b54092d63"
},
{
"algorithm":256,
"key": "derivedKEY234556iksRtryrtg578hfr",
"dataToEncrypt": "test de cifrado AES-256",
"iv": "7266736438373435",
"encrypted": "6d2e185278b5a87da86941b390ac7baffee5e87ae86d877350edbe9a6077e396"
},
{
"algorithm":256,
"key": "*854FrGTH/hgf_4f6h9v4dfg*&jr-jew",
"dataToEncrypt": "test de cifrado",
"iv": "2e39746438373435",
"encrypted": "3c3dc5a978f756a576a952b4eb3ca868"
}
]
}
68 changes: 68 additions & 0 deletions spec/fixtures/pbe.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"valid": [
{
"key": "passwd",
"salt": "salt",
"iterations": 1,
"keylen": 64,
"result": "55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783" },
{
"key": "Password",
"salt": "NaCl",
"iterations": 80000,
"keylen": 64,
"result": "4ddcd8f60b98be21830cee5ef22701f9641a4418d04c0414aeff08876b34ab56a1d425a1225833549adb841b51c9b3176a272bdebba1d078478f62b397f33c8d" },
{
"key": "password",
"salt": "salt",
"iterations": 1,
"keylen": 32,
"result": "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b" },
{
"key": "password",
"salt": "salt",
"iterations": 2,
"keylen": 32,
"result": "ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43" },
{
"key": "password",
"salt": "salt",
"iterations": 4096,
"keylen": 32,
"result": "c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a"
},
{
"key": "passwordPASSWORDpassword",
"salt": "saltSALTsaltSALTsaltSALTsaltSALTsalt",
"iterations": 4096,
"keylen": 40,
"result": "348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9"
},
{
"key": "",
"salt": "salt",
"iterations": 1024,
"keylen": 32,
"result": "9e83f279c040f2a11aa4a02b24c418f2d3cb39560c9627fa4f47e3bcc2897c3d"

},
{
"key": "password",
"salt": "",
"iterations": 1024,
"keylen": 32,
"result": "ea5808411eb0c7e830deab55096cee582761e22a9bc034e3ece925225b07bf46"

}
],
"invalid": [
{
"key": "password",
"salt": "afas",
"iterations": 1024,
"keylen": 35184372088832,
"result": "",
"description": "key length too long"
}
]
}
46 changes: 46 additions & 0 deletions spec/mifiel/crypto/aes_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
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) { Mifiel::Crypto::AES.new(e_args[:cipher]) }
let(:encrypted) { aes.encrypt(e_args) }
it 'should return Encrypted instance' do
expect(encrypted).to be_a Mifiel::Crypto::Encrypted
end
it 'should return encrypted hex' do
expect(encrypted.to_hex).to eq(v[:encrypted])
end
it 'should receive binary data and return decipher text' do
d_args[:data] = encrypted.data
expect(aes.decrypt(d_args)).to eq(v[:dataToEncrypt])
end
it 'should receive Encrypted instance & return decipher text' do
d_args[:data] = encrypted
expect(aes.decrypt(d_args)).to eq(v[:dataToEncrypt])
end
it 'should encrypt & decrypt with static method' do
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(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 = Mifiel::Crypto::AES.random_iv.unpack('H*').first
it "should be unique #{iv}" do
expect(ivs.include?(iv)).to be false
ivs.add(iv)
end
end
end
end
end
Loading

0 comments on commit 251d11a

Please sign in to comment.