secret 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a56b7cd7533a64c852d89901ba1460a2b487d498
4
- data.tar.gz: 2993017272c967c3b9e7249f6be3eff1a9bc3e22
3
+ metadata.gz: 41f92b03a262766c7d234c19c6a960de5a842c19
4
+ data.tar.gz: 6e32e9c816c5fc79e8a37409438e8874a66d79d9
5
5
  SHA512:
6
- metadata.gz: f263a042a3fb1373b73a7548143b36fc1eb6147cbdbd5ce58e7f6aa34c22bfa40cb014d6934186b220ee08c305976b3b87df8ffb1721091c120243b363297fdd
7
- data.tar.gz: a80eb4b104b6fde26085b253e9d6065aa145d9a6cf65d8a54041e98310f4dd69e7b29abd4a88b3f1b2fd9f0faab5ee5f7bc126d2d23b2a0cc9b850a3778e3b76
6
+ metadata.gz: 675d910898db33b3b877c5b18d0a6a510e41cef439c4ad9c2133e1965c112e02fad125c04537d784da9a944cc002596f85838c52a83ff50cdaa8a696a994d13c
7
+ data.tar.gz: 29a50491731fc543171b33a47296f3c49275469f8fce3ab3abc4a5847bbf8754e43b1e7eef996e6ea17fd97c1f3f6dbfdd0fba780298ffbc7987a30a1763944c
data/README.md CHANGED
@@ -30,7 +30,7 @@ secret.some_key.stash "ThisIsSomeKey"
30
30
  puts secret.some_key.contents
31
31
 
32
32
  # Manually seek through the file
33
- secret.some_key.stream do |f|
33
+ secret.some_key.stream 'r' do |f|
34
34
  f.seek 1, IO::SEEK_CUR
35
35
  end
36
36
 
@@ -44,6 +44,44 @@ secret.stash "certs/file.key", "Contents of this key file!"
44
44
  puts secret.contents "certs/file.key"
45
45
  ```
46
46
 
47
+ ## Encryption
48
+ The secret gem supports basic AES encryption with a random [IV](http://en.wikipedia.org/wiki/Initialization_vector).
49
+ Note that encryption / decryption is somewhat slow and is intended only for small strings and files.
50
+
51
+ You should implement your own encryption mechanism for anything that is more comprehensive than basic passphrase encryption.
52
+
53
+ ```ruby
54
+ secret = Secret.default
55
+ file = secret.file "my_file.txt"
56
+
57
+ # Note here that unencrypted content touches the hard drive
58
+ file.stash "This is some secret contents"
59
+
60
+ if file.encrypted?
61
+ puts "Encrypting file contents..."
62
+ file.encrypt! "password"
63
+ puts file.contents
64
+
65
+ puts "Changing file passphrase..."
66
+ file.change_encryption_passphrase! "password", "password2"
67
+ else
68
+ puts "Decrypted file contents..."
69
+ puts file.decrypted "password2"
70
+
71
+ # Will still be an encrypted string
72
+ puts file.contents
73
+
74
+ # Decrypt the file
75
+ puts "Decrypting file..."
76
+ file.decrypt!
77
+ puts file.contents
78
+ end
79
+
80
+ # If we immediately wish to stash some encrypted data
81
+ file = secret.file "file2.txt"
82
+ file.stash_encrypted "This is encrypted", "password"
83
+ ```
84
+
47
85
  ## How Secure is It?
48
86
  Ths is only *somewhat* secure and will provide protection against:
49
87
 
@@ -1,4 +1,5 @@
1
1
  require "secret/version"
2
+ require "secret/encryption"
2
3
  require "secret/file"
3
4
  require "secret/container"
4
5
 
@@ -8,7 +9,7 @@ module Secret
8
9
  CHMOD_MODE = 0700
9
10
 
10
11
  # The file extension for secret files
11
- FILE_EXT = ".sfile"
12
+ FILE_EXT = ".sf"
12
13
 
13
14
  # Gets the default container
14
15
  # @return [Secret::Container] the default container
@@ -29,6 +30,8 @@ module Secret
29
30
  end
30
31
 
31
32
  class FileUnreadableError < Exception; end
33
+
34
+ class FileEncryptedError < Exception; end
32
35
 
33
36
 
34
37
  end
@@ -1,45 +1,90 @@
1
- require 'openssl'
1
+ require 'aes'
2
2
 
3
3
  module Secret
4
+
5
+ # Enables basic encryption support with AES.
6
+ #
7
+ # Note that encryption and decription are rather slow processes and are intended to be
8
+ # used with small strings / file sizes. Please use sparingly!
4
9
  module Encryption
5
10
 
6
11
 
7
12
 
8
- def encrypt_basic(passphrase)
9
- cipher = OpenSSL::Cipher.new('aes-256-cbc')
10
- cipher.encrypt
11
- key = passphrase
12
- iv = cipher.random_iv
13
+ # Gets the contents of the file in an encrypted format. This may quite possibly
14
+ # result in doubly-encrypted text if you're not careful. This process will take
15
+ # a few moments.
16
+ def encrypted(passphrase)
17
+ return contents if encrypted?
18
+ encrypt_string passphrase, contents
19
+ end
13
20
 
14
- out = StringIO.new("", "wb") do |outf|
15
- StringIO.new(contents, "rb") do |inf|
16
- while inf.read(4096, buf)
17
- outf << cipher.update(buf)
18
- end
19
- outf << cipher.final
20
- end
21
- end
21
+
22
+ # Gets the decrypted version of this.
23
+ # @raise [OpenSSL::Cipher::CipherError] if the password was incorrect
24
+ def decrypted(passphrase)
25
+ return contents unless encrypted?
26
+ AES.decrypt contents, passphrase
27
+ end
28
+
29
+ # Immediately decrypt the contents of this file.
30
+ # @raise [OpenSSL::Cipher::CipherError] if the password was incorrect
31
+ def decrypt!(passphrase)
32
+ raise ArgumentError, "The contents of this file are not encrypted" unless encrypted?
33
+ str = decrypted(passphrase)
34
+ remove_encrypted_indicator
35
+ stash str
36
+ end
22
37
 
23
- return out.string
38
+ # Encrypt the contents of this file immediately
39
+ def encrypt!(passphrase)
40
+ stash_encrypted passphrase, contents
24
41
  end
42
+
43
+ # Change the passphrase.
44
+ def change_encryption_passphrase!(old_passphrase, new_passphrase)
45
+ raise ArgumentError, "The contents of this file are not encrypted" unless encrypted?
46
+ original = decrypted old_passphrase
47
+ remove_encrypted_indicator
48
+ stash_encrypted original, new_passphrase
49
+ end
50
+
51
+ # Stash the contents of this file with an encrypted password
52
+ def stash_encrypted(data, passphrase)
53
+ raise ArgumentError, "The contents of this file is already encrypted" if encrypted?
54
+ ::File.open(encrypted_meta_filename, 'w', container.chmod_mode) {|f| f.write "aes-default" }
55
+ str = encrypt_string passphrase, data
56
+ stash str
57
+ ::File.open(encrypted_meta_filename, 'w', container.chmod_mode) {|f| f.write "aes-default" }
58
+ end
59
+
25
60
 
26
61
  # Checks to see if the file is encrypted
27
62
  def encrypted?
28
63
  ::File.exist?(encrypted_meta_filename)
29
64
  end
30
65
 
31
-
32
- def stash(content); raise "Not Implemented"; end
33
-
34
- def contents; raise "Not Implemented"; end
66
+ # Ensure that the contents of this file are unencrypted
67
+ def ensure_unencrypted!
68
+ raise FileEncryptedError, "Contents of the file are encrypted" if encrypted?
69
+ end
35
70
 
36
71
 
72
+ def remove_encrypted_indicator
73
+ ::File.delete encrypted_meta_filename if encrypted?
74
+ end
37
75
 
38
76
  protected
77
+
78
+ def encrypt_string(passphrase, string)
79
+ iv = AES.iv :base_64
80
+ return AES.encrypt string, passphrase, :iv => iv
81
+ end
39
82
 
40
83
  def encrypted_meta_filename
41
- raise NotImplementedError, "Must implement dis!"
84
+ file_path + '.enc'
42
85
  end
86
+
87
+
43
88
 
44
89
  end
45
90
  end
@@ -2,7 +2,7 @@ module Secret
2
2
 
3
3
  # Handles file operations. Uses Ruby's internal file locking mechanisms.
4
4
  class File
5
- # include Secret::Encryption
5
+ include Secret::Encryption
6
6
 
7
7
  attr_reader :container, :identifier
8
8
 
@@ -108,6 +108,9 @@ module Secret
108
108
  # Rename tmp file to backup file now we know contents are sane
109
109
  ::File.rename(tmp_file_path, backup_file_path)
110
110
 
111
+ # Remove encryption indicator
112
+ remove_encrypted_indicator
113
+
111
114
  # Truncate file contents to zero bytes
112
115
  f.truncate 0
113
116
 
@@ -153,6 +156,11 @@ module Secret
153
156
 
154
157
  end
155
158
 
159
+ # Delete the contents of this file, along with any other associated files.
160
+ def delete!
161
+ ::File.delete(file_path) if exist?
162
+ Dir[file_path + "*"].each {|f| ::File.delete f }
163
+ end
156
164
 
157
165
  private
158
166
 
@@ -1,3 +1,3 @@
1
1
  module Secret
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -17,6 +17,8 @@ Gem::Specification.new do |spec|
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'aes'
20
22
 
21
23
  spec.add_development_dependency "bundler", "~> 1.3"
22
24
  spec.add_development_dependency "rake"
@@ -7,9 +7,24 @@ require 'secret'
7
7
  Secret.configure_default 'secrets'
8
8
  container = Secret.default
9
9
 
10
- container.stash "key.crt", "The contents of this key!"
10
+ file = container.file "key.crt"
11
+ #file.delete!
12
+ unless file.encrypted?
13
+ puts "Encrypting contents of file..."
14
+ file.stash_encrypted "This is some secret text!", "password"
15
+ puts "File contents: #{file.contents}"
16
+
17
+ puts "Changing passphrase..."
18
+ file.change_encryption_passphrase! "password", "password2"
19
+
20
+ # puts "This should result in an error..."
21
+ puts file.contents
22
+ else
23
+ puts "Decrypting file contents..."
24
+ file.decrypt! "password2"
25
+ puts "Decrypted contents: " + file.contents
26
+ end
11
27
 
12
- puts "Contents of key: '#{container.contents 'key.crt'}'"
13
28
 
14
29
 
15
30
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: secret
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Thornton
@@ -10,6 +10,20 @@ bindir: bin
10
10
  cert_chain: []
11
11
  date: 2013-05-14 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aes
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement