1 #pragma once
2 #include <memory>
3 #include <string>
4 #include <unordered_map>
5 #include <vector>
6 
7 #include "json.hpp"
8 // for convenience
9 using json = nlohmann::json;
10 
11 struct KeychainField {
12     std::string name;
13     std::string value;
14     std::string type;
15     bool password;
16 };
17 
18 struct KeychainItem {
19     std::string title;
20     std::string uuid;
21     std::string category;
22     std::string folder;
23     std::unordered_map<std::string, std::vector<KeychainField>> sections;
addFieldKeychainItem24     void addField(std::string section, KeychainField field) {
25         auto it = sections.find(section);
26         if (it == sections.end()) {
27             sections.emplace(std::make_pair(section, std::vector<KeychainField>{field}));
28         } else {
29             it->second.push_back(std::move(field));
30         }
31     }
32     std::vector<std::string> URLs;
33     std::string website;
34     std::string notes;
35 };
36 
37 class AgileKeychainMasterKey {
38 public:
39     AgileKeychainMasterKey(const json& input, const std::string masterPassword);
40 
41     json decryptItem(const json& input);
42     json decryptJSON(const std::string& input);
43     std::string encryptJSON(const json& input);
44 
45     std::string level;
46     std::string id;
47 
48 private:
49     std::vector<uint8_t> key_data;
50 };
51 
52 class Keychain {
53 public:
54     Keychain(std::string path, std::string masterPassword);
55 
56     using ItemMap = std::unordered_map<std::string, KeychainItem>;
begin()57     ItemMap::iterator begin() {
58         if (!loaded)
59             reloadItems();
60         return items.begin();
61     }
62 
end()63     ItemMap::iterator end() {
64         if (!loaded)
65             reloadItems();
66         return items.end();
67     }
68 
find(std::string key)69     ItemMap::iterator find(std::string key) {
70         if (!loaded)
71             reloadItems();
72         return items.find(key);
73     }
74 
75     void reloadItems();
76     void unloadItems();
77 
getTitle()78     std::string getTitle() {
79         return title;
80     }
81 
decryptJSON(const std::string & input)82     json decryptJSON(const std::string& input) {
83         return level5_key->decryptJSON(input);
84     }
85 
encryptJSON(const json & input)86     std::string encryptJSON(const json& input) {
87         return level5_key->encryptJSON(input);
88     }
89 
90 private:
91     void loadItem(std::string uuid);
92 
93     ItemMap items;
94     std::unique_ptr<AgileKeychainMasterKey> level3_key, level5_key;
95     std::string vault_path;
96     std::string title;
97     bool loaded = false;
98 };
99