Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch '0.0.3' of https://github.com/basho/ripple-encryption
- Loading branch information
Showing
17 changed files
with
231 additions
and
121 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,117 @@ | |||
module Ripple | |||
module Encryption | |||
# Implements the {Riak::Serializer} API for the purpose of | |||
# encrypting/decrypting Ripple documents. | |||
# | |||
# Example usage: | |||
# ::Riak::Serializers['application/x-json-encrypted'] = EncryptedSerializer.new(OpenSSL::Cipher.new("AES-256")) | |||
# class MyDocument | |||
# include Ripple::Document | |||
# include Riak::Encryption | |||
# end | |||
# | |||
# @see Encryption | |||
class EncryptedSerializer | |||
# @return [String] The Content-Type of the internal format, | |||
# generally "application/json" | |||
attr_accessor :content_type | |||
|
|||
# @return [OpenSSL::Cipher, OpenSSL::PKey::*] the cipher used to encrypt the object | |||
attr_accessor :cipher | |||
|
|||
# Cipher-specific settings | |||
# @see OpenSSL::Cipher | |||
attr_accessor :key, :iv, :key_length, :padding | |||
|
|||
# Serialization Options | |||
# @return [true, false] Is the encrypted text also base64 encoded? | |||
attr_accessor :base64 | |||
|
|||
# Creates a serializer using the provided cipher and internal | |||
# content type. Be sure to set the {#key}, {#iv}, {#key_length}, | |||
# {#padding} as appropriate for the cipher before attempting | |||
# (de-)serialization. | |||
# @param [OpenSSL::Cipher] cipher the desired | |||
# encryption/decryption algorithm | |||
# @param [String] content_type the Content-Type of the | |||
# unencrypted contents | |||
def initialize(cipher, content_type='application/json', path) | |||
@cipher, @content_type = cipher, content_type | |||
@config = Ripple::Encryption::Config.new(path) | |||
end | |||
|
|||
# Serializes and encrypts the Ruby object using the assigned | |||
# cipher and Content-Type. | |||
# @param [Object] object the Ruby object to serialize/encrypt | |||
# @return [String] the serialized, encrypted form of the object | |||
def dump(object) | |||
JsonDocument.new(@config, object).encrypt | |||
end | |||
|
|||
# Decrypts and deserializes the blob using the assigned cipher | |||
# and Content-Type. | |||
# @param [String] blob the original content from Riak | |||
# @return [Object] the decrypted and deserialized object | |||
def load(object) | |||
# try the v1 way first | |||
begin | |||
internal = decrypt(object) | |||
return ::Riak::Serializers.deserialize('application/json', internal) | |||
# if that doesn't work, try the v2 way | |||
rescue OpenSSL::Cipher::CipherError, MultiJson::DecodeError | |||
return EncryptedJsonDocument.new(@config, object).decrypt | |||
end | |||
end | |||
|
|||
private | |||
|
|||
# generates a new iv each call unless a static (less secure) | |||
# iv is used. | |||
def encrypt(object) | |||
old_version = '0.0.1' | |||
result = '' | |||
if cipher.respond_to?(:iv=) and @iv == nil | |||
iv = OpenSSL::Random.random_bytes(cipher.iv_len) | |||
cipher.iv = iv | |||
result << old_version << iv | |||
end | |||
|
|||
if cipher.respond_to?(:public_encrypt) | |||
result << cipher.public_encrypt(object) | |||
else | |||
cipher_setup :encrypt | |||
result << cipher.update(object) << cipher.final | |||
cipher.reset | |||
end | |||
return result | |||
end | |||
|
|||
def decrypt(cipher_text) | |||
old_version = '0.0.1' | |||
|
|||
if cipher.respond_to?(:iv=) and @iv == nil | |||
version = cipher_text.slice(0, old_version.length) | |||
cipher.iv = cipher_text.slice(old_version.length, cipher.iv_len) | |||
cipher_text = cipher_text.slice(old_version.length + cipher.iv_len, cipher_text.length) | |||
end | |||
|
|||
if cipher.respond_to?(:private_decrypt) | |||
cipher.private_decrypt(cipher_text) | |||
else | |||
cipher_setup :decrypt | |||
result = cipher.update(cipher_text) << cipher.final | |||
cipher.reset | |||
result | |||
end | |||
end | |||
|
|||
def cipher_setup(mode) | |||
cipher.send mode | |||
cipher.key = key if key | |||
cipher.iv = iv if iv | |||
cipher.key_length = key_length if key_length | |||
cipher.padding = padding if padding | |||
end | |||
end | |||
end | |||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -1,20 +1,78 @@ | |||
require 'openssl' | |||
require 'ripple' | |||
|
|||
module Ripple | module Ripple | ||
# When mixed into a Ripple::Document class, this will encrypt the |
|
||
# serialized form before it is stored in Riak. You must register | |||
# a serializer that will perform the encryption. | |||
# @see Serializer | |||
module Encryption | module Encryption | ||
# Overrides the internal method to set the content-type to be |
|
||
# encrypted. | # When mixed into a Ripple::Document class, this will encrypt the | ||
def robject | # serialized form before it is stored in Riak. You must register | ||
@robject ||= Riak::RObject.new(self.class.bucket, key).tap do |obj| | # a serializer that will perform the encryption. | ||
obj.content_type = 'application/x-json-encrypted' | # @see EncryptedSerializer | ||
module Encryption | |||
extend ActiveSupport::Concern | |||
|
|||
@@is_activated = false | |||
|
|||
included do | |||
@@encrypted_content_type = self.encrypted_content_type = 'application/x-json-encrypted' | |||
end | end | ||
|
|||
module ClassMethods | |||
# @return [String] the content type to be used to indicate the | |||
# proper encryption scheme. Defaults to 'application/x-json-encrypted' | |||
attr_accessor :encrypted_content_type | |||
end | |||
|
|||
# Overrides the internal method to set the content-type to be | |||
# encrypted. | |||
def update_robject | |||
super | |||
if @@is_activated | |||
robject.content_type = @@encrypted_content_type | |||
end | |||
end | |||
|
|||
def self.activate(path) | |||
encryptor = nil | |||
unless Riak::Serializers['application/x-json-encrypted'] | |||
begin | |||
config = YAML.load_file(path)[ENV['RACK_ENV']] | |||
encryptor = Ripple::Encryption::EncryptedSerializer.new(OpenSSL::Cipher.new(config['cipher']), 'application/x-json-encrypted', path) | |||
rescue Exception => e | |||
handle_invalid_encryption_config(e.message, e.backtrace) | |||
end | |||
encryptor.key = config['key'] if config['key'] | |||
encryptor.iv = config['iv'] if config['iv'] | |||
Riak::Serializers['application/x-json-encrypted'] = encryptor | |||
@@is_activated = true | |||
end | |||
encryptor | |||
end | |||
|
|||
def self.activated | |||
@@is_activated | |||
end | |||
|
|||
end | end | ||
def update_robject | |||
robject.key = key if robject.key != key | |||
robject.content_type ||= 'application/x-json-encrypted' | |||
robject.data = attributes_for_persistence | |||
end | |||
end | end | ||
end | end | ||
|
|||
def handle_invalid_encryption_config(msg, trace) | |||
puts <<eos | |||
The file "config/encryption.yml" is missing or incorrect. You will | |||
need to create this file and populate it with a valid cipher, | |||
initialization vector and secret key. | |||
An example is provided in "config/encryption.yml.example". | |||
eos | |||
|
|||
puts "Error Message: " + msg | |||
puts "Error Trace:" | |||
trace.each do |line| | |||
puts line | |||
end | |||
|
|||
exit 1 | |||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -1 +1 @@ | |||
{"version":"0.1.0","iv":"ABYLnUHWE/fIwE2gKYC6hg==\n","data":"KYtsnoDZ85AMR/eZAVBtEXe88gB/UNagMpl4oV7FLxUgtqw5BvPCbLChrmdg\nsRQas2VZ8/FkIx5CiMeJYoi9Ag==\n"} | {"version":"0.0.3","iv":"ABYLnUHWE/fIwE2gKYC6hg==\n","data":"KYtsnoDZ85AMR/eZAVBtEXe88gB/UNagMpl4oV7FLxUgtqw5BvPCbLChrmdg\nsRQas2VZ8/FkIx5CiMeJYoi9Ag==\n"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1 @@ | |||
{"message":"this is unencrypted data", "_type":"TestDocument"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1 @@ | |||
0��d�>^��|���`f���p�#ʼl_�*� | |||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1 @@ | |||
{"version":"0.0.2","iv":"ABYLnUHWE/fIwE2gKYC6hg==\n","data":"MK0LuGThPhde4t0NfKSbhAvPjTuFmykhWVGNxPG++40=\n"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.