secret 0.0.2 → 0.0.3
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.
- checksums.yaml +4 -4
- data/README.md +39 -1
- data/lib/secret.rb +4 -1
- data/lib/secret/encryption.rb +65 -20
- data/lib/secret/file.rb +9 -1
- data/lib/secret/version.rb +1 -1
- data/secret.gemspec +2 -0
- data/test/tester.rb +17 -2
- metadata +15 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 41f92b03a262766c7d234c19c6a960de5a842c19
|
4
|
+
data.tar.gz: 6e32e9c816c5fc79e8a37409438e8874a66d79d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
|
data/lib/secret.rb
CHANGED
@@ -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 = ".
|
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
|
data/lib/secret/encryption.rb
CHANGED
@@ -1,45 +1,90 @@
|
|
1
|
-
require '
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
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
|
33
|
-
|
34
|
-
|
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
|
-
|
84
|
+
file_path + '.enc'
|
42
85
|
end
|
86
|
+
|
87
|
+
|
43
88
|
|
44
89
|
end
|
45
90
|
end
|
data/lib/secret/file.rb
CHANGED
@@ -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
|
-
|
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
|
|
data/lib/secret/version.rb
CHANGED
data/secret.gemspec
CHANGED
@@ -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"
|
data/test/tester.rb
CHANGED
@@ -7,9 +7,24 @@ require 'secret'
|
|
7
7
|
Secret.configure_default 'secrets'
|
8
8
|
container = Secret.default
|
9
9
|
|
10
|
-
container.
|
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.
|
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
|