# # # patch "database_check.cc" # from [927ecbc5cb205246a6cd959005031b122928d20c] # to [e7462b630cad47cf8e0c263b293b7228d8e16392] # # patch "key_store.cc" # from [f938c386df63885d1ccb75fb6e57c91e0172b24c] # to [122f910da775017a2d086805c4e460b68b1a2fb0] # # patch "key_store.hh" # from [a5ab423522918bb9c0cc828e6658b2c88ef88947] # to [c23fc37613716cae27681652cd917359280c2a61] # # patch "keys.cc" # from [dd5a511fcd817f152489a4892c1c6cbf1b2232e2] # to [b818f882c867150822c9826b8b78e33adee46541] # # patch "keys.hh" # from [784b404e0e233bcf92b96aac0ebdde82b60fc3b3] # to [d4c34c10f4c29dbdbc6b7471011ee57aa438fb5c] # # patch "rcs_import.cc" # from [2bdf86d7e0951c686cd68fcf60d831ee5ea2c363] # to [0f51bc2b23658e9ef7477a1ba9c7f4f8eff691a5] # # patch "ssh_agent.cc" # from [b16db7de9029559a0013c95dc49b985e12fceeeb] # to [dcc8cefe23e376c74df2eb10011f874802a609d6] # ============================================================ --- database_check.cc 927ecbc5cb205246a6cd959005031b122928d20c +++ database_check.cc e7462b630cad47cf8e0c263b293b7228d8e16392 @@ -13,7 +13,6 @@ #include "constants.hh" #include "database.hh" -#include "keys.hh" #include "revision.hh" #include "ui.hh" #include "vocab.hh" ============================================================ --- key_store.cc f938c386df63885d1ccb75fb6e57c91e0172b24c +++ key_store.cc 122f910da775017a2d086805c4e460b68b1a2fb0 @@ -10,6 +10,7 @@ #include "transforms.hh" #include "constants.hh" #include "ssh_agent.hh" +#include "safe_map.hh" #include "botan/botan.h" #include "botan/rsa.h" @@ -37,20 +38,17 @@ using Botan::Pipe; using Botan::PK_Signer; using Botan::Pipe; -class key_store_state +struct key_store_state { - friend class key_store; - system_path key_dir; bool have_read; app_state & app; map keys; map, rsa_keypair_id> hashes; - // These are used to cache signers (if the hook allows). - map, - shared_ptr > > signers; + // These are used to cache keys and signers (if the hook allows). + map > privkey_cache; + map > signer_cache; // Initialized when first required. scoped_ptr agent; @@ -59,11 +57,15 @@ class key_store_state : key_dir(app.opts.conf_dir / "keys"), have_read(false), app(app) {} -public: + // internal methods + void get_key_file(rsa_keypair_id const & ident, system_path & file); + void write_key(rsa_keypair_id const & ident, keypair const & kp); + void maybe_read_key_dir(); + shared_ptr decrypt_private_key(rsa_keypair_id const & id, + bool force_from_user = false); + // just like put_key_pair except that the key is _not_ written to disk. - // primarily for internal use in reading keys back from disk. public so - // keyreader (which is in an anonymous namespace and so can't be friended) - // can get at it. + // for internal use in reading keys back from disk. bool put_key_pair_memory(rsa_keypair_id const & ident, keypair const & kp); @@ -74,16 +76,25 @@ public: agent.reset(new ssh_agent); return *agent; } + + // duplicates of key_store interfaces for use by key_store_state methods + // and the keyreader. + bool maybe_get_key_pair(rsa_keypair_id const & ident, + keypair & kp); + bool put_key_pair(rsa_keypair_id const & ident, + keypair const & kp); + void migrate_old_key_pair(rsa_keypair_id const & id, + base64 const & old_priv, + base64 const & pub); }; namespace { struct keyreader : public packet_consumer { - key_store & ks; key_store_state & kss; - keyreader(key_store & ks, key_store_state & kss): ks(ks), kss(kss) {} + keyreader(key_store_state & kss): kss(kss) {} virtual void consume_file_data(file_id const & ident, file_data const & dat) {E(false, F("Extraneous data in key store."));} @@ -121,7 +132,7 @@ namespace W(F("converting old-format private key '%s'") % ident); base64 dummy; - ks.migrate_old_key_pair(ident, k, dummy); + kss.migrate_old_key_pair(ident, k, dummy); L(FL("successfully read key pair '%s' from key store") % ident); } @@ -138,7 +149,16 @@ key_store::set_key_dir(system_path const void key_store::set_key_dir(system_path const & kd) { + if (s->key_dir == kd) + return; + + // Changing the key directory wipes the internal cache of keys. s->key_dir = kd; + s->have_read = false; + s->keys.clear(); + s->hashes.clear(); + s->signer_cache.clear(); + s->privkey_cache.clear(); } system_path const & @@ -148,46 +168,41 @@ void } void -key_store::read_key_dir() +key_store_state::maybe_read_key_dir() { + if (have_read) + return; + have_read = true; + vector key_files, dirs; - if (directory_exists(s->key_dir)) + if (directory_exists(key_dir)) { - L(FL("reading key dir '%s'") % s->key_dir); - read_directory(s->key_dir, key_files, dirs); + L(FL("reading key dir '%s'") % key_dir); + read_directory(key_dir, key_files, dirs); } else { - L(FL("key dir '%s' does not exist") % s->key_dir); + L(FL("key dir '%s' does not exist") % key_dir); return; } - keyreader kr(*this, *s); + keyreader kr(*this); for (vector::const_iterator i = key_files.begin(); i != key_files.end(); ++i) { L(FL("reading keys from file '%s'") % (*i)); data dat; - read_data(s->key_dir / *i, dat); + read_data(key_dir / *i, dat); istringstream is(dat()); read_packets(is, kr); } } void -key_store::maybe_read_key_dir() -{ - if (s->have_read) - return; - s->have_read = true; - read_key_dir(); -} - -void key_store::get_key_ids(globish const & pattern, vector & priv) { - maybe_read_key_dir(); + s->maybe_read_key_dir(); priv.clear(); for (map::const_iterator i = s->keys.begin(); i != s->keys.end(); ++i) @@ -198,7 +213,7 @@ key_store::get_key_ids(vector & priv) { - maybe_read_key_dir(); + s->maybe_read_key_dir(); priv.clear(); for (map::const_iterator i = s->keys.begin(); i != s->keys.end(); ++i) @@ -208,22 +223,29 @@ key_store::key_pair_exists(rsa_keypair_i bool key_store::key_pair_exists(rsa_keypair_id const & ident) { - maybe_read_key_dir(); + s->maybe_read_key_dir(); return s->keys.find(ident) != s->keys.end(); } bool -key_store::maybe_get_key_pair(rsa_keypair_id const & ident, - keypair & kp) +key_store_state::maybe_get_key_pair(rsa_keypair_id const & ident, + keypair & kp) { maybe_read_key_dir(); - map::const_iterator i = s->keys.find(ident); - if (i == s->keys.end()) + map::const_iterator i = keys.find(ident); + if (i == keys.end()) return false; kp = i->second; return true; } +bool +key_store::maybe_get_key_pair(rsa_keypair_id const & ident, + keypair & kp) +{ + return s->maybe_get_key_pair(ident, kp); +} + void key_store::get_key_pair(rsa_keypair_id const & ident, keypair & kp) @@ -237,7 +259,7 @@ key_store::maybe_get_key_pair(hexenc rsa_keypair_id & keyid, keypair & kp) { - maybe_read_key_dir(); + s->maybe_read_key_dir(); map, rsa_keypair_id>::const_iterator hi = s->hashes.find(hash); if (hi == s->hashes.end()) return false; @@ -251,8 +273,8 @@ void } void -key_store::get_key_file(rsa_keypair_id const & ident, - system_path & file) +key_store_state::get_key_file(rsa_keypair_id const & ident, + system_path & file) { // filename is the keypair id, except that some characters can't be put in // filenames (especially on windows). @@ -261,38 +283,45 @@ key_store::get_key_file(rsa_keypair_id c if (leaf.at(i) == '+') leaf.at(i) = '_'; - file = s->key_dir / path_component(leaf); + file = key_dir / path_component(leaf); } void -key_store::write_key(rsa_keypair_id const & ident) +key_store_state::write_key(rsa_keypair_id const & ident, + keypair const & kp) { - keypair kp; - get_key_pair(ident, kp); ostringstream oss; packet_writer pw(oss); pw.consume_key_pair(ident, kp); data dat(oss.str()); + system_path file; get_key_file(ident, file); // Make sure the private key is not readable by anyone other than the user. - L(FL("writing key '%s' to file '%s' in dir '%s'") % ident % file % s->key_dir); - write_data_userprivate(file, dat, s->key_dir); + L(FL("writing key '%s' to file '%s' in dir '%s'") % ident % file % key_dir); + write_data_userprivate(file, dat, key_dir); } bool -key_store::put_key_pair(rsa_keypair_id const & ident, - keypair const & kp) +key_store_state::put_key_pair(rsa_keypair_id const & ident, + keypair const & kp) { maybe_read_key_dir(); - bool newkey = s->put_key_pair_memory(ident, kp); + bool newkey = put_key_pair_memory(ident, kp); if (newkey) - write_key(ident); + write_key(ident, kp); return newkey; } bool +key_store::put_key_pair(rsa_keypair_id const & ident, + keypair const & kp) +{ + return s->put_key_pair(ident, kp); +} + +bool key_store_state::put_key_pair_memory(rsa_keypair_id const & ident, keypair const & kp) { @@ -319,7 +348,7 @@ key_store::delete_key(rsa_keypair_id con void key_store::delete_key(rsa_keypair_id const & ident) { - maybe_read_key_dir(); + s->maybe_read_key_dir(); map::iterator i = s->keys.find(ident); if (i != s->keys.end()) { @@ -329,9 +358,11 @@ key_store::delete_key(rsa_keypair_id con I(j != s->hashes.end()); s->hashes.erase(j); s->keys.erase(i); + s->signer_cache.erase(ident); + s->privkey_cache.erase(ident); } system_path file; - get_key_file(ident, file); + s->get_key_file(ident, file); delete_file(file); } @@ -339,7 +370,90 @@ key_store::delete_key(rsa_keypair_id con // Crypto operations // +shared_ptr +key_store_state::decrypt_private_key(rsa_keypair_id const & id, + bool force_from_user) +{ + rsa_priv_key decoded_key; + + // See if we have this key in the decrypted key cache. + map >::const_iterator + cpk = privkey_cache.find(id); + if (cpk != privkey_cache.end()) + return cpk->second; + + keypair kp; + N(maybe_get_key_pair(id, kp), + F("no key pair '%s' found in key store '%s'") % id % key_dir); + + L(FL("base64-decoding %d-byte private key") % kp.priv().size()); + decode_base64(kp.priv, decoded_key); + + shared_ptr pkcs8_key; + try // with empty passphrase + { + Pipe p; + p.process_msg(decoded_key()); + pkcs8_key.reset(Botan::PKCS8::load_key(p, "")); + } + catch (Botan::Exception & e) + { + L(FL("failed to load key with no passphrase: %s") % e.what()); + + utf8 phrase; + string lua_phrase; + // See whether a lua hook will tell us the passphrase. + if (!force_from_user && app.lua.hook_get_passphrase(id, lua_phrase)) + phrase = utf8(lua_phrase); + else + get_passphrase(phrase, id, false, false); + + int cycles = 1; + for (;;) + try + { + Pipe p; + p.process_msg(decoded_key()); + pkcs8_key.reset(Botan::PKCS8::load_key(p, phrase())); + break; + } + catch (Botan::Exception & e) + { + L(FL("decrypt_private_key: failure %d to load encrypted key: %s") + % cycles % e.what()); + E(cycles <= 3, + F("failed to decrypt old private RSA key, " + "probably incorrect passphrase")); + + get_passphrase(phrase, id, false, false); + cycles++; + continue; + } + } + + I(pkcs8_key); + + shared_ptr priv_key; + priv_key = shared_dynamic_cast(pkcs8_key); + E(priv_key, + F("failed to extract RSA private key from PKCS#8 keypair")); + + // Cache the decrypted key if we're allowed. + if (app.lua.hook_persist_phrase_ok()) + safe_insert(privkey_cache, make_pair(id, priv_key)); + + return priv_key; +} + void +key_store::cache_decrypted_key(const rsa_keypair_id & id) +{ + signing_key = id; + if (s->app.lua.hook_persist_phrase_ok()) + s->decrypt_private_key(id); +} + +void key_store::create_key_pair(database & db, rsa_keypair_id const & id, utf8 const * maybe_passphrase, @@ -417,8 +531,7 @@ key_store::change_key_passphrase(rsa_key { keypair kp; load_key_pair(*this, id, kp); - - shared_ptr priv = get_private_key(*this, id, kp.priv, true); + shared_ptr priv = s->decrypt_private_key(id, true); utf8 new_phrase; get_passphrase(new_phrase, id, true, false); @@ -442,7 +555,7 @@ key_store::decrypt_rsa(rsa_keypair_id co { keypair kp; load_key_pair(*this, id, kp); - shared_ptr priv_key = get_private_key(*this, id, kp.priv); + shared_ptr priv_key = s->decrypt_private_key(id); shared_ptr decryptor(get_pk_decryptor(*priv_key, "EME1(SHA-1)")); @@ -518,16 +631,17 @@ key_store::make_signature(database & db, // you're making a half-dozen certs during a commit or merge or // something. - bool persist_phrase = !s->signers.empty() || hook_persist_phrase_ok(); + bool persist_phrase = (!s->signer_cache.empty() + || s->app.lua.hook_persist_phrase_ok()); shared_ptr signer; shared_ptr priv_key; - if (persist_phrase && s->signers.find(id) != s->signers.end()) - signer = s->signers[id].first; + if (persist_phrase && s->signer_cache.find(id) != s->signer_cache.end()) + signer = s->signer_cache[id]; else { - priv_key = get_private_key(*this, id, key.priv); + priv_key = s->decrypt_private_key(id); if (agent.connected() && opt_ssh_sign != "only" && opt_ssh_sign != "no") { @@ -536,12 +650,11 @@ key_store::make_signature(database & db, } signer = shared_ptr(get_pk_signer(*priv_key, "EMSA3(SHA-1)")); - /* XXX This is ugly. We need to keep the key around as long - * as the signer is around, but the shared_ptr for the key will go - * away after we leave this scope. Hence we store a pair of - * so they both exist. */ + /* If persist_phrase is true, the RSA_PrivateKey object is + cached in s->active_keys and will survive as long as the + PK_Signer object does. */ if (persist_phrase) - s->signers.insert(make_pair(id,make_pair(signer,priv_key))); + s->signer_cache.insert(make_pair(id, signer)); } sig = signer->sign_message(reinterpret_cast(tosign.data()), tosign.size()); @@ -581,10 +694,7 @@ key_store::add_key_to_agent(rsa_keypair_ N(agent.connected(), F("no ssh-agent is available, cannot add key '%s'") % id); - keypair key; - get_key_pair(id, key); - - shared_ptr priv = get_private_key(*this, id, key.priv); + shared_ptr priv = s->decrypt_private_key(id); agent.add_identity(*priv, id()); } @@ -592,9 +702,7 @@ key_store::export_key_for_agent(rsa_keyp key_store::export_key_for_agent(rsa_keypair_id const & id, std::ostream & os) { - keypair key; - get_key_pair(id, key); - shared_ptr priv = get_private_key(*this, id, key.priv); + shared_ptr priv = s->decrypt_private_key(id); utf8 new_phrase; get_passphrase(new_phrase, id, true, false); @@ -616,9 +724,10 @@ void // void -key_store::migrate_old_key_pair(rsa_keypair_id const & id, - base64 const & old_priv, - base64 const & pub) +key_store_state::migrate_old_key_pair + (rsa_keypair_id const & id, + base64 const & old_priv, + base64 const & pub) { keypair kp; SecureVector arc4_key; @@ -628,7 +737,7 @@ key_store::migrate_old_key_pair(rsa_keyp // See whether a lua hook will tell us the passphrase. string lua_phrase; - if (s->app.lua.hook_get_passphrase(id, lua_phrase)) + if (app.lua.hook_get_passphrase(id, lua_phrase)) phrase = utf8(lua_phrase); else get_passphrase(phrase, id, false, false); @@ -698,22 +807,15 @@ key_store::migrate_old_key_pair(rsa_keyp put_key_pair(id, kp); } -// -// Hooks into the application configuration -// - -bool -key_store::hook_get_passphrase(rsa_keypair_id const & k, std::string & phrase) +void +key_store::migrate_old_key_pair + (rsa_keypair_id const & id, + base64 const & old_priv, + base64 const & pub) { - return s->app.lua.hook_get_passphrase(k, phrase); + s->migrate_old_key_pair(id, old_priv, pub); } -bool -key_store::hook_persist_phrase_ok() -{ - return s->app.lua.hook_persist_phrase_ok(); -} - // Local Variables: // mode: C++ // fill-column: 76 ============================================================ --- key_store.hh a5ab423522918bb9c0cc828e6658b2c88ef88947 +++ key_store.hh c23fc37613716cae27681652cd917359280c2a61 @@ -11,18 +11,13 @@ class database; struct globish; class database; -class key_store_state; +struct key_store_state; class key_store { private: boost::scoped_ptr s; - void get_key_file(rsa_keypair_id const & ident, system_path & file); - void write_key(rsa_keypair_id const & ident); - void read_key_dir(); - void maybe_read_key_dir(); - public: rsa_keypair_id signing_key; @@ -55,6 +50,8 @@ public: // Crypto operations + void cache_decrypted_key(rsa_keypair_id const & id); + void create_key_pair(database & db, rsa_keypair_id const & id, utf8 const * maybe_passphrase = NULL, hexenc * maybe_pubhash = NULL, @@ -81,11 +78,6 @@ public: void migrate_old_key_pair(rsa_keypair_id const & id, base64 const & old_priv, base64 const & pub); - - // FIXME: quick hack to make these hooks and options available via - // the key_store context - bool hook_get_passphrase(rsa_keypair_id const & k, std::string & phrase); - bool hook_persist_phrase_ok(); }; // Local Variables: ============================================================ --- keys.cc dd5a511fcd817f152489a4892c1c6cbf1b2232e2 +++ keys.cc b818f882c867150822c9826b8b78e33adee46541 @@ -8,57 +8,25 @@ // PURPOSE. #include "base.hh" -#include -#include -#include -#include +#include -#include -#include - -#include "botan/botan.h" -#include "botan/rsa.h" -#include "botan/keypair.h" -#include "botan/pem.h" - +#include "keys.hh" +#include "sanity.hh" +#include "ui.hh" #include "constants.hh" -#include "keys.hh" -#include "key_store.hh" -#include "lua_hooks.hh" -#include "netio.hh" #include "platform.hh" -#include "safe_map.hh" #include "transforms.hh" #include "simplestring_xform.hh" -#include "sanity.hh" -#include "ui.hh" -#include "cert.hh" #include "charset.hh" -#include "database.hh" +#include "lua_hooks.hh" #include "options.hh" +#include "key_store.hh" +#include "database.hh" -using std::cout; -using std::make_pair; -using std::map; using std::string; using std::vector; +using std::memset; -using boost::scoped_ptr; -using boost::shared_ptr; -using boost::shared_dynamic_cast; - -using Botan::byte; -using Botan::get_cipher; -using Botan::PKCS8_PrivateKey; -using Botan::PK_Decryptor; -using Botan::PK_Encryptor; -using Botan::PK_Signer; -using Botan::Pipe; -using Botan::RSA_PrivateKey; -using Botan::RSA_PublicKey; -using Botan::SecureVector; -using Botan::X509_PublicKey; - // there will probably forever be bugs in this file. it's very // hard to get right, portably and securely. sorry about that. @@ -119,47 +87,6 @@ get_passphrase(utf8 & phrase, memset(pass2, 0, constants::maxpasswd); } -// 'force_from_user' means that we don't use the passphrase cache, and we -// don't use the get_passphrase hook. -static void -get_passphrase(key_store & keys, - utf8 & phrase, - rsa_keypair_id const & keyid, - bool force_from_user) -{ - // we permit the user to relax security here, by caching a passphrase (if - // they permit it) through the life of a program run. this helps when - // you're making a half-dozen certs during a commit or merge or - // something. - bool persist_phrase = keys.hook_persist_phrase_ok(); - static map phrases; - if (!force_from_user && phrases.find(keyid) != phrases.end()) - { - phrase = phrases[keyid]; - return; - } - - string lua_phrase; - if (!force_from_user && keys.hook_get_passphrase(keyid, lua_phrase)) - { - N(!lua_phrase.empty(), - F("got empty passphrase from get_passphrase() hook")); - - // user is being a slob and hooking lua to return his passphrase - phrase = utf8(lua_phrase); - return; - } - - get_passphrase(phrase, keyid, false, false); - - // permit security relaxation. maybe. - if (persist_phrase) - { - phrases.erase(keyid); - safe_insert(phrases, make_pair(keyid, phrase)); - } -} - // Loads a key pair for a given key id, considering it a user error // if that key pair is not available. @@ -214,36 +141,28 @@ get_user_key(rsa_keypair_id & key, key = all_privkeys[0]; } - keys.signing_key = key; - // Ensure that the specified key actually exists. keypair priv_key; load_key_pair(keys, key, priv_key); - // we can only do the steps below if we have a database. - if (!db.database_specified()) - return; - - // If the database doesn't have this public key, add it now; otherwise - // make sure the database and key-store agree on the public key. - if (!db.public_key_exists(key)) - db.put_key(key, priv_key.pub); - else + if (db.database_specified()) { - base64 pub_key; - db.get_key(key, pub_key); - E(keys_match(key, pub_key, key, priv_key.pub), - F("The key '%s' stored in your database does\n" - "not match the version in your local key store!") % key); + // If the database doesn't have this public key, add it now; otherwise + // make sure the database and key-store agree on the public key. + if (!db.public_key_exists(key)) + db.put_key(key, priv_key.pub); + else + { + base64 pub_key; + db.get_key(key, pub_key); + E(keys_match(key, pub_key, key, priv_key.pub), + F("The key '%s' stored in your database does\n" + "not match the version in your local key store!") % key); + } } - // If permitted, decrypt and cache the key now. - if (keys.hook_persist_phrase_ok()) - { - string plaintext("hi maude"); - base64 sig; - keys.make_signature(db, key, plaintext, sig); - } + // Decrypt and cache the key now. + keys.cache_decrypted_key(key); } // As above, but does not report which key has been selected; for use when @@ -256,67 +175,6 @@ cache_user_key(options const & opts, lua get_user_key(key, opts, lua, keys, db); } -// ask for passphrase then decrypt a private key. -shared_ptr -get_private_key(key_store & keys, - rsa_keypair_id const & id, - base64< rsa_priv_key > const & priv, - bool force_from_user) -{ - rsa_priv_key decoded_key; - utf8 phrase; - bool force = force_from_user; - - L(FL("base64-decoding %d-byte private key") % priv().size()); - decode_base64(priv, decoded_key); - shared_ptr pkcs8_key; - try //with empty passphrase - { - Pipe p; - p.process_msg(decoded_key()); - pkcs8_key = shared_ptr(Botan::PKCS8::load_key(p, phrase())); - } - catch (...) - { - L(FL("failed to decrypt key with no passphrase")); - } - if (!pkcs8_key) - { - for (int i = 0; i < 3; ++i) - { - get_passphrase(keys, phrase, id, force); - L(FL("have %d-byte encrypted private key") % decoded_key().size()); - - try - { - Pipe p; - p.process_msg(decoded_key()); - pkcs8_key = shared_ptr(Botan::PKCS8::load_key(p, phrase())); - break; - } - catch (...) - { - if (i >= 2) - throw informative_failure("failed to decrypt private RSA key, " - "probably incorrect passphrase"); - // don't use the cached bad one next time - force = true; - continue; - } - } - } - if (pkcs8_key) - { - shared_ptr priv_key; - priv_key = shared_dynamic_cast(pkcs8_key); - if (!priv_key) - throw informative_failure("Failed to get RSA signing key"); - - return priv_key; - } - I(false); -} - void key_hash_code(rsa_keypair_id const & ident, base64 const & pub, ============================================================ --- keys.hh 784b404e0e233bcf92b96aac0ebdde82b60fc3b3 +++ keys.hh d4c34c10f4c29dbdbc6b7471011ee57aa438fb5c @@ -11,13 +11,11 @@ // PURPOSE. #include "vocab.hh" -#include struct options; class lua_hooks; class key_store; class database; -namespace Botan { class RSA_PrivateKey; } // keys.{hh,cc} does all the "delicate" crypto (meaning: that which needs // to read passphrases and manipulate raw, decrypted private keys). it @@ -44,24 +42,6 @@ void load_key_pair(key_store & keys, rsa_keypair_id const & id, keypair & kp); -void encrypt_rsa(key_store & keys, - rsa_keypair_id const & id, - base64 & pub, - std::string const & plaintext, - rsa_oaep_sha_data & ciphertext); - -void decrypt_rsa(key_store & keys, - rsa_keypair_id const & id, - base64< rsa_priv_key > const & priv, - rsa_oaep_sha_data const & ciphertext, - std::string & plaintext); - -boost::shared_ptr -get_private_key(key_store & keys, - rsa_keypair_id const & id, - base64< rsa_priv_key > const & priv, - bool force_from_user = false); - // netsync stuff void key_hash_code(rsa_keypair_id const & ident, ============================================================ --- rcs_import.cc 2bdf86d7e0951c686cd68fcf60d831ee5ea2c363 +++ rcs_import.cc 0f51bc2b23658e9ef7477a1ba9c7f4f8eff691a5 @@ -31,7 +31,6 @@ #include "database.hh" #include "file_io.hh" #include "interner.hh" -#include "keys.hh" #include "paths.hh" #include "platform-wrapped.hh" #include "project.hh" ============================================================ --- ssh_agent.cc b16db7de9029559a0013c95dc49b985e12fceeeb +++ ssh_agent.cc dcc8cefe23e376c74df2eb10011f874802a609d6 @@ -13,7 +13,6 @@ #include "ssh_agent.hh" #include "sanity.hh" #include "netio.hh" -#include "keys.hh" #include "botan/numthry.h" #include "numeric_vocab.hh" #include "netxx/stream.h"