cloudcrypt 0.0.1 → 0.0.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,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in cloudcrypt.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,14 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cloudcrypt (0.0.1)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+
10
+ PLATFORMS
11
+ ruby
12
+
13
+ DEPENDENCIES
14
+ cloudcrypt!
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ require 'bundler'
2
+ require 'date'
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+
7
+ #############################################################################
8
+ #
9
+ # Helper functions
10
+ #
11
+ #############################################################################
12
+
13
+ def name
14
+ @name ||= Dir['*.gemspec'].first.split('.').first
15
+ end
16
+
17
+ def version
18
+ line = File.read("lib/#{name}/version.rb")[/^\s*VERSION\s*=\s*.*/]
19
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
20
+ end
21
+
22
+ def date
23
+ Date.today.to_s
24
+ end
25
+
26
+ def gemspec_file
27
+ "#{name}.gemspec"
28
+ end
29
+
30
+ def gem_file
31
+ "#{name}-#{version}.gem"
32
+ end
33
+
34
+ def replace_header(head, header_name)
35
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
36
+ end
37
+
38
+
39
+ #############################################################################
40
+ #
41
+ # Standard tasks
42
+ #
43
+ #############################################################################
44
+
45
+
46
+ desc "Open an irb session preloaded with this library"
47
+ task :console do
48
+ sh "irb -rubygems -r ./lib/#{name}.rb"
49
+ end
50
+
51
+
data/bin/cloudcrypt.rb ADDED
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
3
+ require 'cloudcrypt'
4
+
5
+
6
+ RAVE_BUCKET='ec2admin-software-installation-rave-5.6.3'
7
+ def is_mac?
8
+ # universal-darwin9.0 shows up for RUBY_PLATFORM on os X leopard with the bundled ruby.
9
+ # Installing ruby in different manners may give a different result, so beware.
10
+ # Examine the ruby platform yourself. If you see other values please comment
11
+ # in the snippet on dzone and I will add them.
12
+ RUBY_PLATFORM.downcase.include?("darwin")
13
+ end
14
+
15
+ def is_windows?
16
+ RUBY_PLATFORM.downcase.include?("mingw32")
17
+ end
18
+
19
+ if is_mac?
20
+ # MAC
21
+ PUBLIC_KEY='/Users/restebanez/id_nodemanager.pub'
22
+ PRIVATE_KEY='/Users/restebanez/id_nodemanager'
23
+ TMP='/tmp'
24
+ elsif is_windows?
25
+
26
+ # Windows
27
+ PUBLIC_KEY='C:\Users\Administrator\.chef\id_nodemanager'
28
+ PRIVATE_KEY='C:\Users\Administrator\.chef\id_nodemanager'
29
+ TMP=ENV['TMP']
30
+ require 'win32/registry.rb'
31
+ require 'Win32API'
32
+ if ENV['RAVE_RW_AWS_ACCESS_KEY_ID'].nil? || ENV['RAVE_RW_AWS_SECRET_ACCESS_KEY'].nil?
33
+ puts "Let's set up some envioroment variables"
34
+ puts "RAVE_RW_AWS_ACCESS_KEY_ID: "
35
+ Win32::Registry::HKEY_CURRENT_USER.open('Environment', Win32::Registry::KEY_WRITE) do |reg|
36
+ reg['RAVE_RW_AWS_ACCESS_KEY_ID'] = gets
37
+ end
38
+ puts "RAVE_RW_AWS_SECRET_ACCESS_KEY: "
39
+ Win32::Registry::HKEY_CURRENT_USER.open('Environment', Win32::Registry::KEY_WRITE) do |reg|
40
+ reg['RAVE_RW_AWS_SECRET_ACCESS_KEY'] = gets
41
+ end
42
+ # make environmental variables available immediately
43
+ # http://stackoverflow.com/questions/190168/persisting-an-environment-variable-through-ruby
44
+ SendMessageTimeout = Win32API.new('user32', 'SendMessageTimeout', 'LLLPLLP', 'L')
45
+ HWND_BROADCAST = 0xffff
46
+ WM_SETTINGCHANGE = 0x001A
47
+ SMTO_ABORTIFHUNG = 2
48
+ result = 0
49
+ SendMessageTimeout.call(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 'Environment', SMTO_ABORTIFHUNG, 5000, result)
50
+ abort('Open a new powershell session and run it again')
51
+ end
52
+ else
53
+ abort('OS not detectect!')
54
+ end
55
+
56
+ abort('Please set the variable RAVE_RW_AWS_ACCESS_KEY_ID and RAVE_RW_AWS_SECRET_ACCESS_KEY') if ENV['RAVE_RW_AWS_ACCESS_KEY_ID'].nil? || ENV['RAVE_RW_AWS_SECRET_ACCESS_KEY'].nil?
57
+
58
+ AWS_ACCESS_KEY_ID=ENV['RAVE_RW_AWS_ACCESS_KEY_ID'].gsub(/\r?\n?/, "")
59
+ AWS_SECRET_ACCESS_KEY=ENV['RAVE_RW_AWS_SECRET_ACCESS_KEY'].gsub(/\r?\n?/, "")
60
+
61
+ ENCRYPTED_FILE_EXTENSION='.encrypted'
62
+ ENCRYPTED_VI_EXTENSION='.vi'
63
+ ENCRYPTED_KEY_EXTENSION='.key'
64
+
65
+
66
+
67
+ params=ARGV
68
+ cloudcrypt = Cloudcrypt::Parser.new
69
+
70
+ if cloudcrypt.parse#(params)
71
+ exit 0
72
+ else
73
+ exit 1
74
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "cloudcrypt/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "cloudcrypt"
7
+ s.version = Cloudcrypt::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Rodrigo Estebanez"]
10
+ s.email = ["restebanez@mdsol.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{encrypt and decrypt files using public and private encryption}
13
+ s.description = %q{You can't encrypt a file bigger than the private key. You first have to generate a random key and a random vector initialization to encrypt the file using a symmetrical algorithom. Later you use the private key to encrypt the random key and the random vector}
14
+
15
+ s.rubyforge_project = "cloudcrypt"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ s.add_dependency('fog')
22
+ s.add_dependency('rubyzip')
23
+ s.add_dependency('trollop')
24
+ end
@@ -0,0 +1,17 @@
1
+ module Cloudcrypt
2
+
3
+ class AsymmetricalCrypt
4
+ def self.encrypt(public_key,data_to_encrypt)
5
+ raise if ( public_key.empty? || data_to_encrypt.empty? )
6
+ public_key_rsa = OpenSSL::PKey::RSA.new(public_key)
7
+ encrypted_data = public_key_rsa.public_encrypt(data_to_encrypt)
8
+ end
9
+
10
+ def self.decrypt(private_key,data_to_dencrypt)
11
+ raise if ( private_key.empty? || data_to_dencrypt.empty?)
12
+ private_key_rsa = OpenSSL::PKey::RSA.new(private_key)
13
+ decrypted_data = private_key_rsa.private_decrypt(data_to_dencrypt)
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,118 @@
1
+ module Cloudcrypt
2
+
3
+ class Main
4
+
5
+
6
+ ENCRYPTED_FILE_EXTENSION='.encrypted'
7
+ ENCRYPTED_VI_EXTENSION='.vi'
8
+ ENCRYPTED_KEY_EXTENSION='.key'
9
+
10
+ if RUBY_PLATFORM.downcase.include?("mingw32")
11
+ TMP=ENV['TMP']
12
+ FILE_SEPARATOR="\\"
13
+ else
14
+ TMP='/tmp'
15
+ FILE_SEPARATOR='/'
16
+ end
17
+ attr_reader :dst_encrypted_file, :dst_encrypted_key_file, :dst_encrypted_iv_file, :dst_unencrypted_file, :dst_zip_file
18
+
19
+ def initialize(public_key_file,private_key_file=nil)
20
+ @public_key_file = public_key_file
21
+ @private_key_file = private_key_file
22
+ end
23
+
24
+ def encrypt(file_path,dst=TMP)
25
+ raise_unless_exists(@public_key_file)
26
+ public_key = File.read(@public_key_file)
27
+
28
+ file_basename=File.basename(file_path) #gets the filename without the extension
29
+ file_uri = dst + FILE_SEPARATOR + file_basename
30
+ @dst_encrypted_file = file_uri + ENCRYPTED_FILE_EXTENSION
31
+ @dst_encrypted_key_file = raise_if_exists(file_uri + ENCRYPTED_KEY_EXTENSION)
32
+ @dst_encrypted_iv_file = raise_if_exists(file_uri + ENCRYPTED_VI_EXTENSION)
33
+
34
+ s=SymmetricalCrypt.new(file_path,@dst_encrypted_file)
35
+ s.encrypt
36
+
37
+ File.open(@dst_encrypted_key_file,'wb') {|f|
38
+ f << AsymmetricalCrypt.encrypt(public_key,s.random_key)
39
+ }
40
+
41
+ File.open(@dst_encrypted_iv_file,'wb') {|f|
42
+ f << AsymmetricalCrypt.encrypt(public_key,s.random_iv)
43
+ }
44
+ @dst_zip_file = file_path + '.zip'
45
+ zip(@dst_zip_file, [@dst_encrypted_file,@dst_encrypted_key_file,@dst_encrypted_iv_file])
46
+ File.delete(@dst_encrypted_file,@dst_encrypted_key_file,@dst_encrypted_iv_file)
47
+
48
+ end
49
+
50
+ def decrypt(file_path_zip,dst=TMP)
51
+ unzip(file_path_zip,dst)
52
+
53
+ raise_unless_exists(@private_key_file)
54
+ private_key = File.read(@private_key_file)
55
+
56
+ # where files where extracted from the zip file
57
+ dir_basename = dst
58
+ # gets the filename without the extension .zip
59
+ file_basename = File.basename(file_path_zip,'.zip')
60
+
61
+
62
+ # Where to look for key and iv files
63
+ file_uri = dir_basename + FILE_SEPARATOR + file_basename
64
+ source_encrypted_file = raise_unless_exists(file_uri + ENCRYPTED_FILE_EXTENSION)
65
+ source_encrypted_key_file = raise_unless_exists(file_uri + ENCRYPTED_KEY_EXTENSION)
66
+ source_encrypted_iv_file = raise_unless_exists(file_uri + ENCRYPTED_VI_EXTENSION)
67
+ @dst_unencrypted_file = dst + '/' + file_basename
68
+
69
+ iv = AsymmetricalCrypt.decrypt(File.read(@private_key_file),File.open(source_encrypted_iv_file,'rb').read)
70
+ key = AsymmetricalCrypt.decrypt(File.read(@private_key_file),File.open(source_encrypted_key_file,'rb').read)
71
+
72
+ s = SymmetricalCrypt.new(source_encrypted_file,@dst_unencrypted_file)
73
+ s.decrypt(key,iv)
74
+ #windows thinks it's opened
75
+ #File.delete(source_encrypted_file,source_encrypted_key_file,source_encrypted_iv_file)
76
+ end
77
+
78
+
79
+
80
+ def zip(new_zip_file,files=[])
81
+ Zip::ZipFile.open(new_zip_file,Zip::ZipFile::CREATE) do |zip|
82
+ files.each do |file|
83
+ file_basename = File.basename(file)
84
+ zip.file.open(file_basename,'wb') {|f|f << File.open(file,'rb').read }
85
+ end
86
+ end
87
+ end
88
+
89
+ def unzip(file_zip,dst=TMP)
90
+ Zip::ZipFile.open(file_zip) do |zip|
91
+ zip.each do |f|
92
+ f_path=File.join(dst, f.name)
93
+ #Chef::Log.info(f_path)
94
+ FileUtils.mkdir_p(File.dirname(f_path)) unless File.directory?(f_path)
95
+ zip.extract(f, f_path) unless File.exist?(f_path)
96
+ end
97
+ end
98
+ end
99
+
100
+ def md5(file)
101
+ return false unless File.exists?(file)
102
+ return Digest::MD5.hexdigest(File.read(file))
103
+ end
104
+
105
+ private
106
+
107
+
108
+ def raise_if_exists(file)
109
+ raise "#{file} doesn't exist" if File.exists?(file)
110
+ file
111
+ end
112
+
113
+ def raise_unless_exists(file)
114
+ raise "#{file} doesn't exist" unless File.exists?(file)
115
+ file
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,57 @@
1
+ module Cloudcrypt
2
+ require 'trollop'
3
+
4
+ class Parser
5
+
6
+ def initialize
7
+ abort('use --help') if ARGV.empty?
8
+
9
+ @opts = Trollop::options do
10
+
11
+ version "1.0 Rodrigo Estebanez"
12
+ banner <<-EOS
13
+ This script administrates the files of a private S3 Bucket. You can upload,download and delete files. Files will be encrypted using a public key before uploading them, it will be decrypted them after downloading them.
14
+
15
+ Options:
16
+ EOS
17
+
18
+ opt :upload, "upload a file to S3 in an encrypted fashion", :type => String
19
+ opt :download, "download a S3 file and decrypt it", :type => String
20
+ opt :erase, "delete a S3 file", :type => String
21
+ opt :list, "list files of the rave bucket"
22
+ # opt :destination, "where to write the file", :type => String
23
+ opt :public_key, "public key location for encryption", :type => String, :default => PUBLIC_KEY
24
+ opt :private_key, "private key location for decryption", :type => String, :default => PRIVATE_KEY
25
+
26
+ end
27
+ end
28
+
29
+
30
+ def parse
31
+
32
+ Trollop::die :upload, "must exist" unless File.exists?(@opts[:upload]) if @opts[:upload]
33
+
34
+
35
+ m=Cloudcrypt::Main.new(@opts[:public_key],@opts[:private_key])
36
+ s3=Cloudcrypt::S3Transfer.new(AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY)
37
+
38
+
39
+ if @opts[:list]
40
+ s3.list.collect {|file| printf("%s\t%iB\t%s\n", file.key,file.content_length,file.etag) }
41
+ elsif @opts[:erase]
42
+ s3.delete(@opts[:erase])
43
+ elsif @opts[:upload]
44
+ m.encrypt(@opts[:upload])
45
+ s3.upload(m.dst_zip_file)
46
+ else
47
+ pwd = Dir.pwd
48
+ dst = File.join(pwd,@opts[:download])
49
+ abort("it already exists") if File.exists?(dst)
50
+ s3.download(@opts[:download],dst)
51
+ m.decrypt(dst,pwd)
52
+ puts m.dst_unencrypted_file
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,56 @@
1
+ module Cloudcrypt
2
+
3
+ class S3Transfer
4
+ def initialize(aws_access_key_id,aws_secret_access_key)
5
+ begin
6
+ #Gem.clear_paths
7
+ require 'fog'
8
+ rescue LoadError
9
+ #Chef::Log.warn("Missing gem 'fog'")
10
+ end
11
+ @s3=Fog::AWS::Storage.new(
12
+ :aws_access_key_id=> aws_access_key_id,
13
+ :aws_secret_access_key => aws_secret_access_key
14
+ )
15
+
16
+ end
17
+
18
+ def upload(file_uri,bucket=RAVE_BUCKET)
19
+ file_basename = File.basename(file_uri)
20
+ abort("S3://#{bucket}/#{file_basename} already exist") if file_exists?(file_basename,bucket)
21
+ f=@s3.directories.get(bucket).files.new(:key => file_basename, :body=>File.open(file_uri,'rb').read)
22
+ f.save
23
+ f.etag
24
+ File.delete(file_uri)
25
+ end
26
+
27
+ def md5(file_basename,bucket=RAVE_BUCKET)
28
+ return false unless file_exists?(file_basename,bucket)
29
+ return @s3.directories.get(bucket).files.get(file_basename).etag
30
+ end
31
+
32
+ def download(file_basename,destination,bucket=RAVE_BUCKET)
33
+ abort("S3://#{bucket}/#{file_basename} doesn't exist") unless file_exists?(file_basename,bucket)
34
+ File.open(destination,'wb') { |f| f << @s3.directories.get(bucket).files.get(file_basename).body }
35
+ end
36
+
37
+ def list(bucket=RAVE_BUCKET)
38
+ @s3.directories.get(bucket).files
39
+ end
40
+
41
+ def delete(file_basename,bucket=RAVE_BUCKET)
42
+ abort("S3://#{bucket}/#{file_basename} doesn't exist") unless file_exists?(file_basename,bucket)
43
+ @s3.directories.get(bucket).files.get(file_basename).destroy
44
+ end
45
+
46
+ private
47
+
48
+ def file_exists?(file_name,bucket=RAVE_BUCKET)
49
+ @s3.directories.get(bucket).files.each do |f|
50
+ return true if file_name == f.key
51
+ end
52
+ return false
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,42 @@
1
+ module Cloudcrypt
2
+ class SymmetricalCrypt
3
+ SYMMETRICAL_ALGORITHM='aes-256-cbc'
4
+
5
+ attr_reader :random_key, :random_iv
6
+ def initialize(source_file,destination_file)
7
+ @source_file = source_file
8
+ @destination_file = destination_file
9
+ raise "#{@source_file} file doesn't exist" unless File.exists?(@source_file)
10
+ raise "#{@destination_file} Already Exists" if File.exists?(@destination_file)
11
+
12
+ @cipher = OpenSSL::Cipher::Cipher.new(SYMMETRICAL_ALGORITHM)
13
+ end
14
+
15
+ def encrypt
16
+ @cipher.encrypt # We are encypting
17
+ # The OpenSSL library will generate random keys and IVs
18
+ @random_key = @cipher.random_key
19
+ @random_iv = @cipher.random_iv
20
+ @cipher.key = @random_key
21
+ @cipher.iv = @random_iv
22
+ write_to_disk
23
+ end
24
+
25
+ def decrypt(key,iv)
26
+ raise if ( key.empty? || iv.empty?)
27
+ @cipher.decrypt # We are encypting
28
+ @cipher.key = key
29
+ @cipher.iv = iv
30
+ write_to_disk
31
+ end
32
+
33
+ private
34
+ def write_to_disk
35
+ # To improve performance the file is not store into memory
36
+ File.open(@destination_file,'wb') { |f|
37
+ f << @cipher.update(File.open(@source_file,'rb').read)
38
+ f << @cipher.final
39
+ }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,3 @@
1
+ module Cloudcrypt
2
+ VERSION = "0.0.2"
3
+ end
data/lib/cloudcrypt.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'openssl'
3
+ require 'fog'
4
+ require 'zip/zipfilesystem'
5
+
6
+ __DIR__ = File.dirname(__FILE__)
7
+
8
+ $LOAD_PATH.unshift __DIR__ unless
9
+ $LOAD_PATH.include?(__DIR__) ||
10
+ $LOAD_PATH.include?(File.expand_path(__DIR__))
11
+
12
+
13
+ require 'cloudcrypt/parser'
14
+ require 'cloudcrypt/main'
15
+ require 'cloudcrypt/asymmetrical_crypt'
16
+ require 'cloudcrypt/symmetrical_crypt'
17
+ require 'cloudcrypt/s3_transfer'
18
+
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudcrypt
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Rodrigo Estebanez
@@ -17,19 +17,72 @@ cert_chain: []
17
17
 
18
18
  date: 2010-12-29 00:00:00 -05:00
19
19
  default_executable:
20
- dependencies: []
21
-
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: fog
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: rubyzip
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: trollop
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :runtime
62
+ version_requirements: *id003
22
63
  description: You can't encrypt a file bigger than the private key. You first have to generate a random key and a random vector initialization to encrypt the file using a symmetrical algorithom. Later you use the private key to encrypt the random key and the random vector
23
64
  email:
24
65
  - restebanez@mdsol.com
25
- executables: []
26
-
66
+ executables:
67
+ - cloudcrypt.rb
27
68
  extensions: []
28
69
 
29
70
  extra_rdoc_files: []
30
71
 
31
- files: []
32
-
72
+ files:
73
+ - .gitignore
74
+ - Gemfile
75
+ - Gemfile.lock
76
+ - Rakefile
77
+ - bin/cloudcrypt.rb
78
+ - cloudcrypt.gemspec
79
+ - lib/cloudcrypt.rb
80
+ - lib/cloudcrypt/asymmetrical_crypt.rb
81
+ - lib/cloudcrypt/main.rb
82
+ - lib/cloudcrypt/parser.rb
83
+ - lib/cloudcrypt/s3_transfer.rb
84
+ - lib/cloudcrypt/symmetrical_crypt.rb
85
+ - lib/cloudcrypt/version.rb
33
86
  has_rdoc: true
34
87
  homepage: ""
35
88
  licenses: []