Browse Source

Basic key manager.

cl-refactor
Gav Wood 10 years ago
parent
commit
cd64adc541
  1. 86
      exp/main.cpp
  2. 3
      libdevcore/FixedHash.h
  3. 28
      libdevcrypto/Common.cpp
  4. 6
      libdevcrypto/Common.h
  5. 5
      libdevcrypto/CryptoPP.cpp
  6. 11
      test/libdevcrypto/crypto.cpp

86
exp/main.cpp

@ -65,6 +65,7 @@ namespace fs = boost::filesystem;
#if 1 #if 1
inline h128 fromUUID(std::string const& _uuid) { return h128(boost::replace_all_copy(_uuid, "-", "")); } inline h128 fromUUID(std::string const& _uuid) { return h128(boost::replace_all_copy(_uuid, "-", "")); }
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; }
class KeyManager: public Worker class KeyManager: public Worker
{ {
@ -74,31 +75,48 @@ public:
Secret secret(h128 const& _uuid, function<std::string()> const& _pass) Secret secret(h128 const& _uuid, function<std::string()> const& _pass)
{ {
auto rit = m_ready.find(_uuid); auto rit = m_cached.find(_uuid);
if (rit != m_ready.end()) if (rit != m_cached.end())
return rit->second; return rit->second;
auto it = m_keys.find(_uuid); auto it = m_keys.find(_uuid);
if (it == m_keys.end()) if (it == m_keys.end())
return Secret(); return Secret();
Secret ret(decrypt(it->second, _pass())); Secret ret(decrypt(it->second, _pass()));
if (ret) if (ret)
m_ready[_uuid] = ret; m_cached[_uuid] = ret;
return ret; return ret;
} }
h128 create(std::string const& _pass) h128 import(Secret const& _s, std::string const& _pass)
{ {
auto s = Secret::random(); h128 r(sha3(_s));
h128 r(sha3(s)); m_cached[r] = _s;
m_ready[r] = s; m_keys[r] = encrypt(_s.asBytes(), _pass);
m_keys[r] = encrypt(s.asBytes(), _pass); writeKeys();
return r; return r;
} }
h128 create(std::string const& _pass)
{
return import(Secret::random(), _pass);
}
void clearCache() const { m_cached.clear(); }
private: private:
void writeKeys(std::string const& _keysPath = getDataDir("web3") + "/keys") void writeKeys(std::string const& _keysPath = getDataDir("web3") + "/keys")
{ {
(void)_keysPath; fs::path p(_keysPath);
boost::filesystem::create_directories(p);
for (auto const& k: m_keys)
{
std::string uuid = toUUID(k.first);
js::mObject v;
v["crypto"] = k.second;
v["id"] = uuid;
v["version"] = 2;
writeFile((p / uuid).string() + ".json", js::write_string(js::mValue(v), true));
}
} }
void readKeys(std::string const& _keysPath = getDataDir("web3") + "/keys") void readKeys(std::string const& _keysPath = getDataDir("web3") + "/keys")
@ -126,9 +144,42 @@ private:
static js::mValue encrypt(bytes const& _v, std::string const& _pass) static js::mValue encrypt(bytes const& _v, std::string const& _pass)
{ {
(void)_v; js::mObject ret;
(void)_pass;
return js::mValue(); // KDF info
unsigned dklen = 16;
unsigned iterations = 262144;
bytes salt = h256::random().asBytes();
ret["kdf"] = "pbkdf2";
{
js::mObject params;
params["prf"] = "hmac-sha256";
params["c"] = (int)iterations;
params["salt"] = toHex(salt);
params["dklen"] = (int)dklen;
ret["kdfparams"] = params;
}
bytes derivedKey = pbkdf2(_pass, salt, iterations, dklen);
// cipher info
ret["cipher"] = "aes-128-cbc";
h128 key(sha3(h128(derivedKey, h128::AlignRight)), h128::AlignRight);
h128 iv = h128::random();
{
js::mObject params;
params["iv"] = toHex(iv.ref());
ret["cipherparams"] = params;
}
// cipher text
bytes cipherText = encryptSymNoAuth(key, iv, &_v);
ret["ciphertext"] = toHex(cipherText);
// and mac.
h256 mac = sha3(bytesConstRef(&derivedKey).cropped(derivedKey.size() - 16).toBytes() + cipherText);
ret["mac"] = toHex(mac.ref());
return ret;
} }
static bytes decrypt(js::mValue const& _v, std::string const& _pass) static bytes decrypt(js::mValue const& _v, std::string const& _pass)
@ -167,32 +218,29 @@ private:
} }
// decrypt // decrypt
bytes ret;
if (o["cipher"].get_str() == "aes-128-cbc") if (o["cipher"].get_str() == "aes-128-cbc")
{ {
auto params = o["cipherparams"].get_obj(); auto params = o["cipherparams"].get_obj();
h128 key(sha3(h128(derivedKey, h128::AlignRight)), h128::AlignRight); h128 key(sha3(h128(derivedKey, h128::AlignRight)), h128::AlignRight);
h128 iv(params["iv"].get_str()); h128 iv(params["iv"].get_str());
decryptSymNoAuth(key, iv, &cipherText, ret); return decryptSymNoAuth(key, iv, &cipherText);
} }
else else
{ {
cwarn << "Unknown cipher" << o["cipher"].get_str() << "not supported."; cwarn << "Unknown cipher" << o["cipher"].get_str() << "not supported.";
return bytes(); return bytes();
} }
return ret;
} }
mutable std::map<h128, Secret> m_ready; mutable std::map<h128, Secret> m_cached;
std::map<h128, js::mValue> m_keys; std::map<h128, js::mValue> m_keys;
}; };
int main() int main()
{ {
cdebug << toHex(pbkdf2("password", asBytes("salt"), 1, 20));
KeyManager keyman; KeyManager keyman;
cdebug << "Secret key for 0498f19a-59db-4d54-ac95-33901b4f1870 is " << keyman.secret(fromUUID("0498f19a-59db-4d54-ac95-33901b4f1870"), [](){ return "foo"; }); auto id = fromUUID("441193ae-a767-f1c3-48ba-dd6610db5ed0");
cdebug << "Secret key for " << toUUID(id) << "is" << keyman.secret(id, [](){ return "bar"; });
} }
#elif 0 #elif 0

3
libdevcore/FixedHash.h

@ -113,6 +113,9 @@ public:
/// @returns an abridged version of the hash as a user-readable hex string. /// @returns an abridged version of the hash as a user-readable hex string.
std::string abridged() const { return toHex(ref().cropped(0, 4)) + "\342\200\246"; } std::string abridged() const { return toHex(ref().cropped(0, 4)) + "\342\200\246"; }
/// @returns an abridged version of the hash as a user-readable hex string.
std::string hex() const { return toHex(ref()); }
/// @returns a mutable byte vector_ref to the object's data. /// @returns a mutable byte vector_ref to the object's data.
bytesRef ref() { return bytesRef(m_data.data(), N); } bytesRef ref() { return bytesRef(m_data.data(), N); }

28
libdevcrypto/Common.cpp

@ -112,51 +112,47 @@ bool dev::decryptSym(Secret const& _k, bytesConstRef _cipher, bytes& o_plain)
return decrypt(_k, _cipher, o_plain); return decrypt(_k, _cipher, o_plain);
} }
h128 dev::encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher) std::pair<bytes, h128> dev::encryptSymNoAuth(h128 const& _k, bytesConstRef _plain)
{ {
h128 iv(Nonce::get()); h128 iv(Nonce::get());
return encryptSymNoAuth(_k, _plain, o_cipher, iv); return make_pair(encryptSymNoAuth(_k, iv, _plain), iv);
} }
h128 dev::encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher, h128 const& _iv) bytes dev::encryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _plain)
{ {
o_cipher.resize(_plain.size());
const int c_aesKeyLen = 16; const int c_aesKeyLen = 16;
SecByteBlock key(_k.data(), c_aesKeyLen); SecByteBlock key(_k.data(), c_aesKeyLen);
try try
{ {
CTR_Mode<AES>::Encryption e; CTR_Mode<AES>::Encryption e;
e.SetKeyWithIV(key, key.size(), _iv.data()); e.SetKeyWithIV(key, key.size(), _iv.data());
e.ProcessData(o_cipher.data(), _plain.data(), _plain.size()); bytes ret(_plain.size());
return _iv; e.ProcessData(ret.data(), _plain.data(), _plain.size());
return ret;
} }
catch (CryptoPP::Exception& _e) catch (CryptoPP::Exception& _e)
{ {
cerr << _e.what() << endl; cerr << _e.what() << endl;
o_cipher.resize(0); return bytes();
return h128();
} }
} }
bool dev::decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher, bytes& o_plaintext) bytes dev::decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher)
{ {
o_plaintext.resize(_cipher.size());
const size_t c_aesKeyLen = 16; const size_t c_aesKeyLen = 16;
SecByteBlock key(_k.data(), c_aesKeyLen); SecByteBlock key(_k.data(), c_aesKeyLen);
try try
{ {
CTR_Mode<AES>::Decryption d; CTR_Mode<AES>::Decryption d;
d.SetKeyWithIV(key, key.size(), _iv.data()); d.SetKeyWithIV(key, key.size(), _iv.data());
d.ProcessData(o_plaintext.data(), _cipher.data(), _cipher.size()); bytes ret(_cipher.size());
return true; d.ProcessData(ret.data(), _cipher.data(), _cipher.size());
return ret;
} }
catch (CryptoPP::Exception& _e) catch (CryptoPP::Exception& _e)
{ {
cerr << _e.what() << endl; cerr << _e.what() << endl;
o_plaintext.resize(0); return bytes();
return false;
} }
} }

6
libdevcrypto/Common.h

@ -103,13 +103,13 @@ void encryptECIES(Public const& _k, bytesConstRef _plain, bytes& o_cipher);
bool decryptECIES(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext); bool decryptECIES(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext);
/// Encrypts payload with random IV/ctr using AES128-CTR. /// Encrypts payload with random IV/ctr using AES128-CTR.
h128 encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher); std::pair<bytes, h128> encryptSymNoAuth(h128 const& _k, bytesConstRef _plain);
/// Encrypts payload with specified IV/ctr using AES128-CTR. /// Encrypts payload with specified IV/ctr using AES128-CTR.
h128 encryptSymNoAuth(h128 const& _k, bytesConstRef _plain, bytes& o_cipher, h128 const& _iv); bytes encryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _plain);
/// Decrypts payload with specified IV/ctr using AES128-CTR. /// Decrypts payload with specified IV/ctr using AES128-CTR.
bool decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher, bytes& o_plaintext); bytes decryptSymNoAuth(h128 const& _k, h128 const& _iv, bytesConstRef _cipher);
/// Recovers Public key from signed message hash. /// Recovers Public key from signed message hash.
Public recover(Signature const& _sig, h256 const& _hash); Public recover(Signature const& _sig, h256 const& _hash);

5
libdevcrypto/CryptoPP.cpp

@ -78,8 +78,7 @@ void Secp256k1::encryptECIES(Public const& _k, bytes& io_cipher)
bytes mKey(32); bytes mKey(32);
ctx.Final(mKey.data()); ctx.Final(mKey.data());
bytes cipherText; bytes cipherText = encryptSymNoAuth(h128(eKey), h128(), bytesConstRef(&io_cipher));
encryptSymNoAuth(h128(eKey), bytesConstRef(&io_cipher), cipherText, h128());
if (cipherText.empty()) if (cipherText.empty())
return; return;
@ -139,7 +138,7 @@ bool Secp256k1::decryptECIES(Secret const& _k, bytes& io_text)
if (mac[i] != msgMac[i]) if (mac[i] != msgMac[i])
return false; return false;
decryptSymNoAuth(h128(eKey), iv, cipherNoIV, plain); plain = decryptSymNoAuth(h128(eKey), iv, cipherNoIV);
io_text.resize(plain.size()); io_text.resize(plain.size());
io_text.swap(plain); io_text.swap(plain);

11
test/libdevcrypto/crypto.cpp

@ -593,15 +593,14 @@ BOOST_AUTO_TEST_CASE(ecies_aes128_ctr_unaligned)
// TESTING: send encrypt magic sequence // TESTING: send encrypt magic sequence
bytes magic {0x22,0x40,0x08,0x91}; bytes magic {0x22,0x40,0x08,0x91};
bytes magicCipherAndMac; bytes magicCipherAndMac;
encryptSymNoAuth(encryptK, &magic, magicCipherAndMac, h128()); magicCipherAndMac = encryptSymNoAuth(encryptK, h128(), &magic);
magicCipherAndMac.resize(magicCipherAndMac.size() + 32); magicCipherAndMac.resize(magicCipherAndMac.size() + 32);
sha3mac(egressMac.ref(), &magic, egressMac.ref()); sha3mac(egressMac.ref(), &magic, egressMac.ref());
egressMac.ref().copyTo(bytesRef(&magicCipherAndMac).cropped(magicCipherAndMac.size() - 32, 32)); egressMac.ref().copyTo(bytesRef(&magicCipherAndMac).cropped(magicCipherAndMac.size() - 32, 32));
bytes plaintext;
bytesConstRef cipher(&magicCipherAndMac[0], magicCipherAndMac.size() - 32); bytesConstRef cipher(&magicCipherAndMac[0], magicCipherAndMac.size() - 32);
decryptSymNoAuth(encryptK, h128(), cipher, plaintext); bytes plaintext = decryptSymNoAuth(encryptK, h128(), cipher);
plaintext.resize(magic.size()); plaintext.resize(magic.size());
BOOST_REQUIRE(plaintext.size() > 0); BOOST_REQUIRE(plaintext.size() > 0);
@ -615,10 +614,10 @@ BOOST_AUTO_TEST_CASE(ecies_aes128_ctr)
bytesConstRef msg((byte*)m.data(), m.size()); bytesConstRef msg((byte*)m.data(), m.size());
bytes ciphertext; bytes ciphertext;
auto iv = encryptSymNoAuth(k, msg, ciphertext); h128 iv;
tie(ciphertext, iv) = encryptSymNoAuth(k, msg);
bytes plaintext; bytes plaintext = decryptSymNoAuth(k, iv, &ciphertext);
decryptSymNoAuth(k, iv, &ciphertext, plaintext);
BOOST_REQUIRE_EQUAL(asString(plaintext), m); BOOST_REQUIRE_EQUAL(asString(plaintext), m);
} }

Loading…
Cancel
Save