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. 8
      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
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
{
@ -74,31 +75,48 @@ public:
Secret secret(h128 const& _uuid, function<std::string()> const& _pass)
{
auto rit = m_ready.find(_uuid);
if (rit != m_ready.end())
auto rit = m_cached.find(_uuid);
if (rit != m_cached.end())
return rit->second;
auto it = m_keys.find(_uuid);
if (it == m_keys.end())
return Secret();
Secret ret(decrypt(it->second, _pass()));
if (ret)
m_ready[_uuid] = ret;
m_cached[_uuid] = 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));
m_ready[r] = s;
m_keys[r] = encrypt(s.asBytes(), _pass);
h128 r(sha3(_s));
m_cached[r] = _s;
m_keys[r] = encrypt(_s.asBytes(), _pass);
writeKeys();
return r;
}
h128 create(std::string const& _pass)
{
return import(Secret::random(), _pass);
}
void clearCache() const { m_cached.clear(); }
private:
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")
@ -126,9 +144,42 @@ private:
static js::mValue encrypt(bytes const& _v, std::string const& _pass)
{
(void)_v;
(void)_pass;
return js::mValue();
js::mObject ret;
// 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)
@ -167,32 +218,29 @@ private:
}
// decrypt
bytes ret;
if (o["cipher"].get_str() == "aes-128-cbc")
{
auto params = o["cipherparams"].get_obj();
h128 key(sha3(h128(derivedKey, h128::AlignRight)), h128::AlignRight);
h128 iv(params["iv"].get_str());
decryptSymNoAuth(key, iv, &cipherText, ret);
return decryptSymNoAuth(key, iv, &cipherText);
}
else
{
cwarn << "Unknown cipher" << o["cipher"].get_str() << "not supported.";
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;
};
int main()
{
cdebug << toHex(pbkdf2("password", asBytes("salt"), 1, 20));
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

3
libdevcore/FixedHash.h

@ -113,6 +113,9 @@ public:
/// @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"; }
/// @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.
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);
}
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());
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;
SecByteBlock key(_k.data(), c_aesKeyLen);
try
{
CTR_Mode<AES>::Encryption e;
e.SetKeyWithIV(key, key.size(), _iv.data());
e.ProcessData(o_cipher.data(), _plain.data(), _plain.size());
return _iv;
bytes ret(_plain.size());
e.ProcessData(ret.data(), _plain.data(), _plain.size());
return ret;
}
catch (CryptoPP::Exception& _e)
{
cerr << _e.what() << endl;
o_cipher.resize(0);
return h128();
return bytes();
}
}
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;
SecByteBlock key(_k.data(), c_aesKeyLen);
try
{
CTR_Mode<AES>::Decryption d;
d.SetKeyWithIV(key, key.size(), _iv.data());
d.ProcessData(o_plaintext.data(), _cipher.data(), _cipher.size());
return true;
bytes ret(_cipher.size());
d.ProcessData(ret.data(), _cipher.data(), _cipher.size());
return ret;
}
catch (CryptoPP::Exception& _e)
{
cerr << _e.what() << endl;
o_plaintext.resize(0);
return false;
return bytes();
}
}

8
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);
/// 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.
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.
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.
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);
ctx.Final(mKey.data());
bytes cipherText;
encryptSymNoAuth(h128(eKey), bytesConstRef(&io_cipher), cipherText, h128());
bytes cipherText = encryptSymNoAuth(h128(eKey), h128(), bytesConstRef(&io_cipher));
if (cipherText.empty())
return;
@ -139,7 +138,7 @@ bool Secp256k1::decryptECIES(Secret const& _k, bytes& io_text)
if (mac[i] != msgMac[i])
return false;
decryptSymNoAuth(h128(eKey), iv, cipherNoIV, plain);
plain = decryptSymNoAuth(h128(eKey), iv, cipherNoIV);
io_text.resize(plain.size());
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
bytes magic {0x22,0x40,0x08,0x91};
bytes magicCipherAndMac;
encryptSymNoAuth(encryptK, &magic, magicCipherAndMac, h128());
magicCipherAndMac = encryptSymNoAuth(encryptK, h128(), &magic);
magicCipherAndMac.resize(magicCipherAndMac.size() + 32);
sha3mac(egressMac.ref(), &magic, egressMac.ref());
egressMac.ref().copyTo(bytesRef(&magicCipherAndMac).cropped(magicCipherAndMac.size() - 32, 32));
bytes plaintext;
bytesConstRef cipher(&magicCipherAndMac[0], magicCipherAndMac.size() - 32);
decryptSymNoAuth(encryptK, h128(), cipher, plaintext);
bytes plaintext = decryptSymNoAuth(encryptK, h128(), cipher);
plaintext.resize(magic.size());
BOOST_REQUIRE(plaintext.size() > 0);
@ -615,10 +614,10 @@ BOOST_AUTO_TEST_CASE(ecies_aes128_ctr)
bytesConstRef msg((byte*)m.data(), m.size());
bytes ciphertext;
auto iv = encryptSymNoAuth(k, msg, ciphertext);
h128 iv;
tie(ciphertext, iv) = encryptSymNoAuth(k, msg);
bytes plaintext;
decryptSymNoAuth(k, iv, &ciphertext, plaintext);
bytes plaintext = decryptSymNoAuth(k, iv, &ciphertext);
BOOST_REQUIRE_EQUAL(asString(plaintext), m);
}

Loading…
Cancel
Save