ripple-encryption 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +13 -0
- data/Gemfile.lock +80 -0
- data/LICENSE +16 -0
- data/README.md +67 -0
- data/Rakefile +32 -0
- data/config/encryption.yml.example +20 -0
- data/config/ripple.yml.example +9 -0
- data/lib/rake/migrate.rb +82 -0
- data/lib/ripple-encryption.rb +10 -0
- data/lib/ripple-encryption/activation.rb +75 -0
- data/lib/ripple-encryption/config.rb +43 -0
- data/lib/ripple-encryption/encrypted_json_document.rb +29 -0
- data/lib/ripple-encryption/encryptor.rb +48 -0
- data/lib/ripple-encryption/json_document.rb +24 -0
- data/lib/ripple-encryption/serializer.rb +117 -0
- data/lib/ripple-encryption/version.rb +5 -0
- data/ripple-encryption.gemspec +24 -0
- data/test/fixtures/encryption.yml +5 -0
- data/test/fixtures/encryption_no_iv.yml +3 -0
- data/test/fixtures/ripple.yml +4 -0
- data/test/fixtures/test_document/some_data.unencrypted.riak +1 -0
- data/test/fixtures/test_document/some_other_data.encrypted.riak +1 -0
- data/test/fixtures/test_document/v0_doc.riak +1 -0
- data/test/fixtures/test_document/v1_doc.riak +1 -0
- data/test/fixtures/test_document/v2_doc.riak +1 -0
- data/test/helper.rb +53 -0
- data/test/test_config.rb +11 -0
- data/test/test_encryptor.rb +42 -0
- data/test/test_json_document.rb +42 -0
- data/test/test_ripple.rb +27 -0
- data/test/test_unencrypted_document.rb +24 -0
- metadata +156 -0
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in ripple-contrib.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
gem 'riak-client', '~> 1.1.1'
|
7
|
+
gem 'ripple', :git => 'git://github.com/basho/ripple.git', :ref => '913806aa2942db5a3b61d1432d2c9be200338f50'
|
8
|
+
|
9
|
+
group :development, :test do
|
10
|
+
gem 'linecache19', :git => 'git://github.com/mark-moseley/linecache'
|
11
|
+
gem 'ruby-debug-base19x', '~> 0.11.30.pre4'
|
12
|
+
gem "ruby-debug19", "0.11.6"
|
13
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git://github.com/basho/ripple.git
|
3
|
+
revision: 913806aa2942db5a3b61d1432d2c9be200338f50
|
4
|
+
ref: 913806aa2942db5a3b61d1432d2c9be200338f50
|
5
|
+
specs:
|
6
|
+
ripple (1.0.0.beta2)
|
7
|
+
activemodel (>= 3.0.0, < 3.3.0)
|
8
|
+
activesupport (>= 3.0.0, < 3.3.0)
|
9
|
+
riak-client (~> 1.1.0)
|
10
|
+
tzinfo
|
11
|
+
|
12
|
+
GIT
|
13
|
+
remote: git://github.com/mark-moseley/linecache
|
14
|
+
revision: 869c6a65155068415925067e480741bd0a71527e
|
15
|
+
specs:
|
16
|
+
linecache19 (0.5.12)
|
17
|
+
ruby_core_source (>= 0.1.4)
|
18
|
+
|
19
|
+
PATH
|
20
|
+
remote: .
|
21
|
+
specs:
|
22
|
+
ripple-encryption (0.0.3)
|
23
|
+
riak-client
|
24
|
+
ripple
|
25
|
+
|
26
|
+
GEM
|
27
|
+
remote: https://rubygems.org/
|
28
|
+
specs:
|
29
|
+
activemodel (3.2.12)
|
30
|
+
activesupport (= 3.2.12)
|
31
|
+
builder (~> 3.0.0)
|
32
|
+
activesupport (3.2.12)
|
33
|
+
i18n (~> 0.6)
|
34
|
+
multi_json (~> 1.0)
|
35
|
+
archive-tar-minitar (0.5.2)
|
36
|
+
beefcake (0.3.7)
|
37
|
+
builder (3.0.4)
|
38
|
+
columnize (0.3.6)
|
39
|
+
i18n (0.6.4)
|
40
|
+
innertube (1.0.2)
|
41
|
+
mini_shoulda (0.5.0)
|
42
|
+
minitest (> 2.1.0)
|
43
|
+
minitest (3.3.0)
|
44
|
+
multi_json (1.6.1)
|
45
|
+
rake (0.9.2.2)
|
46
|
+
riak-client (1.1.1)
|
47
|
+
beefcake (~> 0.3.7)
|
48
|
+
builder (>= 2.1.2)
|
49
|
+
i18n (>= 0.4.0)
|
50
|
+
innertube (~> 1.0.2)
|
51
|
+
multi_json (~> 1.0)
|
52
|
+
ruby-debug-base19 (0.11.25)
|
53
|
+
columnize (>= 0.3.1)
|
54
|
+
linecache19 (>= 0.5.11)
|
55
|
+
ruby_core_source (>= 0.1.4)
|
56
|
+
ruby-debug-base19x (0.11.30.pre10)
|
57
|
+
columnize (>= 0.3.1)
|
58
|
+
linecache19 (>= 0.5.11)
|
59
|
+
rake (>= 0.8.1)
|
60
|
+
ruby_core_source (>= 0.1.4)
|
61
|
+
ruby-debug19 (0.11.6)
|
62
|
+
columnize (>= 0.3.1)
|
63
|
+
linecache19 (>= 0.5.11)
|
64
|
+
ruby-debug-base19 (>= 0.11.19)
|
65
|
+
ruby_core_source (0.1.5)
|
66
|
+
archive-tar-minitar (>= 0.5.2)
|
67
|
+
tzinfo (0.3.35)
|
68
|
+
|
69
|
+
PLATFORMS
|
70
|
+
ruby
|
71
|
+
|
72
|
+
DEPENDENCIES
|
73
|
+
linecache19!
|
74
|
+
mini_shoulda
|
75
|
+
rake
|
76
|
+
riak-client (~> 1.1.1)
|
77
|
+
ripple!
|
78
|
+
ripple-encryption!
|
79
|
+
ruby-debug-base19x (~> 0.11.30.pre4)
|
80
|
+
ruby-debug19 (= 0.11.6)
|
data/LICENSE
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Copyright (c) 2012 Basho Technologies, Inc.
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
14
|
+
|
15
|
+
All of the files in this project are under the project-wide license
|
16
|
+
unless they are otherwise marked.
|
data/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# Ripple::Encryption
|
2
|
+
|
3
|
+
The ripple-encryption gem provides encryption and decryption for Ripple documents.
|
4
|
+
[riak-ruby](https://github.com/basho/riak-ruby-client) [ripple](https://github.com/basho/ripple)
|
5
|
+
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'ripple-encryption'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install ripple-encryption
|
20
|
+
|
21
|
+
## Overview
|
22
|
+
|
23
|
+
You call the activation, which initializes a global serializer within
|
24
|
+
Ripple. Any object that gets saved with content-type 'application/x-json-encrypted'
|
25
|
+
then goes through the Encryption::Serializer, which loads or unloads the
|
26
|
+
data from Riak through the JsonDocument and EncryptedJsonDocument,
|
27
|
+
respectively. Both of these have a dependency on Encryption::Encrypter,
|
28
|
+
which makes the actual calls to OpenSSL.
|
29
|
+
|
30
|
+
JsonDocument stores the encrypted data wrapped in JSON encapsulation so
|
31
|
+
that you can still introspect the Riak object and see which version of
|
32
|
+
this gem was used to encrypt it.
|
33
|
+
|
34
|
+
There is also a Rake file to convert between encrypted and decrypted
|
35
|
+
JSON objects.
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
Include the gem in your Gemfile. Activate it somewhere in your
|
40
|
+
application initialization by pointing it to your encryption config file
|
41
|
+
like so:
|
42
|
+
|
43
|
+
Ripple::Encryption.activate PATH_TO_CONFIG_FILE
|
44
|
+
|
45
|
+
Then include the Ripple::Encryption module in your document class:
|
46
|
+
|
47
|
+
class SomeDocument
|
48
|
+
include Ripple::Document
|
49
|
+
include Ripple::Encryption
|
50
|
+
property :message, String
|
51
|
+
end
|
52
|
+
|
53
|
+
These documents will now be stored encrypted.
|
54
|
+
|
55
|
+
## Running the Tests
|
56
|
+
|
57
|
+
Adjust the 'test/fixtures/ripple.yml' to point to a test riak database.
|
58
|
+
|
59
|
+
bundle exec rake
|
60
|
+
|
61
|
+
## Contributing
|
62
|
+
|
63
|
+
1. Fork it
|
64
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
65
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
66
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
67
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
require 'rake'
|
5
|
+
require 'rake/testtask'
|
6
|
+
|
7
|
+
Rake::TestTask.new(:test) do |t|
|
8
|
+
t.libs << "test"
|
9
|
+
t.test_files = FileList['test/**/test_*.rb']
|
10
|
+
t.verbose = true
|
11
|
+
end
|
12
|
+
|
13
|
+
namespace :test do
|
14
|
+
desc "Test everything"
|
15
|
+
task :all => [:test]
|
16
|
+
end
|
17
|
+
|
18
|
+
task :default => :test
|
19
|
+
|
20
|
+
# Connect to Riak and test the client connection.
|
21
|
+
|
22
|
+
namespace :migrate do
|
23
|
+
desc "Read in all unencrypted files, and save them to encrypted encoding."
|
24
|
+
task :encrypt do
|
25
|
+
Ripple::Encrytion::Migrate.new.convert(:encrypt)
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Read in all encrypted files, and save them unencrypted."
|
29
|
+
task :decrypt do
|
30
|
+
Ripple::Encrytion::Migrate.new.convert(:decrypt)
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# AES-256-CBC requires a 32-byte key and 16 byte iv
|
2
|
+
|
3
|
+
# remove iv if a random generated iv is desired
|
4
|
+
|
5
|
+
development:
|
6
|
+
cipher: AES-256-CBC
|
7
|
+
key: fantasticobscurekeygoesherenowty
|
8
|
+
iv: !binary |
|
9
|
+
ABYLnUHWE/fIwE2gKYC6hg==
|
10
|
+
|
11
|
+
test:
|
12
|
+
cipher: AES-256-CBC
|
13
|
+
key: fantasticobscurekeygoesherenowty
|
14
|
+
iv: !binary |
|
15
|
+
ABYLnUHWE/fIwE2gKYC6hg==
|
16
|
+
|
17
|
+
prod:
|
18
|
+
cipher: AES-256-CBC
|
19
|
+
key: fantasticobscurekeygoesherenowty
|
20
|
+
base64: true
|
data/lib/rake/migrate.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
module Ripple
|
2
|
+
module Encryption
|
3
|
+
class Migration
|
4
|
+
# create log files in the tmp dir
|
5
|
+
def initialize
|
6
|
+
relative_root = File.expand_path(File.join('..','..','..'),__FILE__)
|
7
|
+
require File.join(relative_root,'lib','ripple-encryption.rb')
|
8
|
+
tmp_dir = File.join(relative_root,'tmp')
|
9
|
+
output_dir = File.join(tmp_dir,Time.now.strftime("%m-%d-%Y-%I%M%p"))
|
10
|
+
Dir.mkdir(tmp_dir) unless File.exists?(tmp_dir)
|
11
|
+
Dir.mkdir(output_dir) unless File.exists?(output_dir)
|
12
|
+
@fetched_file = File.open(File.join(output_dir,'fetched.log'),'w')
|
13
|
+
@stored_file = File.open(File.join(output_dir,'stored.log'),'w')
|
14
|
+
@error_file = File.open(File.join(output_dir,'error.log'),'w')
|
15
|
+
end
|
16
|
+
|
17
|
+
# finde only the encryptable models
|
18
|
+
def models
|
19
|
+
Objects.constants.map{|c| "#{c}".constantize}.select{|c| c.include?(Ripple::Encryption)}
|
20
|
+
end
|
21
|
+
|
22
|
+
# cycle through all objects and save them
|
23
|
+
def convert(type)
|
24
|
+
# the difference between encryption or decryption is
|
25
|
+
# simply changing the content-type of the object so
|
26
|
+
# that ripple knows what way to serialize it
|
27
|
+
case type
|
28
|
+
when :encrypt
|
29
|
+
content_type = 'application/x-json-encrypted'
|
30
|
+
when :decrypt
|
31
|
+
content_type = 'application/json'
|
32
|
+
end
|
33
|
+
|
34
|
+
# we don't need no stinking warnings :-)
|
35
|
+
Riak.disable_list_keys_warnings = true
|
36
|
+
|
37
|
+
# cycle through each key in the database and
|
38
|
+
# read it, then save it
|
39
|
+
print 'Processing buckets: '
|
40
|
+
models.each do |model|
|
41
|
+
success = nil
|
42
|
+
count = 0
|
43
|
+
bucket_name = model.bucket_name
|
44
|
+
model.bucket.keys do |streaming_keys|
|
45
|
+
streaming_keys.each do |key|
|
46
|
+
begin
|
47
|
+
object = model.find key
|
48
|
+
log :fetched, "/buckets/#{bucket_name}/keys/#{key}"
|
49
|
+
object.robject.content_type = content_type
|
50
|
+
object.save!
|
51
|
+
log :stored, "/buckets/#{bucket_name}/keys/#{key}"
|
52
|
+
count += 1
|
53
|
+
rescue => e
|
54
|
+
log :error, "/buckets/#{bucket_name}/keys/#{key} #{e}".force_encoding('UTF-8')
|
55
|
+
success = 'E, '
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
print success || "#{count}, "
|
60
|
+
end
|
61
|
+
puts ' Done.'
|
62
|
+
|
63
|
+
# warn us. please. :-)
|
64
|
+
Riak.disable_list_keys_warnings = false
|
65
|
+
end
|
66
|
+
|
67
|
+
# log the object action
|
68
|
+
def log(type, object, error=nil)
|
69
|
+
case type
|
70
|
+
when :fetched
|
71
|
+
@fetched_file.puts object
|
72
|
+
when :stored
|
73
|
+
@stored_file.puts object
|
74
|
+
when :error
|
75
|
+
@error_file.write object
|
76
|
+
@error_file.write error
|
77
|
+
@error_file.write "\n"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'ripple'
|
3
|
+
|
4
|
+
module Ripple
|
5
|
+
module Encryption
|
6
|
+
|
7
|
+
# When mixed into a Ripple::Document class, this will encrypt the
|
8
|
+
# serialized form before it is stored in Riak. You must register
|
9
|
+
# a serializer that will perform the encryption.
|
10
|
+
# @see Serializer
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
@@is_activated = false
|
14
|
+
|
15
|
+
included do
|
16
|
+
@@encrypted_content_type = self.encrypted_content_type = 'application/x-json-encrypted'
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
# @return [String] the content type to be used to indicate the
|
21
|
+
# proper encryption scheme. Defaults to 'application/x-json-encrypted'
|
22
|
+
attr_accessor :encrypted_content_type
|
23
|
+
end
|
24
|
+
|
25
|
+
# Overrides the internal method to set the content-type to be
|
26
|
+
# encrypted.
|
27
|
+
def update_robject
|
28
|
+
super
|
29
|
+
if @@is_activated
|
30
|
+
robject.content_type = @@encrypted_content_type
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.activate(path)
|
35
|
+
encryptor = nil
|
36
|
+
unless Riak::Serializers['application/x-json-encrypted']
|
37
|
+
begin
|
38
|
+
config = YAML.load_file(path)[ENV['RACK_ENV']]
|
39
|
+
encryptor = Ripple::Encryption::Serializer.new(OpenSSL::Cipher.new(config['cipher']), 'application/x-json-encrypted', path)
|
40
|
+
rescue Exception => e
|
41
|
+
handle_invalid_encryption_config(e.message, e.backtrace)
|
42
|
+
end
|
43
|
+
encryptor.key = config['key'] if config['key']
|
44
|
+
encryptor.iv = config['iv'] if config['iv']
|
45
|
+
Riak::Serializers['application/x-json-encrypted'] = encryptor
|
46
|
+
@@is_activated = true
|
47
|
+
end
|
48
|
+
encryptor
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.activated
|
52
|
+
@@is_activated
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def handle_invalid_encryption_config(msg, trace)
|
59
|
+
puts <<eos
|
60
|
+
|
61
|
+
The file "config/encryption.yml" is missing or incorrect. You will
|
62
|
+
need to create this file and populate it with a valid cipher,
|
63
|
+
initialization vector and secret key.
|
64
|
+
|
65
|
+
An example is provided in "config/encryption.yml.example".
|
66
|
+
eos
|
67
|
+
|
68
|
+
puts "Error Message: " + msg
|
69
|
+
puts "Error Trace:"
|
70
|
+
trace.each do |line|
|
71
|
+
puts line
|
72
|
+
end
|
73
|
+
|
74
|
+
exit 1
|
75
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
module Ripple
|
4
|
+
module Encryption
|
5
|
+
# Generic error class for Config
|
6
|
+
class ConfigError < StandardError; end
|
7
|
+
|
8
|
+
# Handles the configuration information for the Encryptor.
|
9
|
+
#
|
10
|
+
# Example usage:
|
11
|
+
# Ripple::Encryption::Config.defaults
|
12
|
+
# Ripple::Encryption::Config.new(:iv => "SOMEIV").to_h
|
13
|
+
class Config
|
14
|
+
# Initializes the config from our yml file.
|
15
|
+
# @param [String] path to yml file
|
16
|
+
def initialize(path)
|
17
|
+
validate_path(path)
|
18
|
+
@config = YAML.load_file(path)[ENV['RACK_ENV']]
|
19
|
+
end
|
20
|
+
|
21
|
+
# Return the options in the hash expected by Encryptor.
|
22
|
+
def to_h
|
23
|
+
@config
|
24
|
+
end
|
25
|
+
|
26
|
+
# Return either the default initialization vector, or create a new one.
|
27
|
+
def activate
|
28
|
+
@config['iv'] ||= OpenSSL::Random.random_bytes(16)
|
29
|
+
end
|
30
|
+
|
31
|
+
def validate_path(path)
|
32
|
+
if !File.exists? path
|
33
|
+
raise Ripple::Encryption::ConfigError, <<MISSINGFILE
|
34
|
+
The file "config/encryption.yml" is missing or incorrect. You will
|
35
|
+
need to create this file and populate it with a valid cipher,
|
36
|
+
initialization vector and secret key. An example is provided in
|
37
|
+
"config/encryption.yml.example".
|
38
|
+
MISSINGFILE
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Ripple
|
2
|
+
module Encryption
|
3
|
+
# Generic error class for Encryptor
|
4
|
+
class EncryptedJsonDocumentError < StandardError; end
|
5
|
+
|
6
|
+
# Interprets a encapsulation in JSON for encrypted Ripple documents.
|
7
|
+
#
|
8
|
+
# Example usage:
|
9
|
+
# Ripple::Encryption::JsonDocument.new(@document).encrypt
|
10
|
+
class EncryptedJsonDocument
|
11
|
+
# Creates an object that is prepared to decrypt its contents.
|
12
|
+
# @param [String] data json string that was stored in Riak
|
13
|
+
def initialize(config, data)
|
14
|
+
@config = config.to_h.clone
|
15
|
+
@json = JSON.parse data
|
16
|
+
raise(EncryptedJsonDocumentError, "Missing 'iv' for decryption") unless @json['iv']
|
17
|
+
iv = Base64.decode64 @json['iv']
|
18
|
+
@config.merge!('iv' => iv)
|
19
|
+
|
20
|
+
@decryptor = Ripple::Encryption::Encryptor.new @config
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the original data from the stored encrypted format
|
24
|
+
def decrypt
|
25
|
+
JSON.load @decryptor.decrypt Base64.decode64 @json['data']
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Ripple
|
2
|
+
module Encryption
|
3
|
+
# Generic error class for Encryptor
|
4
|
+
class EncryptorConfigError < StandardError; end
|
5
|
+
|
6
|
+
# Implements a simple object that can either encrypt or decrypt arbitrary data.
|
7
|
+
#
|
8
|
+
# Example usage:
|
9
|
+
# encryptor = Ripple::Encryption::Encryptor.new Ripple::Encryption::Config.defaults
|
10
|
+
# encryptor.encrypt stuff
|
11
|
+
# encryptor.decrypt stuff
|
12
|
+
class Encryptor
|
13
|
+
# Creates an Encryptor that is prepared to encrypt/decrypt a blob.
|
14
|
+
# @param [Hash] config the key/cipher/iv needed to initialize OpenSSL
|
15
|
+
def initialize(config)
|
16
|
+
# ensure that we have the required configuration keys
|
17
|
+
%w(cipher key iv).each do |option|
|
18
|
+
raise(Ripple::Encryption::EncryptorConfigError, "Missing configuration option '#{option}'.") if config[option].nil?
|
19
|
+
end
|
20
|
+
@config = config
|
21
|
+
@cipher = OpenSSL::Cipher.new(@config['cipher'])
|
22
|
+
end
|
23
|
+
|
24
|
+
# Encrypt stuff.
|
25
|
+
# @param [Object] blob the data to encrypt
|
26
|
+
def encrypt(blob)
|
27
|
+
initialize_cipher_for :encrypt
|
28
|
+
"#{@cipher.update blob}#{@cipher.final}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Decrypt stuff.
|
32
|
+
# @param [Object] blob the encrypted data to decrypt
|
33
|
+
def decrypt(blob)
|
34
|
+
initialize_cipher_for :decrypt
|
35
|
+
"#{@cipher.update blob}#{@cipher.final}"
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
# This sets the mode so OpenSSL knows to encrypt or decrypt, etc.
|
40
|
+
# @param [Symbol] mode either :encrypt or :decrypt
|
41
|
+
def initialize_cipher_for(mode)
|
42
|
+
@cipher.send mode
|
43
|
+
@cipher.key = @config['key']
|
44
|
+
@cipher.iv = @config['iv']
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Ripple
|
2
|
+
module Encryption
|
3
|
+
# Implements an encapsulation in JSON for encrypted Ripple documents.
|
4
|
+
#
|
5
|
+
# Example usage:
|
6
|
+
# Ripple::Encryption::JsonDocument.new(@document).encrypt
|
7
|
+
class JsonDocument
|
8
|
+
# Creates an object that is prepared to encrypt its contents.
|
9
|
+
# @param [String] data object to store
|
10
|
+
def initialize(config, data)
|
11
|
+
config.activate
|
12
|
+
@config = config.to_h
|
13
|
+
@data = JSON.dump(data)
|
14
|
+
@encryptor = Ripple::Encryption::Encryptor.new @config
|
15
|
+
end
|
16
|
+
|
17
|
+
# Converts the data into the encrypted format
|
18
|
+
def encrypt
|
19
|
+
encrypted_data = @encryptor.encrypt @data
|
20
|
+
JSON.dump({:version => Ripple::Encryption::VERSION, :iv => Base64.encode64(@config['iv']), :data => Base64.encode64(encrypted_data)})
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module Ripple
|
2
|
+
module Encryption
|
3
|
+
# Implements the {Riak::Serializer} API for the purpose of
|
4
|
+
# encrypting/decrypting Ripple documents.
|
5
|
+
#
|
6
|
+
# Example usage:
|
7
|
+
# ::Riak::Serializers['application/x-json-encrypted'] = EncryptedSerializer.new(OpenSSL::Cipher.new("AES-256"))
|
8
|
+
# class MyDocument
|
9
|
+
# include Ripple::Document
|
10
|
+
# include Riak::Encryption
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# @see Encryption
|
14
|
+
class Serializer
|
15
|
+
# @return [String] The Content-Type of the internal format,
|
16
|
+
# generally "application/json"
|
17
|
+
attr_accessor :content_type
|
18
|
+
|
19
|
+
# @return [OpenSSL::Cipher, OpenSSL::PKey::*] the cipher used to encrypt the object
|
20
|
+
attr_accessor :cipher
|
21
|
+
|
22
|
+
# Cipher-specific settings
|
23
|
+
# @see OpenSSL::Cipher
|
24
|
+
attr_accessor :key, :iv, :key_length, :padding
|
25
|
+
|
26
|
+
# Serialization Options
|
27
|
+
# @return [true, false] Is the encrypted text also base64 encoded?
|
28
|
+
attr_accessor :base64
|
29
|
+
|
30
|
+
# Creates a serializer using the provided cipher and internal
|
31
|
+
# content type. Be sure to set the {#key}, {#iv}, {#key_length},
|
32
|
+
# {#padding} as appropriate for the cipher before attempting
|
33
|
+
# (de-)serialization.
|
34
|
+
# @param [OpenSSL::Cipher] cipher the desired
|
35
|
+
# encryption/decryption algorithm
|
36
|
+
# @param [String] content_type the Content-Type of the
|
37
|
+
# unencrypted contents
|
38
|
+
def initialize(cipher, content_type='application/json', path)
|
39
|
+
@cipher, @content_type = cipher, content_type
|
40
|
+
@config = Ripple::Encryption::Config.new(path)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Serializes and encrypts the Ruby object using the assigned
|
44
|
+
# cipher and Content-Type.
|
45
|
+
# @param [Object] object the Ruby object to serialize/encrypt
|
46
|
+
# @return [String] the serialized, encrypted form of the object
|
47
|
+
def dump(object)
|
48
|
+
JsonDocument.new(@config, object).encrypt
|
49
|
+
end
|
50
|
+
|
51
|
+
# Decrypts and deserializes the blob using the assigned cipher
|
52
|
+
# and Content-Type.
|
53
|
+
# @param [String] blob the original content from Riak
|
54
|
+
# @return [Object] the decrypted and deserialized object
|
55
|
+
def load(object)
|
56
|
+
# try the v1 way first
|
57
|
+
begin
|
58
|
+
internal = decrypt(object)
|
59
|
+
return ::Riak::Serializers.deserialize('application/json', internal)
|
60
|
+
# if that doesn't work, try the v2 way
|
61
|
+
rescue OpenSSL::Cipher::CipherError, MultiJson::DecodeError
|
62
|
+
return EncryptedJsonDocument.new(@config, object).decrypt
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# generates a new iv each call unless a static (less secure)
|
69
|
+
# iv is used.
|
70
|
+
def encrypt(object)
|
71
|
+
old_version = '0.0.1'
|
72
|
+
result = ''
|
73
|
+
if cipher.respond_to?(:iv=) and @iv == nil
|
74
|
+
iv = OpenSSL::Random.random_bytes(cipher.iv_len)
|
75
|
+
cipher.iv = iv
|
76
|
+
result << old_version << iv
|
77
|
+
end
|
78
|
+
|
79
|
+
if cipher.respond_to?(:public_encrypt)
|
80
|
+
result << cipher.public_encrypt(object)
|
81
|
+
else
|
82
|
+
cipher_setup :encrypt
|
83
|
+
result << cipher.update(object) << cipher.final
|
84
|
+
cipher.reset
|
85
|
+
end
|
86
|
+
return result
|
87
|
+
end
|
88
|
+
|
89
|
+
def decrypt(cipher_text)
|
90
|
+
old_version = '0.0.1'
|
91
|
+
|
92
|
+
if cipher.respond_to?(:iv=) and @iv == nil
|
93
|
+
version = cipher_text.slice(0, old_version.length)
|
94
|
+
cipher.iv = cipher_text.slice(old_version.length, cipher.iv_len)
|
95
|
+
cipher_text = cipher_text.slice(old_version.length + cipher.iv_len, cipher_text.length)
|
96
|
+
end
|
97
|
+
|
98
|
+
if cipher.respond_to?(:private_decrypt)
|
99
|
+
cipher.private_decrypt(cipher_text)
|
100
|
+
else
|
101
|
+
cipher_setup :decrypt
|
102
|
+
result = cipher.update(cipher_text) << cipher.final
|
103
|
+
cipher.reset
|
104
|
+
result
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def cipher_setup(mode)
|
109
|
+
cipher.send mode
|
110
|
+
cipher.key = key if key
|
111
|
+
cipher.iv = iv if iv
|
112
|
+
cipher.key_length = key_length if key_length
|
113
|
+
cipher.padding = padding if padding
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/ripple-encryption/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Randy Secrist", "Casey Rosenthal"]
|
6
|
+
gem.email = ["rsecrist@basho.com", "casey@basho.com"]
|
7
|
+
gem.description = %q{Easily encrypt data at rest with minimal changes to existing ripple models.}
|
8
|
+
gem.summary = %q{A simple encryption library for objects stored in riak.}
|
9
|
+
gem.homepage = "http://github.com/basho/ripple-encryption"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "ripple-encryption"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Ripple::Encryption::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency 'riak-client'
|
19
|
+
gem.add_dependency 'ripple'
|
20
|
+
|
21
|
+
# Test Dependencies
|
22
|
+
gem.add_development_dependency 'rake'
|
23
|
+
gem.add_development_dependency 'mini_shoulda'
|
24
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
{"message":"this is unencrypted data", "_type":"TestDocument"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":"0.0.3","iv":"ABYLnUHWE/fIwE2gKYC6hg==\n","data":"KYtsnoDZ85AMR/eZAVBtEXe88gB/UNagMpl4oV7FLxUgtqw5BvPCbLChrmdg\nsRQas2VZ8/FkIx5CiMeJYoi9Ag==\n"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"message":"this is unencrypted data", "_type":"TestDocument"}
|
@@ -0,0 +1 @@
|
|
1
|
+
0��d�>^��
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":"0.0.2","iv":"ABYLnUHWE/fIwE2gKYC6hg==\n","data":"MK0LuGThPhde4t0NfKSbhAvPjTuFmykhWVGNxPG++40=\n"}
|
data/test/helper.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'minitest/autorun'
|
5
|
+
require 'mini_shoulda'
|
6
|
+
|
7
|
+
require 'ripple-encryption'
|
8
|
+
|
9
|
+
ENV['RACK_ENV'] = 'test'
|
10
|
+
ENV['RIPPLE'] = File.expand_path(File.join('..','fixtures','ripple.yml'),__FILE__)
|
11
|
+
ENV['ENCRYPTION'] = File.expand_path(File.join('..','fixtures','encryption.yml'),__FILE__)
|
12
|
+
|
13
|
+
# connect to a local Riak test node
|
14
|
+
begin
|
15
|
+
Ripple.load_configuration ENV['RIPPLE'], ['test']
|
16
|
+
riak_config = Hash[YAML.load_file(ENV['RIPPLE'])['test'].map{|k,v| [k.to_sym, v]}]
|
17
|
+
client = Riak::Client.new(:nodes => [riak_config])
|
18
|
+
bucket = client.bucket("#{riak_config[:namespace].to_s}test")
|
19
|
+
object = bucket.get_or_new("test")
|
20
|
+
rescue RuntimeError
|
21
|
+
raise RuntimeError, "Could not connect to the Riak test node."
|
22
|
+
end
|
23
|
+
# define test Ripple Documents
|
24
|
+
Ripple::Encryption.activate ENV['ENCRYPTION']
|
25
|
+
class TestDocument
|
26
|
+
include Ripple::Document
|
27
|
+
include Ripple::Encryption
|
28
|
+
property :message, String
|
29
|
+
|
30
|
+
def self.bucket_name
|
31
|
+
"#{Ripple.config[:namespace]}#{super}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
TestDocument.bucket.get_index('$bucket', '_').each {|k| TestDocument.bucket.delete(k)}
|
36
|
+
|
37
|
+
# load Riak fixtures
|
38
|
+
FileList[File.expand_path(File.join('..','fixtures','*'),__FILE__)].each do |f|
|
39
|
+
if Dir.exists? f
|
40
|
+
fixture_type = File.basename(f)
|
41
|
+
begin
|
42
|
+
klass = fixture_type.classify.constantize
|
43
|
+
rescue NameError
|
44
|
+
raise NameError, "Is a Ripple Document of type '#{fixture_type.classify}' defined for that fixture file?"
|
45
|
+
end
|
46
|
+
FileList[File.join(f,'*.riak')].each do |r|
|
47
|
+
key = File.basename(r,'.riak')
|
48
|
+
content_type = (key == 'v0_doc' ? 'application/json' : 'application/x-json-encrypted')
|
49
|
+
`curl -s -H 'content-type: #{content_type}' -XPUT http://#{Ripple.config[:host]}:#{Ripple.config[:http_port]}/buckets/#{Ripple.config[:namespace]}#{fixture_type.pluralize}/keys/#{key} --data-binary @#{r}`
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
data/test/test_config.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestConfig < MiniTest::Spec
|
4
|
+
context "Ripple::Encryption::Config" do
|
5
|
+
should "raise heck if the config file isn't found" do
|
6
|
+
assert_raises Ripple::Encryption::ConfigError do
|
7
|
+
config = Ripple::Encryption::Config.new('nowhere')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestEncryptor < MiniTest::Spec
|
4
|
+
context "Ripple::Encryption::Encryptor" do
|
5
|
+
setup do
|
6
|
+
config = Ripple::Encryption::Config.new ENV['ENCRYPTION']
|
7
|
+
@encryptor = Ripple::Encryption::Encryptor.new config.to_h
|
8
|
+
# example text
|
9
|
+
@text = "This is some nifty text."
|
10
|
+
# this is the example text encrypted
|
11
|
+
@blob = "Vfn\xC3\xF1a\xB9\x89\x16\xCA\xD4w\xC4\xAF\x16\xA0c\xF7\xD0\x88\xA3;d\xC8Y\x91\xA8\x05W+)\xC8"
|
12
|
+
end
|
13
|
+
|
14
|
+
should "convert text to an encrypted blob" do
|
15
|
+
assert_equal @blob, @encryptor.encrypt(@text), "Encryption failed."
|
16
|
+
end
|
17
|
+
|
18
|
+
should "convert encrypted blob to text" do
|
19
|
+
assert_equal @text, @encryptor.decrypt(@blob), "Decryption failed."
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "Ripple::Encryption::Encryptor with missing parameter" do
|
24
|
+
should "raise an error if key is missing" do
|
25
|
+
assert_raises Ripple::Encryption::EncryptorConfigError do
|
26
|
+
Ripple::Encryption::Encryptor.new(:iv => 'iv', :cipher => 'AES-256-CBC')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
should "raise an error if iv is missing" do
|
31
|
+
assert_raises Ripple::Encryption::EncryptorConfigError do
|
32
|
+
Ripple::Encryption::Encryptor.new(:key => 'key', :cipher => 'AES-256-CBC')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
should "raise an error if cipher is missing" do
|
37
|
+
assert_raises Ripple::Encryption::EncryptorConfigError do
|
38
|
+
Ripple::Encryption::Encryptor.new(:key => 'key', :iv => 'iv')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestJsonDocument < MiniTest::Spec
|
4
|
+
context "Ripple::Encryption::JsonDocument" do
|
5
|
+
setup do
|
6
|
+
# get some encryption going
|
7
|
+
@config = Ripple::Encryption::Config.new ENV['ENCRYPTION']
|
8
|
+
encryptor = Ripple::Encryption::Encryptor.new @config.to_h
|
9
|
+
|
10
|
+
# this is the data package that we want
|
11
|
+
@document = {'some' => 'data goes here'}
|
12
|
+
|
13
|
+
# this is how we want that data package to actually be stored
|
14
|
+
encrypted_value = encryptor.encrypt JSON.dump @document
|
15
|
+
@encrypted_document = JSON.dump({:version => Ripple::Encryption::VERSION, :iv => Base64.encode64(@config.to_h['iv']), :data => Base64.encode64(encrypted_value)})
|
16
|
+
end
|
17
|
+
|
18
|
+
should "convert a document to our desired JSON format" do
|
19
|
+
assert_equal @encrypted_document, Ripple::Encryption::JsonDocument.new(@config, @document).encrypt, 'Did not get the JSON format expected.'
|
20
|
+
end
|
21
|
+
|
22
|
+
should "interpret our JSON format into a document" do
|
23
|
+
assert_equal @document, Ripple::Encryption::EncryptedJsonDocument.new(@config, @encrypted_document).decrypt, 'Did not get the JSON format expected.'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "Ripple::Encryption::JsonDocument with no initialization vector" do
|
28
|
+
setup do
|
29
|
+
# this is the data package that we want
|
30
|
+
@document = {'some' => 'data goes here'}
|
31
|
+
|
32
|
+
# rig a JsonDocument without an iv
|
33
|
+
@config = Ripple::Encryption::Config.new File.expand_path(File.join('..','fixtures','encryption_no_iv.yml'),__FILE__)
|
34
|
+
@json_document = Ripple::Encryption::JsonDocument.new(@config, @document)
|
35
|
+
end
|
36
|
+
|
37
|
+
should "convert a document to our desired JSON format and back again" do
|
38
|
+
encrypted_document = @json_document.encrypt
|
39
|
+
assert_equal @document, Ripple::Encryption::EncryptedJsonDocument.new(@config, encrypted_document).decrypt, 'Did not get the JSON format expected.'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/test/test_ripple.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestRipple < MiniTest::Spec
|
4
|
+
context "TestDocument" do
|
5
|
+
should "write the ripple document" do
|
6
|
+
document = TestDocument.new
|
7
|
+
document.message = 'here is some new data'
|
8
|
+
document.save
|
9
|
+
same_document = TestDocument.find(document.key)
|
10
|
+
assert_equal document.message, same_document.message
|
11
|
+
|
12
|
+
# read the document back out
|
13
|
+
read_doc = TestDocument.find(document.key)
|
14
|
+
assert_equal 'here is some new data', read_doc.message
|
15
|
+
end
|
16
|
+
|
17
|
+
should "write the ripple document raw confirmation" do
|
18
|
+
document = TestDocument.new
|
19
|
+
document.message = 'here is some new data'
|
20
|
+
document.save
|
21
|
+
expected_data = 'VpQTfX23xKdMK4Kprp/xgwDh4UFFSYC8q4OeOhK2zPn0l5huFO+vsoBrq8pT\nd5Z3EdgPx3k8VpL0QNH1FM6m4g==\n'
|
22
|
+
expected_doc_data = "{\"version\":\"#{Ripple::Encryption::VERSION}\",\"iv\":\"ABYLnUHWE/fIwE2gKYC6hg==\\n\",\"data\":\"#{expected_data}\"}"
|
23
|
+
raw_data = `curl -s http://#{Ripple.config[:host]}:#{Ripple.config[:http_port]}/buckets/#{TestDocument.bucket_name}/keys/#{document.key}`
|
24
|
+
assert_equal expected_doc_data, raw_data
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestMigrationV1ToV2 < MiniTest::Spec
|
4
|
+
context "unencrypted GenericModel" do
|
5
|
+
setup do
|
6
|
+
end
|
7
|
+
|
8
|
+
should "read unencrypted document type" do
|
9
|
+
assert v0 = TestDocument.find('v0_doc')
|
10
|
+
assert_equal 'this is unencrypted data', v0.message
|
11
|
+
end
|
12
|
+
|
13
|
+
should "write unencrypted document type when content-type is plain" do
|
14
|
+
document = TestDocument.new
|
15
|
+
document.message = 'here is some new data'
|
16
|
+
Ripple::Encryption.class_variable_set(:@@is_activated, false)
|
17
|
+
document.robject.content_type = 'application/json'
|
18
|
+
document.save
|
19
|
+
expected_v2_data = '{"message":"here is some new data","_type":"TestDocument"}'
|
20
|
+
raw_data = `curl -s -XGET http://#{Ripple.config[:host]}:#{Ripple.config[:http_port]}/buckets/#{TestDocument.bucket_name}/keys/#{document.key}`
|
21
|
+
assert_equal expected_v2_data, raw_data
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ripple-encryption
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Randy Secrist
|
9
|
+
- Casey Rosenthal
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2013-03-03 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: riak-client
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '0'
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: ripple
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
type: :runtime
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: mini_shoulda
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
type: :development
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
description: Easily encrypt data at rest with minimal changes to existing ripple models.
|
80
|
+
email:
|
81
|
+
- rsecrist@basho.com
|
82
|
+
- casey@basho.com
|
83
|
+
executables: []
|
84
|
+
extensions: []
|
85
|
+
extra_rdoc_files: []
|
86
|
+
files:
|
87
|
+
- Gemfile
|
88
|
+
- Gemfile.lock
|
89
|
+
- LICENSE
|
90
|
+
- README.md
|
91
|
+
- Rakefile
|
92
|
+
- config/encryption.yml.example
|
93
|
+
- config/ripple.yml.example
|
94
|
+
- lib/rake/migrate.rb
|
95
|
+
- lib/ripple-encryption.rb
|
96
|
+
- lib/ripple-encryption/activation.rb
|
97
|
+
- lib/ripple-encryption/config.rb
|
98
|
+
- lib/ripple-encryption/encrypted_json_document.rb
|
99
|
+
- lib/ripple-encryption/encryptor.rb
|
100
|
+
- lib/ripple-encryption/json_document.rb
|
101
|
+
- lib/ripple-encryption/serializer.rb
|
102
|
+
- lib/ripple-encryption/version.rb
|
103
|
+
- ripple-encryption.gemspec
|
104
|
+
- test/fixtures/encryption.yml
|
105
|
+
- test/fixtures/encryption_no_iv.yml
|
106
|
+
- test/fixtures/ripple.yml
|
107
|
+
- test/fixtures/test_document/some_data.unencrypted.riak
|
108
|
+
- test/fixtures/test_document/some_other_data.encrypted.riak
|
109
|
+
- test/fixtures/test_document/v0_doc.riak
|
110
|
+
- test/fixtures/test_document/v1_doc.riak
|
111
|
+
- test/fixtures/test_document/v2_doc.riak
|
112
|
+
- test/helper.rb
|
113
|
+
- test/test_config.rb
|
114
|
+
- test/test_encryptor.rb
|
115
|
+
- test/test_json_document.rb
|
116
|
+
- test/test_ripple.rb
|
117
|
+
- test/test_unencrypted_document.rb
|
118
|
+
homepage: http://github.com/basho/ripple-encryption
|
119
|
+
licenses: []
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
none: false
|
126
|
+
requirements:
|
127
|
+
- - ! '>='
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
none: false
|
132
|
+
requirements:
|
133
|
+
- - ! '>='
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
requirements: []
|
137
|
+
rubyforge_project:
|
138
|
+
rubygems_version: 1.8.23
|
139
|
+
signing_key:
|
140
|
+
specification_version: 3
|
141
|
+
summary: A simple encryption library for objects stored in riak.
|
142
|
+
test_files:
|
143
|
+
- test/fixtures/encryption.yml
|
144
|
+
- test/fixtures/encryption_no_iv.yml
|
145
|
+
- test/fixtures/ripple.yml
|
146
|
+
- test/fixtures/test_document/some_data.unencrypted.riak
|
147
|
+
- test/fixtures/test_document/some_other_data.encrypted.riak
|
148
|
+
- test/fixtures/test_document/v0_doc.riak
|
149
|
+
- test/fixtures/test_document/v1_doc.riak
|
150
|
+
- test/fixtures/test_document/v2_doc.riak
|
151
|
+
- test/helper.rb
|
152
|
+
- test/test_config.rb
|
153
|
+
- test/test_encryptor.rb
|
154
|
+
- test/test_json_document.rb
|
155
|
+
- test/test_ripple.rb
|
156
|
+
- test/test_unencrypted_document.rb
|