go_secure 0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []