go_secure 0.1

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 (5) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.md +1 -0
  4. data/lib/go_secure.rb +135 -0
  5. metadata +75 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e03f684aa71c0ea293b16228ef7ddb2a49cec19b
4
+ data.tar.gz: efca779a729154a524e2c3b9cb6fa76db0dfba80
5
+ SHA512:
6
+ metadata.gz: 20d03c5c5e05a8d494c7e267016954b0523ba5ae1fe0135c9428331adcee562681295cc037e4a71d97bd3d39a7f1a90cf8a319894a0b09fd7b73334c0e275bd6
7
+ data.tar.gz: 6d702b2fcff177d7ed53fbb9b634ab6fa48debfb19d49da3b567f5ee3ca99ccc7aac12006fb4f11b9335d5553974c46b1dd6662ebb5807e0ada4d440f385d943
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 CoughDrop
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to use,
8
+ copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
9
+ Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1 @@
1
+ Security helper gem, used by multiple CoughDrop libraries
data/lib/go_secure.rb ADDED
@@ -0,0 +1,135 @@
1
+ require 'openssl'
2
+
3
+ module GoSecure
4
+ def self.sha512(str, salt, encryption_key=nil)
5
+ Digest::SHA512.hexdigest(str.to_s + salt.to_s + (encryption_key || self.encryption_key))
6
+ end
7
+
8
+ def self.nonce(str)
9
+ Digest::SHA512.hexdigest(str.to_s + Time.now.to_i.to_s + rand(999999).to_s + self.encryption_key)[0, 24]
10
+ end
11
+
12
+ def self.encrypt(str, ref, encryption_key=nil)
13
+ require 'base64'
14
+ c = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
15
+ c.encrypt
16
+ c.key = Digest::SHA2.hexdigest(ref + "_" + (encryption_key || self.encryption_key))
17
+ c.iv = iv = c.random_iv
18
+ e = c.update(str)
19
+ e << c.final
20
+ res = [Base64.encode64(e), Base64.encode64(iv)]
21
+ res
22
+ end
23
+
24
+ def self.decrypt(str, salt, ref, encryption_key=nil)
25
+ require 'base64'
26
+ c = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
27
+ c.decrypt
28
+ c.key = Digest::SHA2.hexdigest(ref + "_" + (encryption_key || self.encryption_key))
29
+ c.iv = Base64.decode64(salt)
30
+ d = c.update(Base64.decode64(str))
31
+ d << c.final
32
+ d.to_s
33
+ end
34
+
35
+ def self.generate_password(password)
36
+ raise "password required" if password == nil || password.length == 0
37
+ pw = {}
38
+ # pw['hash_type'] = 'sha512'
39
+ # pw['hash_type'] = 'bcrypt'
40
+ pw['hash_type'] = 'pbkdf2-sha256'
41
+ pw['salt'] = Digest::MD5.hexdigest(OpenSSL::Random.pseudo_bytes(4) + Time.now.to_i.to_s + self.encryption_key + "pw" + OpenSSL::Random.pseudo_bytes(16))
42
+ # pw['hashed_password'] = Digest::SHA512.hexdigest(self.encryption_key + pw['salt'] + password.to_s)
43
+ # salted = Digest::SHA256.hexdigest(self.encryption_key + pw['salt'] + password.to_s)
44
+ # pw['hashed_password'] = BCrypt::Password.create(salted)
45
+ digest = OpenSSL::Digest::SHA256.new
46
+ pw['hashed_password'] = Base64.encode64(OpenSSL::PKCS5.pbkdf2_hmac(password.to_s, pw['salt'], 100000, digest.digest_length, digest))
47
+ pw
48
+ end
49
+
50
+ def self.outdated_password?(password_hash)
51
+ return password_hash && password_hash['hash_type'] != 'pbkdf2-sha256'
52
+ end
53
+
54
+ def self.matches_password?(attempt, password_hash)
55
+ if password_hash && password_hash['hash_type'] == 'sha512' && password_hash['salt']
56
+ str = Digest::SHA512.hexdigest(self.encryption_key + password_hash['salt'] + attempt.to_s)
57
+ res = str == password_hash['hashed_password']
58
+ if !res && password_hash['old_passwords']
59
+ # TODO: support for migrating to new hashing algorithms
60
+ else
61
+ res
62
+ end
63
+ elsif password_hash && password_hash['hash_type'] == 'bcrypt' && password_hash['salt']
64
+ pw = BCrypt::Password.new(password_hash['hashed_password'])
65
+ salted = Digest::SHA256.hexdigest(self.encryption_key + password_hash['salt'] + attempt.to_s)
66
+ res = pw == salted
67
+ elsif password_hash && password_hash['hash_type'] == 'pbkdf2-sha256' && password_hash['salt']
68
+ digest = OpenSSL::Digest::SHA256.new
69
+ str = Base64.encode64(OpenSSL::PKCS5.pbkdf2_hmac(attempt.to_s, password_hash['salt'], 100000, digest.digest_length, digest))
70
+ res = str == password_hash['hashed_password']
71
+ else
72
+ false
73
+ end
74
+ end
75
+
76
+ def self.validate_encryption_key
77
+ if !self.encryption_key || self.encryption_key.length < 24
78
+ raise "SECURE_ENCRYPTION_KEY env variable should be at least 24 characters"
79
+ end
80
+ return if !ActiveRecord::Base.connection.data_source_exists?('settings')
81
+ config_hash = Digest::SHA1.hexdigest(self.encryption_key)
82
+ stored_hash = Setting.get('encryption_hash')
83
+ return if stored_hash == config_hash
84
+
85
+ if stored_hash.nil?
86
+ Setting.set('encryption_hash', config_hash);
87
+ else
88
+ raise "SECURE_ENCRYPTION_KEY env variable doesn't match the value stored in the database." +
89
+ " If this is intentional you can try DELETE FROM settings WHERE key='encryption_hash' to reset."
90
+ end
91
+ end
92
+
93
+ def self.encryption_key
94
+ ENV['SECURE_ENCRYPTION_KEY']
95
+ end
96
+
97
+ def self.browser_token
98
+ # TODO: checks around whether it's actually a web browser??
99
+ stamp = Time.now.strftime('%Y%j')
100
+ stamp += '-' + GoSecure.sha512(stamp, 'browser_token')
101
+ end
102
+
103
+ def self.valid_browser_token_signature?(token)
104
+ stamp, hash = token.split(/-/, 2)
105
+ return hash == GoSecure.sha512(stamp, 'browser_token')
106
+ end
107
+
108
+ def self.valid_browser_token?(token)
109
+ return false if !token || token.length == 0 || !token.match(/-/)
110
+ stamp, hash = token.split(/-/, 2)
111
+ if Time.now.strftime('%Y%j').to_i - stamp.to_i < 14 # 14 days?!
112
+ return valid_browser_token_signature?(token)
113
+ end
114
+ false
115
+ end
116
+
117
+ module SecureJson
118
+ def self.load(str)
119
+ return nil unless str
120
+ salt, secret = str.split(/--/, 2)
121
+ JSON.load(GoSecure.decrypt(secret, salt, "secure_json"))
122
+ end
123
+
124
+ def self.dump(obj)
125
+ json = JSON.dump(obj)
126
+ res = encrypted_dump(json)
127
+ res
128
+ end
129
+
130
+ def self.encrypted_dump(json)
131
+ secret, salt = GoSecure.encrypt(json, "secure_json")
132
+ salt + "--" + secret
133
+ end
134
+ end
135
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: go_secure
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Brian Whitmer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ruby-debug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Security helper gem, used by multiple CoughDrop libraries
42
+ email: brian.whitmer@gmail.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files:
46
+ - LICENSE
47
+ files:
48
+ - LICENSE
49
+ - README.md
50
+ - lib/go_secure.rb
51
+ homepage: https://github.com/CoughDrop/obf
52
+ licenses:
53
+ - MIT
54
+ metadata: {}
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 2.5.2
72
+ signing_key:
73
+ specification_version: 4
74
+ summary: Go Secure
75
+ test_files: []