Fabcoin Core  0.16.2
P2P Digital Currency
SecretStore.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #include <fstream>
19 #include <boost/test/unit_test.hpp>
20 #include <boost/filesystem.hpp>
23 #include <libdevcore/CommonIO.h>
24 #include <libdevcore/TrieDB.h>
25 #include <libdevcore/TrieHash.h>
27 #include "MemTrie.h"
29 using namespace std;
30 using namespace dev;
31 using namespace dev::test;
32 
33 namespace js = json_spirit;
34 namespace fs = boost::filesystem;
35 
36 BOOST_AUTO_TEST_SUITE(Crypto)
37 
39 
41 {
42  string testPath = test::getTestPath();
43 
44  testPath += "/KeyStoreTests";
45 
46  cnote << "Testing Key Store...";
47  js::mValue v;
48  string s = contentsString(testPath + "/basic_tests.json");
49  BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'KeyStoreTests/basic_tests.json' is empty. Have you cloned the 'tests' repo branch develop?");
50  js::read_string(s, v);
51  for (auto& i: v.get_obj())
52  {
53  cnote << i.first;
54  js::mObject& o = i.second.get_obj();
55  TransientDirectory tmpDir;
56  SecretStore store(tmpDir.path());
57  h128 u = store.readKeyContent(js::write_string(o["json"], false));
58  cdebug << "read uuid" << u;
59  bytesSec s = store.secret(u, [&](){ return o["password"].get_str(); });
60  cdebug << "got secret" << toHex(s.makeInsecure());
61  BOOST_REQUIRE_EQUAL(toHex(s.makeInsecure()), o["priv"].get_str());
62  }
63 }
64 
65 BOOST_AUTO_TEST_CASE(import_key_from_file)
66 {
67  // Imports a key from an external file. Tests that the imported key is there
68  // and that the external file is not deleted.
69  TransientDirectory importDir;
70  string importFile = importDir.path() + "/import.json";
71  TransientDirectory storeDir;
72  string keyData = R"({
73  "version": 3,
74  "crypto": {
75  "ciphertext": "d69313b6470ac1942f75d72ebf8818a0d484ac78478a132ee081cd954d6bd7a9",
76  "cipherparams": { "iv": "ffffffffffffffffffffffffffffffff" },
77  "kdf": "pbkdf2",
78  "kdfparams": { "dklen": 32, "c": 262144, "prf": "hmac-sha256", "salt": "c82ef14476014cbf438081a42709e2ed" },
79  "mac": "cf6bfbcc77142a22c4a908784b4a16f1023a1d0e2aff404c20158fa4f1587177",
80  "cipher": "aes-128-ctr",
81  "version": 1
82  },
83  "id": "abb67040-8dbe-0dad-fc39-2b082ef0ee5f"
84  })";
85  string password = "bar";
86  string priv = "0202020202020202020202020202020202020202020202020202020202020202";
87  writeFile(importFile, keyData);
88 
89  h128 uuid;
90  {
91  SecretStore store(storeDir.path());
92  BOOST_CHECK_EQUAL(store.keys().size(), 0);
93  uuid = store.importKey(importFile);
94  BOOST_CHECK(!!uuid);
95  BOOST_CHECK(contentsString(importFile) == keyData);
96  BOOST_CHECK_EQUAL(priv, toHex(store.secret(uuid, [&](){ return password; }).makeInsecure()));
97  BOOST_CHECK_EQUAL(store.keys().size(), 1);
98  }
99  fs::remove(importFile);
100  // now do it again to check whether SecretStore properly stored it on disk
101  {
102  SecretStore store(storeDir.path());
103  BOOST_CHECK_EQUAL(store.keys().size(), 1);
104  BOOST_CHECK_EQUAL(priv, toHex(store.secret(uuid, [&](){ return password; }).makeInsecure()));
105  }
106 }
107 
108 BOOST_AUTO_TEST_CASE(import_secret)
109 {
110  for (string const& password: {"foobar", ""})
111  {
112  TransientDirectory storeDir;
113  string priv = "0202020202020202020202020202020202020202020202020202020202020202";
114 
115  h128 uuid;
116  {
117  SecretStore store(storeDir.path());
118  BOOST_CHECK_EQUAL(store.keys().size(), 0);
119  uuid = store.importSecret(bytesSec(fromHex(priv)), password);
120  BOOST_CHECK(!!uuid);
121  BOOST_CHECK_EQUAL(priv, toHex(store.secret(uuid, [&](){ return password; }).makeInsecure()));
122  BOOST_CHECK_EQUAL(store.keys().size(), 1);
123  }
124  {
125  SecretStore store(storeDir.path());
126  BOOST_CHECK_EQUAL(store.keys().size(), 1);
127  BOOST_CHECK_EQUAL(priv, toHex(store.secret(uuid, [&](){ return password; }).makeInsecure()));
128  }
129  }
130 }
131 
132 BOOST_AUTO_TEST_CASE(import_secret_bytesConstRef)
133 {
134  for (string const& password: {"foobar", ""})
135  {
136  TransientDirectory storeDir;
137  string priv = "0202020202020202020202020202020202020202020202020202020202020202";
138 
139  h128 uuid;
140  {
141  SecretStore store(storeDir.path());
142  BOOST_CHECK_EQUAL(store.keys().size(), 0);
143  bytes privateBytes = fromHex(priv);
144  uuid = store.importSecret(&privateBytes, password);
145  BOOST_CHECK(!!uuid);
146  BOOST_CHECK_EQUAL(priv, toHex(store.secret(uuid, [&](){ return password; }).makeInsecure()));
147  BOOST_CHECK_EQUAL(store.keys().size(), 1);
148  }
149  {
150  SecretStore store(storeDir.path());
151  BOOST_CHECK_EQUAL(store.keys().size(), 1);
152  BOOST_CHECK_EQUAL(priv, toHex(store.secret(uuid, [&](){ return password; }).makeInsecure()));
153  }
154  }
155 }
156 
157 BOOST_AUTO_TEST_CASE(wrong_password)
158 {
159  TransientDirectory storeDir;
160  SecretStore store(storeDir.path());
161  string password = "foobar";
162  string priv = "0202020202020202020202020202020202020202020202020202020202020202";
163 
164  h128 uuid;
165  {
166  SecretStore store(storeDir.path());
167  BOOST_CHECK_EQUAL(store.keys().size(), 0);
168  uuid = store.importSecret(bytesSec(fromHex(priv)), password);
169  BOOST_CHECK(!!uuid);
170  BOOST_CHECK_EQUAL(priv, toHex(store.secret(uuid, [&](){ return password; }).makeInsecure()));
171  BOOST_CHECK_EQUAL(store.keys().size(), 1);
172  // password will not be queried
173  BOOST_CHECK_EQUAL(priv, toHex(store.secret(uuid, [&](){ return "abcdefg"; }).makeInsecure()));
174  }
175  {
176  SecretStore store(storeDir.path());
177  BOOST_CHECK_EQUAL(store.keys().size(), 1);
178  BOOST_CHECK(store.secret(uuid, [&](){ return "abcdefg"; }).empty());
179  }
180 }
181 
183 {
184  TransientDirectory storeDir;
185  SecretStore store(storeDir.path());
186  string password = "foobar";
187  string changedPassword = "abcdefg";
188  string priv = "0202020202020202020202020202020202020202020202020202020202020202";
189 
190  h128 uuid;
191  {
192  SecretStore store(storeDir.path());
193  BOOST_CHECK_EQUAL(store.keys().size(), 0);
194  uuid = store.importSecret(bytesSec(fromHex(priv)), password);
195  BOOST_CHECK(!!uuid);
196  BOOST_CHECK_EQUAL(priv, toHex(store.secret(uuid, [&](){ return password; }).makeInsecure()));
197  BOOST_CHECK_EQUAL(store.keys().size(), 1);
198  }
199  {
200  SecretStore store(storeDir.path());
201  BOOST_CHECK_EQUAL(store.keys().size(), 1);
202  BOOST_CHECK(store.secret(uuid, [&](){ return "abcdefg"; }).empty());
203  BOOST_CHECK(store.recode(uuid, changedPassword, [&](){ return password; }));
204  BOOST_CHECK_EQUAL(store.keys().size(), 1);
205  BOOST_CHECK_EQUAL(priv, toHex(store.secret(uuid, [&](){ return changedPassword; }).makeInsecure()));
206  store.clearCache();
207  BOOST_CHECK(store.secret(uuid, [&](){ return password; }).empty());
208  BOOST_CHECK_EQUAL(priv, toHex(store.secret(uuid, [&](){ return changedPassword; }).makeInsecure()));
209  }
210  {
211  SecretStore store(storeDir.path());
212  BOOST_CHECK_EQUAL(store.keys().size(), 1);
213  BOOST_CHECK(store.secret(uuid, [&](){ return password; }).empty());
214  BOOST_CHECK_EQUAL(priv, toHex(store.secret(uuid, [&](){ return changedPassword; }).makeInsecure()));
215  }
216 }
217 
const Object & get_obj() const
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
std::string toHex(T const &_data, int _w=2, HexPrefix _prefix=HexPrefix::DontAdd)
Definition: CommonData.h:54
void writeFile(std::string const &_file, bytesConstRef _data, bool _writeDeleteRename=false)
Write the given binary data into the given file, replacing the file if it pre-exists.
Definition: CommonIO.cpp:107
secure_vector< byte > bytesSec
Definition: Common.h:118
std::hash for asio::adress
Definition: Common.h:323
std::string contentsString(std::string const &_file)
Retrieve and returns the contents of the given file as a std::string.
std::vector< T > const & makeInsecure() const
Definition: Common.h:102
#define cdebug
Definition: Log.h:302
bytes fromHex(std::string const &_s, WhenError _throw=WhenError::DontThrow)
Definition: CommonData.cpp:99
bool read_string(const String_type &s, Value_type &value)
std::vector< byte > bytes
Definition: Common.h:75
std::string getTestPath()
Definition: Common.cpp:35
Fixed-size raw-byte array container type, with an API optimised for storing hashes.
Definition: FixedHash.h:47
mConfig::Object_type mObject
Value_type::String_type write_string(const Value_type &value, bool pretty)
#define cnote
Definition: Log.h:303
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
std::string const & path() const
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_AUTO_TEST_SUITE_END()
Definition: object.cpp:16
Manages encrypted keys stored in a certain directory on disk.
Definition: SecretStore.h:46
BOOST_AUTO_TEST_CASE(basic_tests)
Definition: SecretStore.cpp:40
std::string get_str(std::string::const_iterator begin, std::string::const_iterator end)
temporary directory implementation It creates temporary directory in the given path.
Helper functions to work with json::spirit and test files.
#define BOOST_CHECK(expr)
Definition: object.cpp:17