# # # patch "README.encapsulation" # from [7775f0fa4adab68eaf623276d3c883126503d401] # to [d30f7ef43adcc15592adc8495355d58811122096] # # patch "cert.cc" # from [7b5c4be73e3946f7ae25bf707a30c2c7cf039af7] # to [058fce8cad7351e2c5894575a4669d0de37fab19] # # patch "cert.hh" # from [71a5ac357a0a437c5556a69297c0116ef41917a8] # to [842ed3d1c08d9ec589673ef4b7afd7b2a6470788] # # patch "key_store.cc" # from [d9d884883cba69e5cf6a3a4d452eabe6880d164e] # to [d11a17a84b06232222a63b1558000809e67f4507] # # patch "key_store.hh" # from [78b1f281a7dcd30fbd3404b2b954e0470a362c85] # to [9b2f66870fb8a087ec42bb4a8bcc5778bad625fb] # # patch "keys.cc" # from [e7e47cab5f6efeae027fa0eefdddd64438c9a074] # to [af4ec09e883c6e145c9cc5f931c0047e8d78000b] # # patch "keys.hh" # from [2247bc16bb59873ced93ccc907e10d4615af6861] # to [565ab9f8faf9c3f3c9135107b9361033a587e674] # # patch "netsync.cc" # from [4d388b36d00bcfa1aba5ffcb1f767f6737488673] # to [41565b23d89c106c08c1bd67a85b387d834f18c7] # ============================================================ --- README.encapsulation 7775f0fa4adab68eaf623276d3c883126503d401 +++ README.encapsulation d30f7ef43adcc15592adc8495355d58811122096 @@ -20,6 +20,11 @@ key_store.cc: key_store.cc: app is a member variable of class key_store, used by: + key_store::make_signature() + app.opts.ssh_sign + app.agent + + key_store::hook_get_passphrase() app.lua.hook_get_passphrase() @@ -34,12 +39,6 @@ key_store.cc: key_store::get_opt_signing_key() app.opts.signing_key - key_store::get_opt_ssh_sign() - app.opts.ssh_sign - - key_store::get_agent() - app.agent - lua_hooks.cc: << evil mess involving a map from lua_*state* pointers to app_state pointers >> ============================================================ --- cert.cc 7b5c4be73e3946f7ae25bf707a30c2c7cf039af7 +++ cert.cc 058fce8cad7351e2c5894575a4669d0de37fab19 @@ -365,13 +365,19 @@ void // if that key pair is not available. void +load_key_pair(key_store & keys, rsa_keypair_id const & id) +{ + N(keys.key_pair_exists(id), + F("no key pair '%s' found in key store '%s'") + % id % keys.get_key_dir()); +} + +void load_key_pair(key_store & keys, rsa_keypair_id const & id, keypair & kp) { - N(keys.key_pair_exists(id), - F("no key pair '%s' found in key store '%s'") - % id % keys.get_key_dir()); + load_key_pair(keys, id); keys.get_key_pair(id, kp); } @@ -379,13 +385,9 @@ calculate_cert(key_store & keys, databas calculate_cert(key_store & keys, database & db, cert & t) { string signed_text; - keypair kp; cert_signable_text(t, signed_text); - - load_key_pair(keys, t.key, kp); - db.put_key(t.key, kp.pub); - - make_signature(keys, db, t.key, kp.priv, signed_text, t.sig); + load_key_pair(keys, t.key); + keys.make_signature(db, t.key, signed_text, t.sig); } cert_status ============================================================ --- cert.hh 71a5ac357a0a437c5556a69297c0116ef41917a8 +++ cert.hh 842ed3d1c08d9ec589673ef4b7afd7b2a6470788 @@ -65,7 +65,11 @@ cert_status check_cert(database & db, ce void cert_signable_text(cert const & t,std::string & out); cert_status check_cert(database & db, cert const & t); + void load_key_pair(key_store & keys, + rsa_keypair_id const & id); + +void load_key_pair(key_store & keys, rsa_keypair_id const & id, keypair & kp); ============================================================ --- key_store.cc d9d884883cba69e5cf6a3a4d452eabe6880d164e +++ key_store.cc d11a17a84b06232222a63b1558000809e67f4507 @@ -7,7 +7,13 @@ #include "keys.hh" #include "globish.hh" #include "app_state.hh" +#include "transforms.hh" +#include "botan/botan.h" +#include "botan/rsa.h" +#include "botan/keypair.h" +#include "botan/pem.h" + using std::make_pair; using std::istringstream; using std::map; @@ -16,13 +22,48 @@ using std::vector; using std::string; using std::vector; +using boost::shared_ptr; +using boost::shared_dynamic_cast; + +using Botan::RSA_PrivateKey; +using Botan::RSA_PublicKey; +using Botan::SecureVector; +using Botan::X509_PublicKey; +using Botan::PK_Signer; + +class 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; + + key_store_state(app_state &); + +public: + // 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. + bool put_key_pair_memory(rsa_keypair_id const & ident, + keypair const & kp); +}; + namespace { struct keyreader : public packet_consumer { - key_store & ks; + key_store_state & ks; - keyreader(key_store & k): ks(k) {} + keyreader(key_store_state & k): ks(k) {} virtual void consume_file_data(file_id const & ident, file_data const & dat) {E(false, F("Extraneous data in key store."));} @@ -55,40 +96,54 @@ namespace }; } -key_store::key_store(app_state & a): have_read(false), app(a) +key_store_state::key_store_state(app_state & a) : have_read(false), app(a) { } +key_store::key_store(app_state & a) + : s(new key_store_state(a)) +{ +} + +key_store::~key_store() +{ + delete s; +} + void key_store::set_key_dir(system_path const & kd) { - key_dir = kd; + s->key_dir = kd; } system_path const & key_store::get_key_dir() { - return key_dir; + return s->key_dir; } void key_store::read_key_dir() { vector key_files, dirs; - if (directory_exists(key_dir)) + if (directory_exists(s->key_dir)) { - L(FL("reading key dir '%s'") % key_dir); - read_directory(key_dir, key_files, dirs); + L(FL("reading key dir '%s'") % s->key_dir); + read_directory(s->key_dir, key_files, dirs); } else - L(FL("key dir '%s' does not exist") % key_dir); - keyreader kr(*this); + { + L(FL("key dir '%s' does not exist") % s->key_dir); + return; + } + + keyreader kr(*s); 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(key_dir / *i, dat); + read_data(s->key_dir / *i, dat); istringstream is(dat()); read_packets(is, kr, *this); } @@ -97,9 +152,9 @@ key_store::maybe_read_key_dir() void key_store::maybe_read_key_dir() { - if (have_read) + if (s->have_read) return; - have_read = true; + s->have_read = true; read_key_dir(); } @@ -110,7 +165,7 @@ key_store::get_key_ids(globish const & p maybe_read_key_dir(); priv.clear(); for (map::const_iterator - i = keys.begin(); i != keys.end(); ++i) + i = s->keys.begin(); i != s->keys.end(); ++i) if (pattern.matches((i->first)())) priv.push_back(i->first); } @@ -121,7 +176,7 @@ key_store::get_key_ids(vector::const_iterator - i = keys.begin(); i != keys.end(); ++i) + i = s->keys.begin(); i != s->keys.end(); ++i) priv.push_back(i->first); } @@ -129,7 +184,7 @@ key_store::key_pair_exists(rsa_keypair_i key_store::key_pair_exists(rsa_keypair_id const & ident) { maybe_read_key_dir(); - return keys.find(ident) != keys.end(); + return s->keys.find(ident) != s->keys.end(); } bool @@ -137,8 +192,8 @@ key_store::maybe_get_key_pair(rsa_keypai keypair & kp) { maybe_read_key_dir(); - map::const_iterator i = keys.find(ident); - if (i == keys.end()) + map::const_iterator i = s->keys.find(ident); + if (i == s->keys.end()) return false; kp = i->second; return true; @@ -158,12 +213,12 @@ key_store::maybe_get_key_pair(hexenc keypair & kp) { maybe_read_key_dir(); - map, rsa_keypair_id>::const_iterator hi = hashes.find(hash); - if (hi == hashes.end()) + map, rsa_keypair_id>::const_iterator hi = s->hashes.find(hash); + if (hi == s->hashes.end()) return false; - map::const_iterator ki = keys.find(hi->second); - if (ki == keys.end()) + map::const_iterator ki = s->keys.find(hi->second); + if (ki == s->keys.end()) return false; keyid = hi->second; kp = ki->second; @@ -181,7 +236,7 @@ key_store::get_key_file(rsa_keypair_id c if (leaf.at(i) == '+') leaf.at(i) = '_'; - file = key_dir / path_component(leaf); + file = s->key_dir / path_component(leaf); } void @@ -197,25 +252,25 @@ key_store::write_key(rsa_keypair_id cons 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 % key_dir); - write_data_userprivate(file, dat, key_dir); + L(FL("writing key '%s' to file '%s' in dir '%s'") % ident % file % s->key_dir); + write_data_userprivate(file, dat, s->key_dir); } bool key_store::put_key_pair(rsa_keypair_id const & ident, keypair const & kp) { - bool newkey = put_key_pair_memory(ident, kp); + maybe_read_key_dir(); + bool newkey = s->put_key_pair_memory(ident, kp); if (newkey) write_key(ident); return newkey; } bool -key_store::put_key_pair_memory(rsa_keypair_id const & ident, - keypair const & kp) +key_store_state::put_key_pair_memory(rsa_keypair_id const & ident, + keypair const & kp) { - maybe_read_key_dir(); L(FL("putting key pair '%s'") % ident); pair::iterator, bool> res; res = keys.insert(make_pair(ident, kp)); @@ -240,63 +295,170 @@ key_store::delete_key(rsa_keypair_id con key_store::delete_key(rsa_keypair_id const & ident) { maybe_read_key_dir(); - map::iterator i = keys.find(ident); - if (i != keys.end()) + map::iterator i = s->keys.find(ident); + if (i != s->keys.end()) { hexenc hash; key_hash_code(ident, i->second.pub, hash); - map, rsa_keypair_id>::iterator j = hashes.find(hash); - I(j != hashes.end()); - hashes.erase(j); - keys.erase(i); + map, rsa_keypair_id>::iterator j = s->hashes.find(hash); + I(j != s->hashes.end()); + s->hashes.erase(j); + s->keys.erase(i); } system_path file; get_key_file(ident, file); delete_file(file); } +// +// Crypto operations +// + +void +key_store::make_signature(database & db, + rsa_keypair_id const & id, + string const & tosign, + base64 & signature) +{ + const string & opt_ssh_sign = s->app.opts.ssh_sign; + + keypair key; + get_key_pair(id, key); + + // If the database doesn't have this public key, add it now. + if (!db.public_key_exists(id)) + db.put_key(id, key.pub); + + string sig_string; + ssh_agent & agent = s->app.agent; + + //sign with ssh-agent (if connected) + N(agent.connected() || opt_ssh_sign != "only", + F("You have chosen to sign only with ssh-agent but ssh-agent" + " does not seem to be running.")); + if (opt_ssh_sign == "yes" + || opt_ssh_sign == "check" + || opt_ssh_sign == "only") + { + if (agent.connected()) { + //grab the monotone public key as an RSA_PublicKey + rsa_pub_key pub; + decode_base64(key.pub, pub); + SecureVector pub_block; + pub_block.set(reinterpret_cast(pub().data()), + pub().size()); + L(FL("make_signature: building %d-byte pub key") % pub_block.size()); + shared_ptr x509_key = + shared_ptr(Botan::X509::load_key(pub_block)); + shared_ptr pub_key = shared_dynamic_cast(x509_key); + + if (!pub_key) + throw informative_failure("Failed to get monotone RSA public key"); + agent.sign_data(*pub_key, tosign, sig_string); + } + if (sig_string.length() <= 0) + L(FL("make_signature: monotone and ssh-agent keys do not match, will" + " use monotone signing")); + } + + string ssh_sig = sig_string; + + N(ssh_sig.length() > 0 || opt_ssh_sign != "only", + F("You don't seem to have your monotone key imported ")); + + if (ssh_sig.length() <= 0 + || opt_ssh_sign == "check" + || opt_ssh_sign == "no") + { + SecureVector sig; + + // we permit the user to relax security here, by caching a decrypted key + // (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 = !s->signers.empty() || 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; + + else + { + priv_key = get_private_key(*this, id, key.priv); + if (agent.connected() + && opt_ssh_sign != "only" + && opt_ssh_sign != "no") { + L(FL("make_signature: adding private key (%s) to ssh-agent") % id()); + agent.add_identity(*priv_key, id()); + } + 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) + s->signers.insert(make_pair(id,make_pair(signer,priv_key))); + } + + sig = signer->sign_message(reinterpret_cast(tosign.data()), tosign.size()); + sig_string = string(reinterpret_cast(sig.begin()), sig.size()); + } + + if (opt_ssh_sign == "check" && ssh_sig.length() > 0) + { + E(ssh_sig == sig_string, + F("make_signature: ssh signature (%i) != monotone signature (%i)\n" + "ssh signature : %s\n" + "monotone signature: %s") + % ssh_sig.length() + % sig_string.length() + % encode_hexenc(ssh_sig) + % encode_hexenc(sig_string)); + L(FL("make_signature: signatures from ssh-agent and monotone" + " are the same")); + } + + L(FL("make_signature: produced %d-byte signature") % sig_string.size()); + encode_base64(rsa_sha1_signature(sig_string), signature); + + cert_status s = db.check_signature(id, tosign, signature); + I(s != cert_unknown); + E(s == cert_ok, F("make_signature: signature is not valid")); +} + bool key_store::hook_get_passphrase(rsa_keypair_id const & k, std::string & phrase) { - return app.lua.hook_get_passphrase(k, phrase); + return s->app.lua.hook_get_passphrase(k, phrase); } bool key_store::hook_persist_phrase_ok() { - return app.lua.hook_persist_phrase_ok(); + return s->app.lua.hook_persist_phrase_ok(); } bool key_store::hook_get_current_branch_key(rsa_keypair_id & k) { - return app.lua.hook_get_branch_key(app.opts.branchname, k); + return s->app.lua.hook_get_branch_key(s->app.opts.branchname, k); } bool key_store::has_opt_signing_key() { - return (app.opts.signing_key() != ""); + return (s->app.opts.signing_key() != ""); } rsa_keypair_id key_store::get_opt_signing_key() { - return app.opts.signing_key; + return s->app.opts.signing_key; } -const string & -key_store::get_opt_ssh_sign() -{ - return app.opts.ssh_sign; -} - -ssh_agent & -key_store::get_agent() -{ - return app.agent; -} - // Local Variables: // mode: C++ // fill-column: 76 ============================================================ --- key_store.hh 78b1f281a7dcd30fbd3404b2b954e0470a362c85 +++ key_store.hh 9b2f66870fb8a087ec42bb4a8bcc5778bad625fb @@ -1,42 +1,30 @@ #ifndef __KEY_STORE_H__ #define __KEY_STORE_H__ -#include #include "vector.hh" -#include - -#include - #include "vocab.hh" #include "paths.hh" class app_state; struct globish; -class ssh_agent; +class database; -namespace Botan -{ - class PK_Signer; - class RSA_PrivateKey; - class PK_Verifier; - class RSA_PublicKey; -}; +class key_store_state; class key_store { private: - system_path key_dir; - bool have_read; - app_state & app; - std::map keys; - std::map, rsa_keypair_id> hashes; + key_store_state * 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: key_store(app_state & a); + ~key_store(); + void set_key_dir(system_path const & kd); system_path const & get_key_dir(); @@ -57,23 +45,14 @@ public: bool put_key_pair(rsa_keypair_id const & ident, keypair const & kp); - // just like put_key_pair except that the key is _not_ written to disk. - // primarily for internal use in reading keys back from disk. - bool put_key_pair_memory(rsa_keypair_id const & ident, - keypair const & kp); - - void delete_key(rsa_keypair_id const & ident); - // These are used to cache signers/verifiers (if the hook allows). - // They can't be function-static variables in key.cc, since they - // must be destroyed before the Botan deinitialize() function is - // called. + // Crypto operations - std::map, - boost::shared_ptr > > signers; - + void make_signature(database & db, rsa_keypair_id const & id, + std::string const & tosign, + base64 & signature); + // 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); @@ -81,8 +60,6 @@ public: bool hook_get_current_branch_key(rsa_keypair_id & k); bool has_opt_signing_key(); rsa_keypair_id get_opt_signing_key(); - std::string const & get_opt_ssh_sign(); - ssh_agent & get_agent(); }; // Local Variables: ============================================================ --- keys.cc e7e47cab5f6efeae027fa0eefdddd64438c9a074 +++ keys.cc af4ec09e883c6e145c9cc5f931c0047e8d78000b @@ -360,145 +360,6 @@ change_key_passphrase(key_store & keys, encode_base64(decoded_key, encoded_key); } -void -make_signature(key_store & keys, - database & db, - rsa_keypair_id const & id, // to prompt user for phrase - base64< rsa_priv_key > const & priv, - string const & tosign, - base64 & signature) -{ - const string & opt_ssh_sign = keys.get_opt_ssh_sign(); - - keypair key; - keys.get_key_pair(id, key); - I(key.priv == priv); - - // If the database doesn't have this public key, add it now. - if (!db.public_key_exists(id)) - db.put_key(id, key.pub); - - string sig_string; - ssh_agent & agent = keys.get_agent(); - //sign with ssh-agent (if connected) - N(agent.connected() || opt_ssh_sign != "only", - F("You have chosen to sign only with ssh-agent but ssh-agent" - " does not seem to be running.")); - if (opt_ssh_sign == "yes" - || opt_ssh_sign == "check" - || opt_ssh_sign == "only") - { - /* - vector ssh_keys = agent.get_keys(); - if (ssh_keys.size() <= 0) - L(FL("make_signature: no rsa keys received from ssh-agent")); - else { - */ - if (agent.connected()) { - //grab the monotone public key as an RSA_PublicKey - keys.get_key_pair(id, key); - rsa_pub_key pub; - decode_base64(key.pub, pub); - SecureVector pub_block; - pub_block.set(reinterpret_cast(pub().data()), - pub().size()); - L(FL("make_signature: building %d-byte pub key") % pub_block.size()); - shared_ptr x509_key = - shared_ptr(Botan::X509::load_key(pub_block)); - shared_ptr pub_key = shared_dynamic_cast(x509_key); - - if (!pub_key) - throw informative_failure("Failed to get monotone RSA public key"); - /* - //if monotone key matches ssh-agent key, sign with ssh-agent - for (vector::const_iterator - si = ssh_keys.begin(); si != ssh_keys.end(); ++si) { - if ((*pub_key).get_e() == (*si).get_e() - && (*pub_key).get_n() == (*si).get_n()) { - L(FL("make_signature: ssh key matches monotone key, signing with" - " ssh-agent")); - */ - agent.sign_data(*pub_key, tosign, sig_string); - /* - break; - } - } - */ - } - if (sig_string.length() <= 0) - L(FL("make_signature: monotone and ssh-agent keys do not match, will" - " use monotone signing")); - } - - string ssh_sig = sig_string; - - N(ssh_sig.length() > 0 || opt_ssh_sign != "only", - F("You don't seem to have your monotone key imported ")); - - if (ssh_sig.length() <= 0 - || opt_ssh_sign == "check" - || opt_ssh_sign == "no") - { - SecureVector sig; - - // we permit the user to relax security here, by caching a decrypted key - // (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.signers.empty()) - || keys.hook_persist_phrase_ok(); - - shared_ptr signer; - shared_ptr priv_key; - if (persist_phrase && keys.signers.find(id) != keys.signers.end()) - signer = keys.signers[id].first; - - else - { - priv_key = get_private_key(keys, id, priv); - if (agent.connected() - && opt_ssh_sign != "only" - && opt_ssh_sign != "no") { - L(FL("keys.cc: make_signature: adding private key (%s) to ssh-agent") % id()); - agent.add_identity(*priv_key, id()); - } - 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) - keys.signers.insert(make_pair(id,make_pair(signer,priv_key))); - } - - sig = signer->sign_message(reinterpret_cast(tosign.data()), tosign.size()); - sig_string = string(reinterpret_cast(sig.begin()), sig.size()); - } - - if (opt_ssh_sign == "check" && ssh_sig.length() > 0) - { - E(ssh_sig == sig_string, - F("make_signature: ssh signature (%i) != monotone signature (%i)\n" - "ssh signature : %s\n" - "monotone signature: %s") - % ssh_sig.length() - % sig_string.length() - % encode_hexenc(ssh_sig) - % encode_hexenc(sig_string)); - L(FL("make_signature: signatures from ssh-agent and monotone" - " are the same")); - } - - L(FL("make_signature: produced %d-byte signature") % sig_string.size()); - encode_base64(rsa_sha1_signature(sig_string), signature); - - cert_status s = db.check_signature(id, tosign, signature); - I(s != cert_unknown); - E(s == cert_ok, F("make_signature: signature is not valid")); -} - void encrypt_rsa(key_store & keys, rsa_keypair_id const & id, base64 & pub_encoded, @@ -615,13 +476,15 @@ require_password(rsa_keypair_id const & key_store & keys, database & db) { - keypair kp; - load_key_pair(keys, key, kp); + N(keys.key_pair_exists(key), + F("no key pair '%s' found in key store '%s'") + % key % keys.get_key_dir()); + if (keys.hook_persist_phrase_ok()) { string plaintext("hi maude"); base64 sig; - make_signature(keys, db, key, kp.priv, plaintext, sig); + keys.make_signature(db, key, plaintext, sig); } } ============================================================ --- keys.hh 2247bc16bb59873ced93ccc907e10d4615af6861 +++ keys.hh 565ab9f8faf9c3f3c9135107b9361033a587e674 @@ -38,13 +38,6 @@ void migrate_private_key(key_store & key base64< old_arc4_rsa_priv_key > const & old_priv, keypair & kp); -void make_signature(key_store & keys, - database & db, - rsa_keypair_id const & id, - base64< rsa_priv_key > const & priv, - std::string const & tosign, - base64 & signature); - bool check_signature(key_store & keys, rsa_keypair_id const & id, base64 const & pub, ============================================================ --- netsync.cc 4d388b36d00bcfa1aba5ffcb1f767f6737488673 +++ netsync.cc 41565b23d89c106c08c1bd67a85b387d834f18c7 @@ -1371,21 +1371,23 @@ session::process_hello_cmd(rsa_keypair_i if (use_transport_auth && signing_key() != "") { // get our key pair - keypair our_kp; - load_key_pair(keys, signing_key, our_kp); + load_key_pair(keys, signing_key); + // make a signature with it; + // this also ensures our public key is in the database + base64 sig; + rsa_sha1_signature sig_raw; + keys.make_signature(db, signing_key, nonce(), sig); + decode_base64(sig, sig_raw); + // get the hash identifier for our pubkey + base64 our_pub; + db.get_key(signing_key, our_pub); hexenc our_key_hash; id our_key_hash_raw; - key_hash_code(signing_key, our_kp.pub, our_key_hash); + key_hash_code(signing_key, our_pub, our_key_hash); decode_hexenc(our_key_hash, our_key_hash_raw); - // make a signature - base64 sig; - rsa_sha1_signature sig_raw; - make_signature(keys, db, signing_key, our_kp.priv, nonce(), sig); - decode_base64(sig, sig_raw); - // make a new nonce of our own and send off the 'auth' queue_auth_cmd(this->role, our_include_pattern, our_exclude_pattern, our_key_hash_raw, nonce, mk_nonce(), sig_raw(),