bitzesty-safe 0.1.2

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/.gitignore ADDED
@@ -0,0 +1 @@
1
+ pkg/*
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Matthew Ford and Bit Zesty Ltd.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,63 @@
1
+ Safe
2
+ ====
3
+
4
+ A wrapper around [strongbox](http://github.com/spikex/strongbox) to store and encrypt data.
5
+
6
+ Setup
7
+ ----
8
+
9
+ Install strongbox and safe
10
+
11
+ config.gem "spikex-strongbox", :lib => "strongbox", :source => "http://gems.github.com"
12
+ config.gem "bitzesty-safe", :lib => "safe", :source => "http://gems.github.com"
13
+
14
+ rake gems:install
15
+ rake gems:unpack
16
+
17
+ Generate a migration with `script/generate migration CreateSafeCabinet` and add the following
18
+
19
+ class CreateSafeCabinet < ActiveRecord::Migration
20
+ def self.up
21
+ create_table :safe_cabinets, :force => true do |t|
22
+ t.binary :data
23
+ t.binary :data_key
24
+ t.binary :data_iv
25
+ t.integer :encryptable_id
26
+ t.string :encryptable_type
27
+ t.timestamps
28
+ end
29
+ add_index :safe_cabinets, [:encryptable_id, :encryptable_type]
30
+ end
31
+
32
+ def self.down
33
+ drop_table :safe_cabinet
34
+ end
35
+ end
36
+
37
+ In your model that you want to store the encrypted data add:
38
+
39
+ class MyModel
40
+ include Safe::Keys
41
+ attr_accessor :password #length must be > 3
42
+ has_many :safe_cabinets, :as => :encryptable #or has_one
43
+ after_create :make_keys!
44
+ end
45
+
46
+ _N.B. A password must be used when creating an instance of MyModel._
47
+
48
+ To create and use safe_cabinets:
49
+
50
+ m = MyModel.create(:password => "1234")
51
+ c = m.safe_cabinets.new
52
+ c.data = "super secret data"
53
+ c.save
54
+
55
+ c.data
56
+ => #<Strongbox::Lock:0x1f372d...
57
+
58
+ c.data.read_data("1234")
59
+ => "super secret data"
60
+
61
+
62
+
63
+ Copyright (c) 2009 Matthew Ford and Bit Zesty Ltd, See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'rcov/rcovtask'
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |s|
9
+ s.name = "safe"
10
+ s.summary = "strongbox wrapper"
11
+ s.email = "info@bitzesty.com"
12
+ s.homepage = "http://github.com/bitzesty/safe"
13
+ s.description = "Storing encrypted data in a Rails app using Strongbox"
14
+ s.authors = ["Matthew Ford"]
15
+ end
16
+ rescue LoadError
17
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
18
+ end
19
+
20
+ Rake::TestTask.new do |t|
21
+ t.libs << 'lib'
22
+ t.pattern = 'test/**/*_test.rb'
23
+ t.verbose = false
24
+ end
25
+
26
+ Rake::RDocTask.new do |rdoc|
27
+ rdoc.rdoc_dir = 'rdoc'
28
+ rdoc.title = 'safe'
29
+ rdoc.options << '--line-numbers' << '--inline-source'
30
+ rdoc.rdoc_files.include('README*')
31
+ rdoc.rdoc_files.include('lib/**/*.rb')
32
+ end
33
+
34
+ Rcov::RcovTask.new do |t|
35
+ t.libs << 'test'
36
+ t.test_files = FileList['test/**/*_test.rb']
37
+ t.verbose = true
38
+ end
39
+
40
+ task :default => :rcov
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.2
@@ -0,0 +1,15 @@
1
+ class SafeCabinetsController < ApplicationController
2
+ unloadable
3
+
4
+ def show
5
+ @cabinet = SafeCabinet.find(params[:id])
6
+ @data = nil
7
+ end
8
+
9
+
10
+ def unlock
11
+ @cabinet = SafeCabinet.find(params[:id])
12
+ @data = @cabinet.read_data(params[:passphrase])
13
+ render :show
14
+ end
15
+ end
@@ -0,0 +1,51 @@
1
+ require "openssl"
2
+ require 'base64'
3
+ require 'strongbox/lock'
4
+
5
+ class SafeCabinet < ActiveRecord::Base
6
+ # Class Configuration :::::::::::::::::::::::::::::::::::::::::::::
7
+ class_inheritable_reader :lock_options
8
+ write_inheritable_attribute(:lock_options, {}) if lock_options.nil?
9
+
10
+ SAFE_KEYS_DIR = File.join(RAILS_ROOT,'config', 'safe_keys')
11
+
12
+ # Assocations :::::::::::::::::::::::::::::::::::::::::::::::::::::
13
+ belongs_to :encryptable, :polymorphic => true
14
+
15
+ # Validations :::::::::::::::::::::::::::::::::::::::::::::::::::::
16
+ validates_presence_of :encryptable_id
17
+ validates_presence_of :encryptable_type
18
+
19
+ # Callbacks :::::::::::::::::::::::::::::::::::::::::::::::::::::::
20
+ before_save :lockdown
21
+
22
+ # Instance Methods ::::::::::::::::::::::::::::::::::::::::::::::::
23
+ def options
24
+ @options ||= {
25
+ :base64 => false,
26
+ :symmetric => :always,
27
+ :padding => OpenSSL::PKey::RSA::PKCS1_PADDING,
28
+ :symmetric_cipher => 'aes-256-cbc'
29
+ }
30
+ end
31
+
32
+ def data
33
+ lock_for("data")
34
+ end
35
+
36
+ def lockdown
37
+ self.data = lock_for("data").encrypt self[:data]
38
+ end
39
+
40
+ def read_data(pass)
41
+ self.data.decrypt pass
42
+ rescue OpenSSL::PKey::RSAError
43
+ nil
44
+ end
45
+
46
+ def lock_for name
47
+ lock_options[name] = options.merge(:key_pair => File.join(SAFE_KEYS_DIR, self.encryptable_id.to_s, "keypair.pem"))
48
+ @_locks ||= {}
49
+ @_locks[name] ||= Lock.new(name, self, self.class.lock_options[name])
50
+ end
51
+ end
@@ -0,0 +1,8 @@
1
+ <% unless @data %>
2
+ <% form_tag unlock_safe_cabinet_path(@cabinet) do |f| %>
3
+ <%= password_field_tag :passphrase %>
4
+ <%= submit_tag "unlock" %>
5
+ <% end %>
6
+ <% else %>
7
+ <%= @data %>
8
+ <% end %>
@@ -0,0 +1,5 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.resources :safe_cabinets,
3
+ :member => [:unlock],
4
+ :only => [:show, :unlock]
5
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'safe'
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,14 @@
1
+ if defined?(ActionController::Routing::RouteSet)
2
+ class ActionController::Routing::RouteSet
3
+ def load_routes_with_safe!
4
+ lib_path = File.dirname(__FILE__)
5
+ safe_routes = File.join(lib_path, *%w[.. .. .. config safe_routes.rb])
6
+ unless configuration_files.include?(safe_routes)
7
+ add_configuration_file(safe_routes)
8
+ end
9
+ load_routes_without_safe!
10
+ end
11
+
12
+ alias_method_chain :load_routes!, :safe
13
+ end
14
+ end
data/lib/safe/keys.rb ADDED
@@ -0,0 +1,57 @@
1
+ require 'open4'
2
+ require 'fileutils'
3
+ require 'strongbox'
4
+
5
+ module Safe
6
+ class KeygenError < StandardError;end
7
+ module Keys
8
+ SAFE_KEYS_DIR = File.join(RAILS_ROOT,'config', 'safe_keys')
9
+
10
+ def gen_private_key(path, pass)
11
+ cmd = "openssl genrsa -des3 -passout pass:#{pass} -out #{path}private.pem 2048"
12
+ Open4::popen4("sh") do |pid, stdin, stdout, stderr|
13
+ stdin.puts cmd
14
+ stdin.close
15
+ end
16
+ end
17
+
18
+ def gen_public_key(path, pass)
19
+ cmd = "openssl rsa -in #{path}private.pem -out #{path}public.pem -outform PEM -pubout -passin pass:#{pass}"
20
+ Open4::popen4("sh") do |pid, stdin, stdout, stderr|
21
+ stdin.puts cmd
22
+ stdin.close
23
+ end
24
+ end
25
+
26
+ def gen_keypair(path, pass)
27
+ gen_private_key(path, pass)
28
+ gen_public_key(path, pass)
29
+ if File.exists?("#{path}keypair.pem")
30
+ FileUtils.rm("#{path}keypair.pem")
31
+ end
32
+ cmd = "cat #{path}private.pem #{path}public.pem >> #{path}keypair.pem"
33
+ Open4::popen4("sh") do |pid, stdin, stdout, stderr|
34
+ stdin.puts cmd
35
+ stdin.close
36
+ end
37
+ end
38
+
39
+ # destructible, only call once
40
+ def make_keys!
41
+ root_dir = SAFE_KEYS_DIR
42
+ object_id = self.id
43
+ pass = self.password
44
+ raise Safe::KeygenError if object_id.nil? || pass.nil?
45
+ dir_id = "/#{object_id}/"
46
+ dir = root_dir + dir_id
47
+ if File.exists?(root_dir) && File.directory?(root_dir)
48
+ Dir.mkdir(dir) unless File.exists?(dir)
49
+ gen_keypair(dir, pass)
50
+ else
51
+ Dir.mkdir(root_dir)
52
+ Dir.mkdir(dir)
53
+ gen_keypair(dir, pass)
54
+ end
55
+ end
56
+ end
57
+ end
data/lib/safe.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'safe/extensions/routes'
2
+
3
+ require 'safe/keys'
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'safe'
data/safe.gemspec ADDED
@@ -0,0 +1,60 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{safe}
8
+ s.version = "0.1.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Matthew Ford"]
12
+ s.date = %q{2009-09-25}
13
+ s.description = %q{Storing encrypted data in a Rails app using Strongbox}
14
+ s.email = %q{info@bitzesty.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.markdown"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "LICENSE",
22
+ "README.markdown",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "app/controllers/safe_cabinets_controller.rb",
26
+ "app/models/safe_cabinet.rb",
27
+ "app/views/safe_cabinets/show.html.erb",
28
+ "config/safe_routes.rb",
29
+ "init.rb",
30
+ "install.rb",
31
+ "lib/safe.rb",
32
+ "lib/safe/extensions/routes.rb",
33
+ "lib/safe/keys.rb",
34
+ "rails/init.rb",
35
+ "safe.gemspec",
36
+ "tasks/safe_tasks.rake",
37
+ "test/safe_test.rb",
38
+ "test/test_helper.rb",
39
+ "uninstall.rb"
40
+ ]
41
+ s.homepage = %q{http://github.com/bitzesty/safe}
42
+ s.rdoc_options = ["--charset=UTF-8"]
43
+ s.require_paths = ["lib"]
44
+ s.rubygems_version = %q{1.3.5}
45
+ s.summary = %q{strongbox wrapper}
46
+ s.test_files = [
47
+ "test/safe_test.rb",
48
+ "test/test_helper.rb"
49
+ ]
50
+
51
+ if s.respond_to? :specification_version then
52
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
53
+ s.specification_version = 3
54
+
55
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
56
+ else
57
+ end
58
+ else
59
+ end
60
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :safe do
3
+ # # Task goes here
4
+ # end
data/test/safe_test.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+
3
+ class SafeTest < ActiveSupport::TestCase
4
+ # Replace this with your real tests.
5
+ test "the truth" do
6
+ assert true
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'active_support/test_case'
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bitzesty-safe
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Matthew Ford
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-25 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Storing encrypted data in a Rails app using Strongbox
17
+ email: info@bitzesty.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.markdown
25
+ files:
26
+ - .gitignore
27
+ - LICENSE
28
+ - README.markdown
29
+ - Rakefile
30
+ - VERSION
31
+ - app/controllers/safe_cabinets_controller.rb
32
+ - app/models/safe_cabinet.rb
33
+ - app/views/safe_cabinets/show.html.erb
34
+ - config/safe_routes.rb
35
+ - init.rb
36
+ - install.rb
37
+ - lib/safe.rb
38
+ - lib/safe/extensions/routes.rb
39
+ - lib/safe/keys.rb
40
+ - rails/init.rb
41
+ - safe.gemspec
42
+ - tasks/safe_tasks.rake
43
+ - test/safe_test.rb
44
+ - test/test_helper.rb
45
+ - uninstall.rb
46
+ has_rdoc: false
47
+ homepage: http://github.com/bitzesty/safe
48
+ licenses:
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --charset=UTF-8
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.5
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: strongbox wrapper
73
+ test_files:
74
+ - test/safe_test.rb
75
+ - test/test_helper.rb