This repository has been archived by the owner on Jan 6, 2020. It is now read-only.
/
passport.cc
260 lines (222 loc) · 11.6 KB
/
passport.cc
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
/* Copyright 2012 MaidSafe.net limited
This MaidSafe Software is licensed to you under (1) the MaidSafe.net Commercial License,
version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which
licence you accepted on initial access to the Software (the "Licences").
By contributing code to the MaidSafe Software, or to this project generally, you agree to be
bound by the terms of the MaidSafe Contributor Agreement, version 1.0, found in the root
directory of this project at LICENSE, COPYING and CONTRIBUTOR respectively and also
available at: http://www.maidsafe.net/licenses
Unless required by applicable law or agreed to in writing, the MaidSafe Software distributed
under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
OF ANY KIND, either express or implied.
See the Licences for the specific language governing permissions and limitations relating to
use of the MaidSafe Software. */
#include "maidsafe/passport/passport.h"
#include "maidsafe/common/make_unique.h"
#include "maidsafe/common/utils.h"
#include "maidsafe/common/authentication/user_credentials.h"
#include "maidsafe/common/authentication/user_credential_utils.h"
#include "maidsafe/common/serialisation/serialisation.h"
namespace maidsafe {
namespace passport {
namespace {
template <typename Key>
void CheckThenAddKeyAndSigner(std::vector<std::pair<Key, typename Key::Signer>>& keys_and_signers,
std::mutex& mutex,
std::pair<Key, typename Key::Signer> key_and_signer) {
std::lock_guard<std::mutex> lock{mutex};
if (std::any_of(std::begin(keys_and_signers), std::end(keys_and_signers),
[&](const std::pair<Key, typename Key::Signer>& existing_pair) {
return key_and_signer.first.name() == existing_pair.first.name() ||
key_and_signer.second.name() == existing_pair.second.name();
})) {
LOG(kError) << "Key or signer already exists in passport - use unique keys and signers.";
BOOST_THROW_EXCEPTION(MakeError(PassportErrors::id_already_exists));
}
keys_and_signers.emplace_back(std::move(key_and_signer));
}
template <typename Key>
std::vector<Key> GetKeys(const std::vector<std::pair<Key, typename Key::Signer>>& keys_and_signers,
std::mutex& mutex) {
std::vector<Key> keys;
std::lock_guard<std::mutex> lock{mutex};
for (const auto& key_and_signer : keys_and_signers)
keys.push_back(key_and_signer.first);
return keys;
}
template <typename Key>
typename Key::Signer RemovePassportKeyAndSigner(
std::vector<std::pair<Key, typename Key::Signer>>& keys_and_signers, std::mutex& mutex,
const Key& key_to_be_removed) {
std::lock_guard<std::mutex> lock{mutex};
auto itr(std::find_if(std::begin(keys_and_signers), std::end(keys_and_signers),
[&](const std::pair<Key, typename Key::Signer>& existing_pair) {
return key_to_be_removed.name() == existing_pair.first.name();
}));
if (itr == std::end(keys_and_signers))
BOOST_THROW_EXCEPTION(MakeError(CommonErrors::no_such_element));
typename Key::Signer signer{std::move(itr->second)};
keys_and_signers.erase(itr);
return signer;
}
} // unnamed namespace
crypto::CipherText EncryptMaid(const Maid& maid, const crypto::AES256Key& symm_key,
const crypto::AES256InitialisationVector& symm_iv) {
return maid.Encrypt(symm_key, symm_iv);
}
crypto::CipherText EncryptAnpmid(const Anpmid& anpmid, const crypto::AES256Key& symm_key,
const crypto::AES256InitialisationVector& symm_iv) {
return anpmid.Encrypt(symm_key, symm_iv);
}
crypto::CipherText EncryptPmid(const Pmid& pmid, const crypto::AES256Key& symm_key,
const crypto::AES256InitialisationVector& symm_iv) {
return pmid.Encrypt(symm_key, symm_iv);
}
Maid DecryptMaid(const crypto::CipherText& encrypted_maid, const crypto::AES256Key& symm_key,
const crypto::AES256InitialisationVector& symm_iv) {
return Maid(encrypted_maid, symm_key, symm_iv);
}
Anpmid DecryptAnpmid(const crypto::CipherText& encrypted_anpmid, const crypto::AES256Key& symm_key,
const crypto::AES256InitialisationVector& symm_iv) {
return Anpmid(encrypted_anpmid, symm_key, symm_iv);
}
Pmid DecryptPmid(const crypto::CipherText& encrypted_pmid, const crypto::AES256Key& symm_key,
const crypto::AES256InitialisationVector& symm_iv) {
return Pmid(encrypted_pmid, symm_key, symm_iv);
}
MaidAndSigner CreateMaidAndSigner() {
Maid::Signer signer;
return std::make_pair(Maid{signer}, signer);
}
PmidAndSigner CreatePmidAndSigner() {
Pmid::Signer signer;
return std::make_pair(Pmid{signer}, signer);
}
MpidAndSigner CreateMpidAndSigner() {
Mpid::Signer signer;
return std::make_pair(Mpid{signer}, signer);
}
Passport::Passport(MaidAndSigner maid_and_signer)
: maid_and_signer_(maidsafe::make_unique<MaidAndSigner>(std::move(maid_and_signer))),
pmids_and_signers_(),
mpids_and_signers_(),
mutex_() {}
Passport::Passport(const crypto::CipherText& encrypted_passport,
const authentication::UserCredentials& user_credentials)
: maid_and_signer_(), pmids_and_signers_(), mpids_and_signers_(), mutex_() {
crypto::SecurePassword secure_password(authentication::CreateSecurePassword(user_credentials));
crypto::AES256Key symm_key(authentication::DeriveSymmEncryptKey(secure_password));
crypto::AES256InitialisationVector symm_iv(authentication::DeriveSymmEncryptIv(secure_password));
FromString(authentication::Obfuscate(user_credentials,
crypto::SymmDecrypt(encrypted_passport, symm_key, symm_iv)),
symm_key, symm_iv);
}
void Passport::FromString(const NonEmptyString& serialised_passport,
const crypto::AES256Key& symm_key,
const crypto::AES256InitialisationVector& symm_iv) {
try {
std::string contents(serialised_passport.string());
InputVectorStream binary_input_stream(SerialisedData(contents.begin(), contents.end()));
std::lock_guard<std::mutex> lock(mutex_);
crypto::CipherText encrypted_fob(Parse<crypto::CipherText>(binary_input_stream));
crypto::CipherText encrypted_signer(Parse<crypto::CipherText>(binary_input_stream));
maid_and_signer_ = maidsafe::make_unique<MaidAndSigner>(
std::make_pair(Maid(std::move(encrypted_fob), symm_key, symm_iv),
Anmaid(std::move(encrypted_signer), symm_key, symm_iv)));
std::uint32_t pmids_and_signers_size(Parse<std::uint32_t>(binary_input_stream));
std::uint32_t mpids_and_signers_size(Parse<std::uint32_t>(binary_input_stream));
for (std::uint32_t i = 0; i < pmids_and_signers_size; ++i) {
encrypted_fob = Parse<crypto::CipherText>(binary_input_stream);
encrypted_signer = Parse<crypto::CipherText>(binary_input_stream);
pmids_and_signers_.push_back(
std::make_pair(Pmid(std::move(encrypted_fob), symm_key, symm_iv),
Anpmid(std::move(encrypted_signer), symm_key, symm_iv)));
}
for (std::uint32_t i = 0; i < mpids_and_signers_size; ++i) {
encrypted_fob = Parse<crypto::CipherText>(binary_input_stream);
encrypted_signer = Parse<crypto::CipherText>(binary_input_stream);
mpids_and_signers_.push_back(
std::make_pair(Mpid(std::move(encrypted_fob), symm_key, symm_iv),
Anmpid(std::move(encrypted_signer), symm_key, symm_iv)));
}
} catch (const std::exception&) {
BOOST_THROW_EXCEPTION(MakeError(CommonErrors::parsing_error));
}
}
NonEmptyString Passport::ToString(const crypto::AES256Key& symm_key,
const crypto::AES256InitialisationVector& symm_iv) const {
std::lock_guard<std::mutex> lock(mutex_);
if (!maid_and_signer_) {
LOG(kError) << "Passport must contain a Maid in order to be serialised.";
BOOST_THROW_EXCEPTION(MakeError(CommonErrors::serialisation_error));
}
OutputVectorStream binary_output_stream;
Serialise(binary_output_stream, maid_and_signer_->first.Encrypt(symm_key, symm_iv)->string(),
maid_and_signer_->second.Encrypt(symm_key, symm_iv)->string(),
static_cast<std::uint32_t>(pmids_and_signers_.size()),
static_cast<std::uint32_t>(mpids_and_signers_.size()));
for (const auto& pmid_and_signer : pmids_and_signers_) {
Serialise(binary_output_stream, pmid_and_signer.first.Encrypt(symm_key, symm_iv),
pmid_and_signer.second.Encrypt(symm_key, symm_iv));
}
for (const auto& mpid_and_signer : mpids_and_signers_) {
Serialise(binary_output_stream, mpid_and_signer.first.Encrypt(symm_key, symm_iv),
mpid_and_signer.second.Encrypt(symm_key, symm_iv));
}
SerialisedData contents(binary_output_stream.vector());
return NonEmptyString(std::string(contents.begin(), contents.end()));
}
crypto::CipherText Passport::Encrypt(
const authentication::UserCredentials& user_credentials) const {
crypto::SecurePassword secure_password(authentication::CreateSecurePassword(user_credentials));
crypto::AES256Key symm_key(authentication::DeriveSymmEncryptKey(secure_password));
crypto::AES256InitialisationVector symm_iv(authentication::DeriveSymmEncryptIv(secure_password));
return crypto::SymmEncrypt(
authentication::Obfuscate(user_credentials, ToString(symm_key, symm_iv)), symm_key, symm_iv);
}
Maid Passport::GetMaid() const {
std::lock_guard<std::mutex> lock{mutex_};
if (!maid_and_signer_)
BOOST_THROW_EXCEPTION(MakeError(CommonErrors::no_such_element));
return maid_and_signer_->first;
}
void Passport::AddKeyAndSigner(PmidAndSigner pmid_and_signer) {
CheckThenAddKeyAndSigner(pmids_and_signers_, mutex_, pmid_and_signer);
}
void Passport::AddKeyAndSigner(MpidAndSigner mpid_and_signer) {
CheckThenAddKeyAndSigner(mpids_and_signers_, mutex_, mpid_and_signer);
}
std::vector<Pmid> Passport::GetPmids() const { return GetKeys(pmids_and_signers_, mutex_); }
std::vector<Mpid> Passport::GetMpids() const { return GetKeys(mpids_and_signers_, mutex_); }
template <>
Maid::Signer Passport::RemoveKeyAndSigner<Maid>(const Maid& key_to_be_removed) {
std::lock_guard<std::mutex> lock{mutex_};
if (!maid_and_signer_ || maid_and_signer_->first.name() != key_to_be_removed.name())
BOOST_THROW_EXCEPTION(MakeError(CommonErrors::no_such_element));
Maid::Signer signer{std::move(maid_and_signer_->second)};
maid_and_signer_.reset();
return signer;
}
template <>
Pmid::Signer Passport::RemoveKeyAndSigner<Pmid>(const Pmid& key_to_be_removed) {
return RemovePassportKeyAndSigner(pmids_and_signers_, mutex_, key_to_be_removed);
}
template <>
Mpid::Signer Passport::RemoveKeyAndSigner<Mpid>(const Mpid& key_to_be_removed) {
return RemovePassportKeyAndSigner(mpids_and_signers_, mutex_, key_to_be_removed);
}
Maid::Signer Passport::ReplaceMaidAndSigner(const Maid& maid_to_be_replaced,
MaidAndSigner new_maid_and_signer) {
std::lock_guard<std::mutex> lock{mutex_};
if (!maid_and_signer_ || maid_and_signer_->first.name() != maid_to_be_replaced.name())
BOOST_THROW_EXCEPTION(MakeError(CommonErrors::no_such_element));
if (new_maid_and_signer.first.name() == maid_and_signer_->first.name() ||
new_maid_and_signer.second.name() == maid_and_signer_->second.name()) {
BOOST_THROW_EXCEPTION(MakeError(PassportErrors::id_already_exists));
}
Maid::Signer signer{std::move(maid_and_signer_->second)};
maid_and_signer_ = maidsafe::make_unique<MaidAndSigner>(new_maid_and_signer);
return signer;
}
} // namespace passport
} // namespace maidsafe