ripple-encryption 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|