Skip to content

Commit cd64adc

Browse files
committed
Basic key manager.
1 parent 2f5eb4e commit cd64adc

6 files changed

Lines changed: 93 additions & 48 deletions

File tree

exp/main.cpp

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ namespace fs = boost::filesystem;
6565
#if 1
6666

6767
inline h128 fromUUID(std::string const& _uuid) { return h128(boost::replace_all_copy(_uuid, "-", "")); }
68+
inline std::string toUUID(h128 const& _uuid) { std::string ret = toHex(_uuid.ref()); for (unsigned i: {20, 16, 12, 8}) ret.insert(ret.begin() + i, '-'); return ret; }
6869

6970
class KeyManager: public Worker
7071
{
@@ -74,31 +75,48 @@ class KeyManager: public Worker
7475

7576
Secret secret(h128 const& _uuid, function<std::string()> const& _pass)
7677
{
77-
auto rit = m_ready.find(_uuid);
78-
if (rit != m_ready.end())
78+
auto rit = m_cached.find(_uuid);
79+
if (rit != m_cached.end())
7980
return rit->second;
8081
auto it = m_keys.find(_uuid);
8182
if (it == m_keys.end())
8283
return Secret();
8384
Secret ret(decrypt(it->second, _pass()));
8485
if (ret)
85-
m_ready[_uuid] = ret;
86+
m_cached[_uuid] = ret;
8687
return ret;
8788
}
8889

89-
h128 create(std::string const& _pass)
90+
h128 import(Secret const& _s, std::string const& _pass)
9091
{
91-
auto s = Secret::random();
92-
h128 r(sha3(s));
93-
m_ready[r] = s;
94-
m_keys[r] = encrypt(s.asBytes(), _pass);
92+
h128 r(sha3(_s));
93+
m_cached[r] = _s;
94+
m_keys[r] = encrypt(_s.asBytes(), _pass);
95+
writeKeys();
9596
return r;
9697
}
9798

99+
h128 create(std::string const& _pass)
100+
{
101+
return import(Secret::random(), _pass);
102+
}
103+
104+
void clearCache() const { m_cached.clear(); }
105+
98106
private:
99107
void writeKeys(std::string const& _keysPath = getDataDir("web3") + "/keys")
100108
{
101-
(void)_keysPath;
109+
fs::path p(_keysPath);
110+
boost::filesystem::create_directories(p);
111+
for (auto const& k: m_keys)
112+
{
113+
std::string uuid = toUUID(k.first);
114+
js::mObject v;
115+
v["crypto"] = k.second;
116+
v["id"] = uuid;
117+
v["version"] = 2;
118+
writeFile((p / uuid).string() + ".json", js::write_string(js::mValue(v), true));
119+
}
102120
}
103121

104122
void readKeys(std::string const& _keysPath = getDataDir("web3") + "/keys")
@@ -126,9 +144,42 @@ class KeyManager: public Worker
126144

127145
static js::mValue encrypt(bytes const& _v, std::string const& _pass)
128146
{
129-
(void)_v;
130-
(void)_pass;
131-
return js::mValue();
147+
js::mObject ret;
148+
149+
// KDF info
150+
unsigned dklen = 16;
151+
unsigned iterations = 262144;
152+
bytes salt = h256::random().asBytes();
153+
ret["kdf"] = "pbkdf2";
154+
{
155+
js::mObject params;
156+
params["prf"] = "hmac-sha256";
157+
params["c"] = (int)iterations;
158+
params["salt"] = toHex(salt);
159+
params["dklen"] = (int)dklen;
160+
ret["kdfparams"] = params;
161+
}
162+
bytes derivedKey = pbkdf2(_pass, salt, iterations, dklen);
163+
164+
// cipher info
165+
ret["cipher"] = "aes-128-cbc";
166+
h128 key(sha3(h128(derivedKey, h128::AlignRight)), h128::AlignRight);
167+
h128 iv = h128::random();
168+
{
169+
js::mObject params;
170+
params["iv"] = toHex(iv.ref());
171+
ret["cipherparams"] = params;
172+
}
173+
174+
// cipher text
175+
bytes cipherText = encryptSymNoAuth(key, iv, &_v);
176+
ret["ciphertext"] = toHex(cipherText);
177+
178+
// and mac.
179+
h256 mac = sha3(bytesConstRef(&derivedKey).cropped(derivedKey.size() - 16).toBytes() + cipherText);
180+
ret["mac"] = toHex(mac.ref());
181+
182+
return ret;
132183
}
133184

134185
static bytes decrypt(js::mValue const& _v, std::string const& _pass)
@@ -167,32 +218,29 @@ class KeyManager: public Worker
167218
}
168219

169220
// decrypt
170-
bytes ret;
171221
if (o["cipher"].get_str() == "aes-128-cbc")
172222
{
173223
auto params = o["cipherparams"].get_obj();
174224
h128 key(sha3(h128(derivedKey, h128::AlignRight)), h128::AlignRight);
175225
h128 iv(params["iv"].get_str());
176-
decryptSymNoAuth(key, iv, &cipherText, ret);
226+
return decryptSymNoAuth(key, iv, &cipherText);
177227
}
178228
else
179229
{
180230
cwarn << "Unknown cipher" << o["cipher"].get_str() << "not supported.";
181231
return bytes();
182232
}
183-
184-
return ret;
185233
}
186234

187-
mutable std::map<h128, Secret> m_ready;
235+
mutable std::map<h128, Secret> m_cached;
188236
std::map<h128, js::mValue> m_keys;
189237
};
190238

191239
int main()
192240
{
193-
cdebug << toHex(pbkdf2("password", asBytes("salt"), 1, 20));
194241
KeyManager keyman;
195-
cdebug << "Secret key for 0498f19a-59db-4d54-ac95-33901b4f1870 is " << keyman.secret(fromUUID("0498f19a-59db-4d54-ac95-33901b4f1870"), [](){ return "foo"; });
242+
auto id = fromUUID("441193ae-a767-f1c3-48ba-dd6610db5ed0");
243+
cdebug << "Secret key for " << toUUID(id) << "is" << keyman.secret(id, [](){ return "bar"; });
196244
}
197245

198246
#elif 0

libdevcore/FixedHash.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ class FixedHash
113113
/// @returns an abridged version of the hash as a user-readable hex string.
114114
std::string abridged() const { return toHex(ref().cropped(0, 4)) + "\342\200\246"; }
115115

116+
/// @returns an abridged version of the hash as a user-readable hex string.
117+
std::string hex() const { return toHex(ref()); }
118+
116119
/// @returns a mutable byte vector_ref to the object's data.
117120
bytesRef ref() { return bytesRef(m_data.data(), N); }
118121

libdevcrypto/Common.cpp

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -112,51 +112,47 @@ bool dev::decryptSym(Secret const& _k, bytesConstRef _cipher, bytes& o_plain)
112112
return decrypt(_k, _cipher, o_plain);
113113
}
114114

115-
h128 dev::encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher)
115+
std::pair<bytes, h128> dev::encryptSymNoAuth(h128 const& _k, bytesConstRef _plain)
116116
{
117117
h128 iv(Nonce::get());
118-
return encryptSymNoAuth(_k, _plain, o_cipher, iv);
118+
return make_pair(encryptSymNoAuth(_k, iv, _plain), iv);
119119
}
120120

121-
h128 dev::encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher, h128 const& _iv)
121+
bytes dev::encryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _plain)
122122
{
123-
o_cipher.resize(_plain.size());
124-
125123
const int c_aesKeyLen = 16;
126124
SecByteBlock key(_k.data(), c_aesKeyLen);
127125
try
128126
{
129127
CTR_Mode<AES>::Encryption e;
130128
e.SetKeyWithIV(key, key.size(), _iv.data());
131-
e.ProcessData(o_cipher.data(), _plain.data(), _plain.size());
132-
return _iv;
129+
bytes ret(_plain.size());
130+
e.ProcessData(ret.data(), _plain.data(), _plain.size());
131+
return ret;
133132
}
134133
catch (CryptoPP::Exception& _e)
135134
{
136135
cerr << _e.what() << endl;
137-
o_cipher.resize(0);
138-
return h128();
136+
return bytes();
139137
}
140138
}
141139

142-
bool dev::decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher, bytes& o_plaintext)
140+
bytes dev::decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher)
143141
{
144-
o_plaintext.resize(_cipher.size());
145-
146142
const size_t c_aesKeyLen = 16;
147143
SecByteBlock key(_k.data(), c_aesKeyLen);
148144
try
149145
{
150146
CTR_Mode<AES>::Decryption d;
151147
d.SetKeyWithIV(key, key.size(), _iv.data());
152-
d.ProcessData(o_plaintext.data(), _cipher.data(), _cipher.size());
153-
return true;
148+
bytes ret(_cipher.size());
149+
d.ProcessData(ret.data(), _cipher.data(), _cipher.size());
150+
return ret;
154151
}
155152
catch (CryptoPP::Exception& _e)
156153
{
157154
cerr << _e.what() << endl;
158-
o_plaintext.resize(0);
159-
return false;
155+
return bytes();
160156
}
161157
}
162158

libdevcrypto/Common.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,13 @@ void encryptECIES(Public const& _k, bytesConstRef _plain, bytes& o_cipher);
103103
bool decryptECIES(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext);
104104

105105
/// Encrypts payload with random IV/ctr using AES128-CTR.
106-
h128 encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher);
106+
std::pair<bytes, h128> encryptSymNoAuth(h128 const& _k, bytesConstRef _plain);
107107

108108
/// Encrypts payload with specified IV/ctr using AES128-CTR.
109-
h128 encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher, h128 const& _iv);
110-
109+
bytes encryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _plain);
110+
111111
/// Decrypts payload with specified IV/ctr using AES128-CTR.
112-
bool decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher, bytes& o_plaintext);
112+
bytes decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher);
113113

114114
/// Recovers Public key from signed message hash.
115115
Public recover(Signature const& _sig, h256 const& _hash);

libdevcrypto/CryptoPP.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ void Secp256k1::encryptECIES(Public const& _k, bytes& io_cipher)
7878
bytes mKey(32);
7979
ctx.Final(mKey.data());
8080

81-
bytes cipherText;
82-
encryptSymNoAuth(h128(eKey), bytesConstRef(&io_cipher), cipherText, h128());
81+
bytes cipherText = encryptSymNoAuth(h128(eKey), h128(), bytesConstRef(&io_cipher));
8382
if (cipherText.empty())
8483
return;
8584

@@ -139,7 +138,7 @@ bool Secp256k1::decryptECIES(Secret const& _k, bytes& io_text)
139138
if (mac[i] != msgMac[i])
140139
return false;
141140

142-
decryptSymNoAuth(h128(eKey), iv, cipherNoIV, plain);
141+
plain = decryptSymNoAuth(h128(eKey), iv, cipherNoIV);
143142
io_text.resize(plain.size());
144143
io_text.swap(plain);
145144

test/libdevcrypto/crypto.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -593,15 +593,14 @@ BOOST_AUTO_TEST_CASE(ecies_aes128_ctr_unaligned)
593593
// TESTING: send encrypt magic sequence
594594
bytes magic {0x22,0x40,0x08,0x91};
595595
bytes magicCipherAndMac;
596-
encryptSymNoAuth(encryptK, &magic, magicCipherAndMac, h128());
596+
magicCipherAndMac = encryptSymNoAuth(encryptK, h128(), &magic);
597597

598598
magicCipherAndMac.resize(magicCipherAndMac.size() + 32);
599599
sha3mac(egressMac.ref(), &magic, egressMac.ref());
600600
egressMac.ref().copyTo(bytesRef(&magicCipherAndMac).cropped(magicCipherAndMac.size() - 32, 32));
601601

602-
bytes plaintext;
603602
bytesConstRef cipher(&magicCipherAndMac[0], magicCipherAndMac.size() - 32);
604-
decryptSymNoAuth(encryptK, h128(), cipher, plaintext);
603+
bytes plaintext = decryptSymNoAuth(encryptK, h128(), cipher);
605604

606605
plaintext.resize(magic.size());
607606
BOOST_REQUIRE(plaintext.size() > 0);
@@ -615,10 +614,10 @@ BOOST_AUTO_TEST_CASE(ecies_aes128_ctr)
615614
bytesConstRef msg((byte*)m.data(), m.size());
616615

617616
bytes ciphertext;
618-
auto iv = encryptSymNoAuth(k, msg, ciphertext);
617+
h128 iv;
618+
tie(ciphertext, iv) = encryptSymNoAuth(k, msg);
619619

620-
bytes plaintext;
621-
decryptSymNoAuth(k, iv, &ciphertext, plaintext);
620+
bytes plaintext = decryptSymNoAuth(k, iv, &ciphertext);
622621
BOOST_REQUIRE_EQUAL(asString(plaintext), m);
623622
}
624623

0 commit comments

Comments
 (0)