Skip to content
Snippets Groups Projects
Commit d7fce164 authored by Konstantinos Sideris's avatar Konstantinos Sideris
Browse files

Upload signed one time keys

fixes #21
parent 8ea888bc
No related branches found
No related tags found
No related merge requests found
......@@ -561,11 +561,14 @@ Client::flow_response(const std::string &user,
//
void
Client::upload_identity_keys(
Client::upload_keys(
const nlohmann::json &identity_keys,
const std::map<std::string, nlohmann::json> &one_time_keys,
std::function<void(const mtx::responses::UploadKeys &res, RequestErr err)> callback)
{
mtx::requests::UploadKeys req;
req.one_time_keys = one_time_keys;
req.device_keys.user_id = user_id().to_string();
req.device_keys.device_id = device_id();
req.device_keys.keys.emplace("curve25519:" + device_id(), identity_keys["curve25519"]);
......@@ -576,17 +579,29 @@ Client::upload_identity_keys(
}
void
Client::upload_one_time_keys(
Client::upload_identity_keys(
const nlohmann::json &identity_keys,
std::function<void(const mtx::responses::UploadKeys &res, RequestErr err)> callback)
{
mtx::requests::UploadKeys req;
req.device_keys.user_id = user_id().to_string();
req.device_keys.device_id = device_id();
req.device_keys.keys.emplace("curve25519:" + device_id(), identity_keys["curve25519"]);
req.device_keys.keys.emplace("ed25519:" + device_id(), identity_keys["ed25519"]);
auto obj = identity_keys.at("curve25519");
for (auto it = obj.begin(); it != obj.end(); ++it)
req.one_time_keys.emplace("curve25519:" + it.key(), it.value());
post<mtx::requests::UploadKeys, mtx::responses::UploadKeys>(
"/client/r0/keys/upload", req, callback);
}
void
Client::upload_one_time_keys(
const std::map<std::string, nlohmann::json> &one_time_keys,
std::function<void(const mtx::responses::UploadKeys &res, RequestErr err)> callback)
{
mtx::requests::UploadKeys req;
req.device_keys.user_id = user_id().to_string();
req.device_keys.device_id = device_id();
req.one_time_keys = one_time_keys;
post<mtx::requests::UploadKeys, mtx::responses::UploadKeys>(
"/client/r0/keys/upload", req, callback);
......
......@@ -200,6 +200,13 @@ public:
// Encryption related endpoints.
//
//! Upload identity keys & one time keys.
// TODO: Replace json with a proper type. API methods shouldn't throw.
void upload_keys(
const nlohmann::json &identity_keys,
const std::map<std::string, nlohmann::json> &one_time_keys,
std::function<void(const mtx::responses::UploadKeys &res, RequestErr err)> cb);
//! Upload identity keys.
// TODO: Replace json with a proper type. API methods shouldn't throw.
void upload_identity_keys(
......@@ -209,7 +216,7 @@ public:
//! Upload one time keys.
// TODO: Replace json with a proper type. API methods shouldn't throw.
void upload_one_time_keys(
const nlohmann::json &one_time_keys,
const std::map<std::string, nlohmann::json> &one_time_keys,
std::function<void(const mtx::responses::UploadKeys &res, RequestErr err)> cb);
private:
......
#include <iostream>
#include <sodium.h>
#include "crypto.hpp"
#include "olm/base64.hh"
using json = nlohmann::json;
using namespace mtx::client::crypto;
......@@ -71,3 +73,37 @@ mtx::client::crypto::one_time_keys(std::shared_ptr<olm::Account> account)
return json::parse(data);
}
std::string
mtx::client::crypto::sign_one_time_key(std::shared_ptr<olm::Account> account,
const std::string &key)
{
json j{{"key", key}};
auto str_json = j.dump();
constexpr std::size_t SIGNATURE_SIZE = 64;
// Message
std::vector<std::uint8_t> tmp(str_json.begin(), str_json.end());
std::uint8_t *buf = &tmp[0];
std::size_t nbytes = str_json.size();
// Signature
auto signature_buf = create_buffer(SIGNATURE_SIZE);
account->sign(buf, nbytes, signature_buf.get(), SIGNATURE_SIZE);
auto encoded_buf = create_buffer(SIGNATURE_SIZE);
olm::encode_base64(signature_buf.get(), SIGNATURE_SIZE, encoded_buf.get());
return std::string(encoded_buf.get(), encoded_buf.get() + SIGNATURE_SIZE);
}
json
mtx::client::crypto::signed_one_time_key_json(const mtx::identifiers::User &user_id,
const std::string &device_id,
const std::string &key,
const std::string &signature)
{
return json{{"key", key},
{"signatures", {{user_id.to_string(), {{"ed25519:" + device_id, signature}}}}}};
}
......@@ -4,6 +4,7 @@
#include <memory>
#include <json.hpp>
#include <mtx/identifiers.hpp>
#include <olm/account.hh>
#include <olm/error.h>
......@@ -49,6 +50,16 @@ one_time_keys(std::shared_ptr<olm::Account> user);
std::unique_ptr<uint8_t[]>
create_buffer(std::size_t nbytes);
//! Sign the given one time keys.
std::string
sign_one_time_key(std::shared_ptr<olm::Account> account, const std::string &key);
//! Generate the json structure for the signed one time key.
nlohmann::json
signed_one_time_key_json(const mtx::identifiers::User &user_id,
const std::string &device_id,
const std::string &key,
const std::string &signature);
} // namespace crypto
} // namespace client
} // namespace mtx
......@@ -80,17 +80,99 @@ TEST(Encryption, UploadOneTimeKeys)
while (alice->access_token().empty())
std::this_thread::sleep_for(std::chrono::milliseconds(100));
auto number_of_keys = mtx::client::crypto::generate_one_time_keys(olm_account, 5);
EXPECT_EQ(number_of_keys, 5);
auto nkeys = mtx::client::crypto::generate_one_time_keys(olm_account, 5);
EXPECT_EQ(nkeys, 5);
auto one_time_keys = mtx::client::crypto::one_time_keys(olm_account);
alice->upload_one_time_keys(one_time_keys,
[](const mtx::responses::UploadKeys &res, ErrType err) {
check_error(err);
EXPECT_EQ(res.one_time_key_counts.size(), 1);
EXPECT_EQ(res.one_time_key_counts.at("curve25519"), 5);
});
// Create the proper structure for uploading.
std::map<std::string, json> keys;
auto obj = one_time_keys.at("curve25519");
for (auto it = obj.begin(); it != obj.end(); ++it)
keys["curve25519:" + it.key()] = it.value();
alice->upload_one_time_keys(keys, [](const mtx::responses::UploadKeys &res, ErrType err) {
check_error(err);
EXPECT_EQ(res.one_time_key_counts.size(), 1);
EXPECT_EQ(res.one_time_key_counts.at("curve25519"), 5);
});
alice->close();
}
TEST(Encryption, UploadSignedOneTimeKeys)
{
auto alice = std::make_shared<Client>("localhost");
auto olm_account = mtx::client::crypto::olm_new_account();
alice->login(
"alice", "secret", [](const mtx::responses::Login &, ErrType err) { check_error(err); });
while (alice->access_token().empty())
std::this_thread::sleep_for(std::chrono::milliseconds(100));
auto nkeys = mtx::client::crypto::generate_one_time_keys(olm_account, 5);
EXPECT_EQ(nkeys, 5);
auto one_time_keys = mtx::client::crypto::one_time_keys(olm_account);
// Create the proper structure for uploading.
std::map<std::string, json> signed_keys;
auto obj = one_time_keys.at("curve25519");
for (auto it = obj.begin(); it != obj.end(); ++it) {
auto sig = mtx::client::crypto::sign_one_time_key(olm_account, it.value());
signed_keys["signed_curve25519:" + it.key()] =
mtx::client::crypto::signed_one_time_key_json(
alice->user_id(), alice->device_id(), it.value(), sig);
}
alice->upload_one_time_keys(
signed_keys, [nkeys](const mtx::responses::UploadKeys &res, ErrType err) {
check_error(err);
EXPECT_EQ(res.one_time_key_counts.size(), 1);
EXPECT_EQ(res.one_time_key_counts.at("signed_curve25519"), nkeys);
});
alice->close();
}
TEST(Encryption, UploadKeys)
{
auto alice = std::make_shared<Client>("localhost");
auto olm_account = mtx::client::crypto::olm_new_account();
alice->login(
"alice", "secret", [](const mtx::responses::Login &, ErrType err) { check_error(err); });
while (alice->access_token().empty())
std::this_thread::sleep_for(std::chrono::milliseconds(100));
json identity_keys = mtx::client::crypto::identity_keys(olm_account);
mtx::client::crypto::generate_one_time_keys(olm_account, 1);
auto one_time_keys = mtx::client::crypto::one_time_keys(olm_account);
// Create the proper structure for uploading.
std::map<std::string, json> signed_keys;
auto obj = one_time_keys.at("curve25519");
for (auto it = obj.begin(); it != obj.end(); ++it) {
auto sig = mtx::client::crypto::sign_one_time_key(olm_account, it.value());
signed_keys["signed_curve25519:" + it.key()] =
mtx::client::crypto::signed_one_time_key_json(
alice->user_id(), alice->device_id(), it.value(), sig);
}
alice->upload_keys(
identity_keys, signed_keys, [](const mtx::responses::UploadKeys &res, ErrType err) {
check_error(err);
EXPECT_EQ(res.one_time_key_counts.size(), 1);
EXPECT_EQ(res.one_time_key_counts.at("signed_curve25519"), 1);
});
alice->close();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment