/
1pass.lua
146 lines (116 loc) · 3.39 KB
/
1pass.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
JSON = (loadfile "JSON.lua")()
local function dumptable(tabname, tab, depth)
if depth == nil then -- first call, before any recursion?
depth = 1
end
if tabname ~= nil then
if tab == nil then
print(tabname .. " = nil")
return
else
print(tabname .. " = {")
end
end
local depthstr = ""
for i=1,(depth*4) do
depthstr = depthstr .. " "
end
if tab.DUMPTABLE_ITERATED then
print(depthstr .. "(...circular reference...)")
else
tab.DUMPTABLE_ITERATED = true
for k,v in pairs(tab) do
if type(v) == "table" then
print(depthstr .. tostring(k) .. " = {")
dumptable(nil, v, depth + 1)
print(depthstr .. "}")
else
if k ~= "DUMPTABLE_ITERATED" then
print(depthstr .. tostring(k) .. " = " .. tostring(v))
end
end
end
tab.DUMPTABLE_ITERATED = nil
end
if tabname ~= nil then
print("}")
end
end
local function load_json_str(str, desc)
local retval = JSON:decode(str)
dumptable("JSON " .. desc, retval)
return retval
end
local function load_json(fname)
local f = io.open(fname, "rb")
if (f == nil) then
return nil
end
local str = f:read("*all")
f:close()
return load_json_str(str, fname)
end
local keys = {}
function loadKey(basedir, level, password)
if keys[level] ~= nil then
return keys[level]
end
local keysjson = load_json(basedir .. "/encryptionKeys.js");
if (keysjson == nil) or (keysjson[level] == nil) then
return nil
end
local identifier = keysjson[level]
for i,v in ipairs(keysjson.list) do
if v.identifier == identifier then
local iterations = v.iterations
if (iterations == nil) or (iterations < 1000) then
iterations = 1000
end
local decrypted = decryptUsingPBKDF2(v.data, password, iterations)
if decrypted == nil then
return nil
end
local validate = decryptBase64UsingKey(v.validation, decrypted)
if validate ~= decrypted then
return nil
end
keys[level] = decrypted
return decrypted
end
end
return nil
end
local function showHint(basedir)
local f = io.open(basedir .. "/.password.hint", "r")
if (f == nil) then
return
end
local str = f:read("*all")
f:close()
print("(hint is '" .. str .. "').")
end
function loadContents(basedir)
return load_json(basedir .. "/contents.js");
end
-- Mainline!
local basedir = "1Password/1Password.agilekeychain/data/default" -- !!! FIXME
showHint(basedir)
io.write("password: ")
local password = io.read("*l")
if loadKey(basedir, "SL5", password) == nil then
print("wrong password?\n")
os.exit(1)
end
items = loadContents(basedir)
for i,v in ipairs(items) do
if v[2] ~= "system.Tombstone" then -- I guess those are dead items?
local metadata = load_json(basedir .. "/" .. v[1] .. ".1password")
if metadata ~= nil then
local plaintext = decryptBase64UsingKey(metadata.encrypted, loadKey(basedir, metadata.securityLevel, password))
if plaintext ~= nil then
local secure = load_json_str(plaintext, v[1])
end
end
end
end
-- end of 1pass.lua ...