onepass 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/OnePass.gemspec +1 -0
- data/lib/OnePass/version.rb +1 -1
- data/lib/OnePass.rb +53 -31
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f081e63d2a0fc4f35b2ca7698facbc79a27dbe68
|
4
|
+
data.tar.gz: 26e4b49e1e270d90ae4c00262d4b0d0bd68cf3fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa0258a8c9ab35aeba1062fbe697f7f46172d2d355158080d80597c7246d21225d32a32bf42a7315bfb29df1ccf8fe52a4dc03e17c7d488c04119d43602b12a1
|
7
|
+
data.tar.gz: 1f16989a6776547b046f6c80eb3075186c0c9c76297061c23b14debb9215cb8211298563f741db47fc6cbff7316690cbd7c5b0e4f326ff308b7bfb3f2f13ff99
|
data/OnePass.gemspec
CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency "sqlite3", "~> 1.3.9"
|
22
|
+
spec.add_dependency "CFPropertyList"
|
22
23
|
|
23
24
|
spec.add_development_dependency "bundler", "~> 1.7"
|
24
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
data/lib/OnePass/version.rb
CHANGED
data/lib/OnePass.rb
CHANGED
@@ -3,6 +3,7 @@ require "openssl"
|
|
3
3
|
require "sqlite3"
|
4
4
|
require "json"
|
5
5
|
require "tempfile"
|
6
|
+
require "cfpropertylist"
|
6
7
|
|
7
8
|
module OnePass
|
8
9
|
class VerifyException < Exception
|
@@ -18,7 +19,7 @@ module OnePass
|
|
18
19
|
if buf[0..7] != "opdata01"
|
19
20
|
raise OnePass::Opdata::InvalidException.new("Header was incorrect")
|
20
21
|
end
|
21
|
-
@length = buf[8..15].unpack("
|
22
|
+
@length = buf[8..15].unpack("Q<")[0]
|
22
23
|
@mac = buf[-32..-1]
|
23
24
|
if OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, mac, buf[0..-33]) != @mac
|
24
25
|
raise OnePass::VerifyException.new("MAC doesn't match; verify failed. Check your encryption/mac keys.")
|
@@ -60,33 +61,48 @@ module OnePass
|
|
60
61
|
db = SQLite3::Database.new(sqlite_file)
|
61
62
|
db.execute "VACUUM;"
|
62
63
|
|
63
|
-
|
64
|
+
@master_keys = []
|
65
|
+
@overview_keys = []
|
64
66
|
@overviews = []
|
65
|
-
|
66
|
-
db.execute "SELECT id,master_key_data,overview_key_data,salt,iterations FROM profiles
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
67
|
+
# read master profile
|
68
|
+
master_profile = db.execute "SELECT id,master_key_data,overview_key_data,salt,iterations FROM profiles WHERE attributes_data IS NULL"
|
69
|
+
raise "Found more than one master profile!" unless master_profile.length == 1
|
70
|
+
master_profile.flatten!
|
71
|
+
master_profile_id = master_profile[0]
|
72
|
+
|
73
|
+
# derive the key from the password
|
74
|
+
derived_key = OpenSSL::PKCS5.pbkdf2_hmac(master_password, master_profile[3], master_profile[4], 64, OpenSSL::Digest::SHA512.new)
|
75
|
+
derived_encryption_key = derived_key[0..31]
|
76
|
+
derived_mac_key = derived_key[32..-1]
|
77
|
+
|
78
|
+
# Obtain the master profile master keys
|
79
|
+
master_key_data = OnePass::Opdata.new(master_profile[1], derived_encryption_key, derived_mac_key)
|
80
|
+
master_key = OpenSSL::Digest::SHA512.new.digest(master_key_data.data)
|
81
|
+
@master_keys[master_profile_id] = {enc_key: master_key[0..31], mac_key: master_key[32..-1]}
|
82
|
+
|
83
|
+
# Obtain the master profile overview keys
|
84
|
+
overview_key_data = OnePass::Opdata.new(master_profile[2], derived_encryption_key, derived_mac_key)
|
85
|
+
overview_key = OpenSSL::Digest::SHA512.new.digest(overview_key_data.data)
|
86
|
+
@overview_keys[master_profile_id] = { enc_key: overview_key[0..31], mac_key: overview_key[32..-1] }
|
87
|
+
|
88
|
+
# Obtain keys for remaining profiles
|
89
|
+
db.execute "SELECT id,attributes_data FROM profiles WHERE attributes_data IS NOT NULL" do |profile|
|
90
|
+
attributes_data = OnePass::Opdata.new(profile[1], @overview_keys[master_profile_id][:enc_key], @overview_keys[master_profile_id][:mac_key])
|
91
|
+
plist = CFPropertyList.native_types(CFPropertyList::List.new(:data => attributes_data.data).value)
|
92
|
+
overview_key_data = plist['$objects'][plist['$top']['overviewKey']]
|
93
|
+
overview_key = OpenSSL::Digest::SHA512.new.digest(overview_key_data)
|
94
|
+
@overview_keys[profile[0]] = { enc_key: overview_key[0..31], mac_key: overview_key[32..-1] }
|
95
|
+
master_key_data = plist['$objects'][plist['$top']['masterKey']]
|
96
|
+
master_key = OpenSSL::Digest::SHA512.new.digest(master_key_data)
|
97
|
+
@master_keys[profile[0]] = { enc_key: master_key[0..31], mac_key: master_key[32..-1] }
|
98
|
+
end
|
99
|
+
|
100
|
+
# load overview opdata into object based format. overviews are stored decrypted for use later.
|
101
|
+
# the encrypted data for the keys is included, but is not decrypted unless requested later
|
102
|
+
db.execute "SELECT items.profile_id, items.key_data, items.overview_data, item_details.data FROM items INNER JOIN item_details ON items.id=item_details.item_id" do |item|
|
103
|
+
overview = OnePass::Opdata.new(item[2], @overview_keys[item[0]][:enc_key], @overview_keys[item[0]][:mac_key])
|
104
|
+
json = JSON.parse(overview.data).merge({profile: item[0], key_data: item[1], data: item[3]})
|
105
|
+
@overviews << json
|
90
106
|
end
|
91
107
|
|
92
108
|
db.close
|
@@ -104,20 +120,26 @@ module OnePass
|
|
104
120
|
return nil
|
105
121
|
end
|
106
122
|
|
107
|
-
def decrypt(overview)
|
123
|
+
def decrypt(overview, all = nil)
|
108
124
|
key_data = overview[:key_data][0..-33]
|
109
125
|
mac = overview[:key_data][-32..-1]
|
110
126
|
profile = overview[:profile]
|
111
|
-
if OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, @
|
127
|
+
if OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, @master_keys[profile][:mac_key], key_data) != mac
|
112
128
|
raise VerifyException.new("The item's encryption key couldn't be verified.")
|
113
129
|
end
|
114
130
|
cipher = OpenSSL::Cipher::AES.new(256, :CBC)
|
115
131
|
cipher.decrypt
|
116
132
|
cipher.padding = 0
|
117
133
|
cipher.iv = key_data[0..15]
|
118
|
-
cipher.key = @
|
134
|
+
cipher.key = @master_keys[profile][:enc_key]
|
119
135
|
key_data = cipher.update(key_data[16..-1]) + cipher.final
|
120
|
-
|
136
|
+
results = JSON.parse(OnePass::Opdata.new(overview[:data],key_data[0..31],key_data[32..-1]).data)
|
137
|
+
password = if results.has_key?("password")
|
138
|
+
results["password"]
|
139
|
+
elsif results.has_key?("fields")
|
140
|
+
results["fields"].find { |h| h["designation"] == "password" }["value"]
|
141
|
+
end
|
142
|
+
return all ? results : password
|
121
143
|
end
|
122
144
|
end
|
123
145
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: onepass
|
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
|
- Kai Lieth
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sqlite3
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.3.9
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: CFPropertyList
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -104,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
118
|
version: '0'
|
105
119
|
requirements: []
|
106
120
|
rubyforge_project:
|
107
|
-
rubygems_version: 2.4.
|
121
|
+
rubygems_version: 2.4.6
|
108
122
|
signing_key:
|
109
123
|
specification_version: 4
|
110
124
|
summary: Decrypt the secrets stored in 1Password 4
|