ohlol-nachos 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.
Files changed (4) hide show
  1. data/LICENSE +25 -0
  2. data/README.markdown +26 -0
  3. data/lib/nachos.rb +194 -0
  4. metadata +57 -0
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ Copyright (c) 2009, Scott Smith <scott@ohlol.net>
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name of the Author (Scott Smith) nor the names of contributors
13
+ to this software may be used to endorse or promote products derived from
14
+ this software without specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,26 @@
1
+ NACHOS
2
+ ------
3
+
4
+ Nachos keeps people from taking your stuff. It's mine, nachos!
5
+
6
+ You need to generate a public and private key to bootstrap it.
7
+
8
+ EXAMPLE USAGE
9
+ -------------
10
+
11
+ ...to store:
12
+
13
+ require 'ohlol-nachos'
14
+
15
+ e = Nachos::Encryptor('password')
16
+ e.clear_data = 'foo bar baz'
17
+ e.secret_data = e.encrypt(e.clear_data)
18
+ e.save_data
19
+
20
+ ...to load:
21
+
22
+ require 'ohlol-nachos'
23
+
24
+ e = Nachos::Encryptor('password)'
25
+ e.load_data
26
+ puts e.clear_data
@@ -0,0 +1,194 @@
1
+ module Nachos
2
+ require 'openssl'
3
+ require 'yaml'
4
+ require 'base64'
5
+
6
+ def config
7
+ @@config
8
+ end
9
+
10
+ def config=(config = {})
11
+ if config.empty?
12
+ config_dir = File.join(File.dirname(__FILE__), '../conf')
13
+
14
+ @@config = {
15
+ :public_key => config_dir + '/public.pem',
16
+ :private_key => config_dir + '/private.pem',
17
+ :secret_key => config_dir + '/secret-key.yml',
18
+ :data_store => config_dir + '/secret-data.enc'
19
+ }
20
+ else
21
+ @@config = {
22
+ :public_key => config[:public_key],
23
+ :private_key => config[:private_key],
24
+ :secret_key => config[:secret_key],
25
+ :data_store => config[:data_store]
26
+ }
27
+ end
28
+ end
29
+
30
+ class EncryptorException < IOError; end
31
+ class KeyStoreException < IOError; end
32
+ end
33
+
34
+ class Nachos::Encryptor
35
+ include Nachos
36
+
37
+ # secret_key, secret_iv, data are encrypted and readable by the caller
38
+ # clear_data is writeable/readable by the caller
39
+ attr_reader :secret_key, :secret_iv
40
+ attr_accessor :clear_data, :encrypted_data
41
+ attr_reader :keystore
42
+
43
+ # pass an optional encrypted secret key & iv
44
+ # we'll decrypt it and store it for private use
45
+ def initialize(password, config = {})
46
+ self.config = config
47
+ @secret_key = @secret_iv = @clear_data = @encrypted_data = ''
48
+
49
+ begin
50
+ @public_key = OpenSSL::PKey::RSA.new(File.open(self.config[:public_key]))
51
+ @private_key =
52
+ OpenSSL::PKey::RSA.new(File.open(self.config[:private_key]), password)
53
+ @cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
54
+
55
+ @keystore = Nachos::KeyStore.new
56
+
57
+ keypair
58
+ rescue Errno::ENOENT
59
+ raise Nachos::EncryptorException, "Public or private key missing! " +
60
+ "(maybe both!)"
61
+ rescue Nachos::KeyStoreException => e
62
+ raise
63
+ rescue => e
64
+ raise Nachos::EncryptorException, "There was a problem loading or " +
65
+ "decrypting the keypair and/or keystore! (#{e})"
66
+ end
67
+ end
68
+
69
+ def keypair
70
+ if @keystore.secret_key.empty? || @keystore.secret_iv.empty?
71
+ begin
72
+ @clear_secret_key = @cipher.random_key
73
+ @clear_secret_iv = @cipher.random_iv
74
+
75
+ @secret_key = @keystore.secret_key encrypt(@clear_secret_key)
76
+ @secret_iv = @keystore.secret_iv = encrypt(@clear_secret_iv)
77
+ @keystore.save_secrets
78
+ rescue => e
79
+ raise Nachos::EncryptorException, "There was a problem generating" +
80
+ "random secret key and/or IV!"
81
+ end
82
+ else
83
+ p "foo"
84
+ @secret_key = @keystore.secret_key
85
+ @secret_iv = @keystore.secret_iv
86
+ end
87
+
88
+ @clear_secret_key = decrypt(@secret_key)
89
+ @clear_secret_iv = decrypt(@secret_iv)
90
+ end
91
+
92
+ def encrypt(str)
93
+ if str.empty?
94
+ raise Nachos::EncryptorException, "What do you want to encrypt?"
95
+ else
96
+ begin
97
+ @cipher.encrypt
98
+ str = @public_key.public_encrypt(str)
99
+ rescue => e
100
+ raise Nachos::EncryptorException, "Couldn't encrypt the data! (#{e})"
101
+ end
102
+ end
103
+ end
104
+
105
+ def decrypt(str)
106
+ if str.empty?
107
+ raise Nachos::EncryptorException, "What do you want to decrypt?"
108
+ else
109
+ begin
110
+ @cipher.decrypt
111
+ str = @private_key.private_decrypt(str)
112
+ rescue => e
113
+ raise Nachos::decryptorException, "Couldn't decrypt the data! (#{e})"
114
+ end
115
+ end
116
+ end
117
+
118
+ def load_data
119
+ begin
120
+ @encrypted_data = ''
121
+
122
+ File.open(self.config[:data_store], 'r') do |f|
123
+ @encrypted_data = @encrypted_data + f.gets
124
+ end
125
+
126
+ @encrypted_data.chomp!
127
+ @clear_data = decrypt(@encrypted_data)
128
+ rescue Errno::ENOENT
129
+ rescue => e
130
+ raise Nachos::EncryptorException, "There was a problem reading the " +
131
+ "data store! (#{e})"
132
+ end
133
+ end
134
+
135
+ def save_data
136
+ if @encrypted_data.empty?
137
+ encrypt
138
+ end
139
+
140
+ begin
141
+ File.open(self.config[:data_store], 'w') do |f|
142
+ f.puts @encrypted_data
143
+ end
144
+ rescue
145
+ raise Nachos::EncryptorException, "There was a problem saving the data " +
146
+ "store!"
147
+ end
148
+ end
149
+ end
150
+
151
+ class Nachos::KeyStore
152
+ include Nachos
153
+
154
+ attr_accessor :secret_key, :secret_iv
155
+
156
+ def initialize
157
+ @secret_key = @secret_iv = ''
158
+ get_secrets
159
+ end
160
+
161
+ def get_secrets
162
+ begin
163
+ y_data = YAML::load(File.open(self.config[:secret_key]))
164
+
165
+ if y_data
166
+ @secret_key = Base64.decode64(y_data[:key])
167
+ @secret_iv = Base64.decode64(y_data[:iv])
168
+ end
169
+ # file was empty for some reason, we'll have to generate a new set.
170
+ # hope we didn't need to decrypt anything!
171
+ rescue Errno::ENOENT
172
+ # fail silently; we'll just generate a new set
173
+ rescue => e
174
+ raise Nachos::KeyStoreException, "There was a problem loading the " +
175
+ "keystore! (#{e})"
176
+ end
177
+ end
178
+
179
+ def save_secrets
180
+ stuff = {
181
+ :key => Base64.encode64(@secret_key),
182
+ :iv => Base64.encode64(@secret_iv)
183
+ }
184
+
185
+ begin
186
+ File.open(self.config[:secret_key], 'w') do |f|
187
+ f.puts stuff.to_yaml
188
+ end
189
+ rescue => e
190
+ raise Nachos::KeyStoreException, "There was a problem saving the " +
191
+ "keystore! (#{e})"
192
+ end
193
+ end
194
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ohlol-nachos
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.2"
5
+ platform: ruby
6
+ authors:
7
+ - Scott Smith
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-13 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Nachos is a Ruby library for managing an encrypted data store.
17
+ email: scott@ohlol.net
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - LICENSE
26
+ - README.markdown
27
+ - lib
28
+ - lib/nachos.rb
29
+ has_rdoc: false
30
+ homepage: http://github.com/ohlol/nachos"
31
+ post_install_message:
32
+ rdoc_options:
33
+ - --inline-source
34
+ - --charset=UTF-8
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ version:
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ requirements: []
50
+
51
+ rubyforge_project: nachos
52
+ rubygems_version: 1.2.0
53
+ signing_key:
54
+ specification_version: 2
55
+ summary: Nachos is a Ruby library for managing an encrypted data store.
56
+ test_files: []
57
+