1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
#include <erebos/attach.h>
#include "identity.h"
#include "pubkey.h"
#include <erebos/network.h>
#include <stdexcept>
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<AttachIdentity> AttachService::handlePairingComplete(const Peer & peer)
{
auto owner = peer.server().identity().finalOwner();
auto id = peer.identity()->ref();
auto prev = Stored<Signed<IdentityData>>::load(*peer.identity()->ref());
auto idata = peer.tempStorage().store(IdentityData {
.prev = { prev },
.name = nullopt,
.owner = Stored<Signed<IdentityData>>::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<AttachIdentity> 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<Signed<IdentityData>>::load(ref.storage().zref()),
.keys = {},
};
return AttachIdentity {
.identity = *rec->item("identity").as<Signed<IdentityData>>(),
.keys = rec->items("skey").asBinary(),
};
}
Ref AttachIdentity::store(const Storage & st) const
{
vector<Record::Item> items;
items.emplace_back("identity", identity.ref());
for (const auto & key : keys)
items.emplace_back("skey", key);
return st.storeObject(Record(std::move(items)));
}
|