go_secure 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +20 -0
- data/README.md +1 -0
- data/lib/go_secure.rb +135 -0
- 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: []
|