#include #include "identity.h" #include "pubkey.h" #include #include using namespace erebos; using std::lock_guard; using std::nullopt; using std::runtime_error; static const UUID myUUID("4995a5f9-2d4d-48e9-ad3b-0bf1c2a1be7f"); AttachService::AttachService(Config && config, const Server &): PairingService(move(config)) { } AttachService::~AttachService() = default; UUID AttachService::uuid() const { return myUUID; } void AttachService::attachTo(const Peer & peer) { requestPairing(myUUID, peer); } Stored AttachService::handlePairingComplete(const Peer & peer) { auto owner = peer.server().identity().finalOwner(); auto id = peer.identity()->ref(); auto prev = Stored>::load(*peer.identity()->ref()); auto idata = peer.tempStorage().store(IdentityData { .prev = { prev }, .name = nullopt, .owner = Stored>::load(*owner.ref()), .keyIdentity = prev->data->keyIdentity, .keyMessage = nullopt, }); auto key = SecretKey::load(owner.keyIdentity()); if (!key) throw runtime_error("failed to load secret key"); auto mkey = SecretKey::load(owner.keyMessage()); if (!mkey) throw runtime_error("failed to load secret key"); auto sdata = key->sign(idata); return peer.tempStorage().store(AttachIdentity { .identity = sdata, .keys = { key->getData(), mkey->getData() }, }); } void AttachService::handlePairingResult(Context & ctx, Stored att) { if (att->identity->data->prev.size() != 1 || att->identity->data->prev[0].ref().digest() != ctx.local()->identity()->ref()->digest()) return; if (att->identity->data->keyIdentity.ref().digest() != ctx.local()->identity()->keyIdentity().ref().digest()) return; auto key = SecretKey::load(ctx.peer().server().identity().keyIdentity()); if (!key) throw runtime_error("failed to load secret key"); auto id = Identity::load(key->signAdd(att->identity).ref()); if (!id) printf("New identity validation failed\n"); auto rid = ctx.local().ref().storage().copy(*id->ref()); id = Identity::load(rid); auto owner = id->owner(); if (!owner) printf("New identity without owner\n"); // Store the keys for (const auto & k : att->keys) { SecretKey::fromData(owner->keyIdentity(), k); SecretKey::fromData(owner->keyMessage(), k); } ctx.local(ctx.local()->identity(*id)); } AttachIdentity AttachIdentity::load(const Ref & ref) { auto rec = ref->asRecord(); if (!rec) return AttachIdentity { .identity = Stored>::load(ref.storage().zref()), .keys = {}, }; return AttachIdentity { .identity = *rec->item("identity").as>(), .keys = rec->items("skey").asBinary(), }; } Ref AttachIdentity::store(const Storage & st) const { vector items; items.emplace_back("identity", identity.ref()); for (const auto & key : keys) items.emplace_back("skey", key); return st.storeObject(Record(std::move(items))); }