travis-encrypt 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +23 -0
- data/lib/travis/encrypt.rb +27 -0
- data/lib/travis/encrypt/common.rb +33 -0
- data/lib/travis/encrypt/decryptor.rb +49 -0
- data/lib/travis/encrypt/encryptor.rb +41 -0
- data/lib/travis/encrypt/helpers.rb +18 -0
- data/lib/travis/encrypt/helpers/active_record.rb +13 -0
- data/lib/travis/encrypt/helpers/common.rb +30 -0
- data/lib/travis/encrypt/helpers/sequel.rb +31 -0
- data/lib/travis/encrypt/version.rb +5 -0
- data/spec/encrypt_spec.rb +21 -0
- data/spec/helpers_spec.rb +45 -0
- data/spec/spec_helper.rb +1 -0
- data/travis-encrypt.gemspec +19 -0
- metadata +59 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3cc5b08f7b744a0d65048a30fbc106574ca09020
|
4
|
+
data.tar.gz: d305be5fa49e303584418c5f848f6a3a333808a7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cd83823e74a711d52dd0e2631f32a0124a38bd6758eb39b76943b4a0f23db04ae8422637b2615f38fa606b4855679f89b1e8a59dd1f0cd24209e1983f772eda3
|
7
|
+
data.tar.gz: 7daf90258525aaadabb554da5ed37702117b02e756a98065a7f6125c69ee442be9b8d08971f57195c1236f6658f75f15fc714ee9bba2f37e5c40e9cda02c09f7
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.2.5)
|
5
|
+
rspec (3.3.0)
|
6
|
+
rspec-core (~> 3.3.0)
|
7
|
+
rspec-expectations (~> 3.3.0)
|
8
|
+
rspec-mocks (~> 3.3.0)
|
9
|
+
rspec-core (3.3.2)
|
10
|
+
rspec-support (~> 3.3.0)
|
11
|
+
rspec-expectations (3.3.1)
|
12
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
13
|
+
rspec-support (~> 3.3.0)
|
14
|
+
rspec-mocks (3.3.2)
|
15
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
16
|
+
rspec-support (~> 3.3.0)
|
17
|
+
rspec-support (3.3.0)
|
18
|
+
|
19
|
+
PLATFORMS
|
20
|
+
ruby
|
21
|
+
|
22
|
+
DEPENDENCIES
|
23
|
+
rspec
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'base64'
|
3
|
+
require 'travis/encrypt/decryptor'
|
4
|
+
require 'travis/encrypt/encryptor'
|
5
|
+
require 'travis/encrypt/helpers'
|
6
|
+
|
7
|
+
module Travis
|
8
|
+
module Encrypt
|
9
|
+
PREFIX = '--ENCR--'
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_accessor :key
|
13
|
+
|
14
|
+
def setup(config)
|
15
|
+
self.key = config[:key]
|
16
|
+
end
|
17
|
+
|
18
|
+
def encrypt(string, options)
|
19
|
+
Encryptor.new(string, { key: key }.merge(options)).apply
|
20
|
+
end
|
21
|
+
|
22
|
+
def decrypt(string, options)
|
23
|
+
Decryptor.new(string, { key: key }.merge(options)).apply
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Travis
|
2
|
+
module Encrypt
|
3
|
+
module Common
|
4
|
+
def create_aes(mode = :encrypt, key, iv)
|
5
|
+
aes = OpenSSL::Cipher::AES.new(256, :CBC)
|
6
|
+
aes.send(mode)
|
7
|
+
aes.key = key
|
8
|
+
aes.iv = iv
|
9
|
+
aes
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_iv
|
13
|
+
SecureRandom.hex(8)
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_iv(string, iv)
|
17
|
+
"#{string}#{iv}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def extract_iv(string)
|
21
|
+
[string[-16..-1], string[0..-17]]
|
22
|
+
end
|
23
|
+
|
24
|
+
def encode(str)
|
25
|
+
Base64.strict_encode64(str)
|
26
|
+
end
|
27
|
+
|
28
|
+
def decode(str)
|
29
|
+
Base64.strict_decode64(str)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'travis/encrypt/common'
|
2
|
+
|
3
|
+
module Travis
|
4
|
+
module Encrypt
|
5
|
+
class Decryptor
|
6
|
+
include Common
|
7
|
+
|
8
|
+
attr_reader :string, :key, :options
|
9
|
+
|
10
|
+
def initialize(string, options)
|
11
|
+
@string = string
|
12
|
+
@key = options[:key] || fail("Need to pass a key")
|
13
|
+
@options = options || {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def apply?
|
17
|
+
string && (!use_prefix? || prefix_used?)
|
18
|
+
end
|
19
|
+
|
20
|
+
def apply
|
21
|
+
apply? ? decrypt : string
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def use_prefix?
|
27
|
+
!!options[:use_prefix]
|
28
|
+
end
|
29
|
+
|
30
|
+
def prefix_used?
|
31
|
+
string[0..7] == PREFIX
|
32
|
+
end
|
33
|
+
|
34
|
+
def decrypt
|
35
|
+
string = self.string
|
36
|
+
string = string[8..-1] if prefix_used?
|
37
|
+
decoded = decode(string.to_s)
|
38
|
+
iv, string = extract_iv(decoded)
|
39
|
+
|
40
|
+
# A nil iv most likely means that the decoded string was not encrypted
|
41
|
+
# to begin with, so we return the plain string.
|
42
|
+
return string if iv.nil?
|
43
|
+
|
44
|
+
aes = create_aes(:decrypt, key.to_s, iv)
|
45
|
+
aes.update(string) + aes.final
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'travis/encrypt/common'
|
2
|
+
|
3
|
+
module Travis
|
4
|
+
module Encrypt
|
5
|
+
class Encryptor
|
6
|
+
include Common
|
7
|
+
|
8
|
+
attr_reader :string, :key, :options
|
9
|
+
|
10
|
+
def initialize(string, options)
|
11
|
+
@string = string
|
12
|
+
@key = options[:key] || fail("Need to pass a key")
|
13
|
+
@options = options || {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def apply?
|
17
|
+
!!string && !string.empty? && !options[:disable] # TODO ask piotr
|
18
|
+
end
|
19
|
+
|
20
|
+
def apply
|
21
|
+
apply? ? encrypt : string
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def encrypt
|
27
|
+
iv = create_iv
|
28
|
+
aes = create_aes(:encrypt, key.to_s, iv)
|
29
|
+
string = aes.update(self.string) + aes.final
|
30
|
+
string = add_iv(string, iv)
|
31
|
+
string = encode(string)
|
32
|
+
string = "#{PREFIX}#{string}" if use_prefix?
|
33
|
+
string
|
34
|
+
end
|
35
|
+
|
36
|
+
def use_prefix?
|
37
|
+
options.key?(:use_prefix) ? !!options[:use_prefix] : true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'travis/encrypt/helpers/active_record'
|
2
|
+
require 'travis/encrypt/helpers/sequel'
|
3
|
+
|
4
|
+
module Travis
|
5
|
+
module Encrypt
|
6
|
+
module Helpers
|
7
|
+
def encrypt(string, options = {})
|
8
|
+
options[:key] ||= Encrypt.key
|
9
|
+
Encrypt.encrypt(string, options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def decrypt(string, options = {})
|
13
|
+
options[:key] ||= Encrypt.key
|
14
|
+
Encrypt.decrypt(string, options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Travis
|
2
|
+
module Encrypt
|
3
|
+
module Helpers
|
4
|
+
module Common
|
5
|
+
module ClassMethods
|
6
|
+
def attr_encrypted(*names)
|
7
|
+
options = names.last.is_a?(Hash) ? names.pop : {}
|
8
|
+
define_encrypted_accessors(names, options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def define_encrypted_accessors(names, options)
|
12
|
+
names.each do |name|
|
13
|
+
define_encrypted_accessor(name, options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def define_encrypted_accessor(name, options)
|
18
|
+
define_method(name) do
|
19
|
+
Encrypt.decrypt(self[name], options)
|
20
|
+
end
|
21
|
+
|
22
|
+
define_method(:"#{name}=") do |string|
|
23
|
+
self[name] = Encrypt.encrypt(string, options)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'travis/encrypt/helpers/common'
|
2
|
+
|
3
|
+
module Travis
|
4
|
+
module Encrypt
|
5
|
+
module Helpers
|
6
|
+
module Sequel
|
7
|
+
module ClassMethods
|
8
|
+
def attr_encrypted(*names)
|
9
|
+
options = names.last.is_a?(Hash) ? names.pop : {}
|
10
|
+
super
|
11
|
+
define_encrypted_values(names, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def define_encrypted_values(names, options)
|
15
|
+
define_method(:values) do
|
16
|
+
super().inject({}) do |values, (name, value)|
|
17
|
+
value = Encrypt.decrypt(value, options) if names.include?(name)
|
18
|
+
values.merge(name => value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.included(base)
|
25
|
+
base.extend(Common::ClassMethods)
|
26
|
+
base.extend(ClassMethods)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
describe Travis::Encrypt do
|
2
|
+
include described_class::Helpers
|
3
|
+
|
4
|
+
let(:string) { 'travis' }
|
5
|
+
let(:encrypted) { encrypt(string, options) }
|
6
|
+
let(:decrypted) { decrypt(encrypted, options) }
|
7
|
+
let(:options) { { key: 'abcd' * 8 } }
|
8
|
+
|
9
|
+
it 'can decrypt an encrypted string' do
|
10
|
+
expect(decrypted).to eql(string)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'prefixes the encrypted string by default' do
|
14
|
+
expect(encrypted[0..7]).to eql(Travis::Encrypt::PREFIX)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'does not prefix the encrypted string when opted out' do
|
18
|
+
options[:use_prefix] = false
|
19
|
+
expect(encrypted[0..7]).to_not eql(described_class::PREFIX)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
describe Travis::Encrypt::Helpers do
|
2
|
+
subject { const.new }
|
3
|
+
before { Travis::Encrypt.key = 'abcd' * 8 }
|
4
|
+
|
5
|
+
shared_examples_for 'attributes' do
|
6
|
+
it 'encrypts an attribute' do
|
7
|
+
subject.attr = 'bar'
|
8
|
+
expect(subject.to_h.values.first[0..7]).to eql(Travis::Encrypt::PREFIX)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'decrypts an encrypted attribute' do
|
12
|
+
subject.attr = 'bar'
|
13
|
+
expect(subject.attr).to eql('bar')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe described_class::ActiveRecord do
|
18
|
+
let(:const) do
|
19
|
+
Struct.new(:attr) do
|
20
|
+
include Travis::Encrypt::Helpers::ActiveRecord
|
21
|
+
attr_encrypted :attr
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
include_examples 'attributes'
|
26
|
+
end
|
27
|
+
|
28
|
+
describe described_class::Sequel do
|
29
|
+
let(:const) do
|
30
|
+
Struct.new(:attr) do
|
31
|
+
# Sequel's values method returns a hash of attributes
|
32
|
+
include Module.new { def values; to_h; end }
|
33
|
+
include Travis::Encrypt::Helpers::Sequel
|
34
|
+
attr_encrypted :attr
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
include_examples 'attributes'
|
39
|
+
|
40
|
+
it 'decrypts an encrypted value' do
|
41
|
+
subject.attr = 'bar'
|
42
|
+
expect(subject.values).to eql(attr: 'bar')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'travis/encrypt'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
$:.unshift File.expand_path('../lib', __FILE__)
|
4
|
+
require 'travis/encrypt/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "travis-encrypt"
|
8
|
+
s.version = Travis::Encrypt::VERSION
|
9
|
+
s.authors = ["Travis CI"]
|
10
|
+
s.email = "contact@travis-ci.org"
|
11
|
+
s.homepage = "https://github.com/travis-ci/travis-encrypt"
|
12
|
+
s.summary = "Travis CI encryption support"
|
13
|
+
s.description = "#{s.summary}."
|
14
|
+
s.license = "MIT"
|
15
|
+
|
16
|
+
s.files = Dir['{bin/**/*,lib/**/*,spec/**/*,[A-Z]*}']
|
17
|
+
s.platform = Gem::Platform::RUBY
|
18
|
+
s.require_path = 'lib'
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: travis-encrypt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Travis CI
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-26 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Travis CI encryption support.
|
14
|
+
email: contact@travis-ci.org
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- Gemfile
|
20
|
+
- Gemfile.lock
|
21
|
+
- lib/travis/encrypt.rb
|
22
|
+
- lib/travis/encrypt/common.rb
|
23
|
+
- lib/travis/encrypt/decryptor.rb
|
24
|
+
- lib/travis/encrypt/encryptor.rb
|
25
|
+
- lib/travis/encrypt/helpers.rb
|
26
|
+
- lib/travis/encrypt/helpers/active_record.rb
|
27
|
+
- lib/travis/encrypt/helpers/common.rb
|
28
|
+
- lib/travis/encrypt/helpers/sequel.rb
|
29
|
+
- lib/travis/encrypt/version.rb
|
30
|
+
- spec/encrypt_spec.rb
|
31
|
+
- spec/helpers_spec.rb
|
32
|
+
- spec/spec_helper.rb
|
33
|
+
- travis-encrypt.gemspec
|
34
|
+
homepage: https://github.com/travis-ci/travis-encrypt
|
35
|
+
licenses:
|
36
|
+
- MIT
|
37
|
+
metadata: {}
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 2.4.5
|
55
|
+
signing_key:
|
56
|
+
specification_version: 4
|
57
|
+
summary: Travis CI encryption support
|
58
|
+
test_files: []
|
59
|
+
has_rdoc:
|