macos related changes

This commit is contained in:
Mikhail Filimonov 2025-04-04 16:58:42 +04:00
parent 5f6f1de1d3
commit b0c637bfff
19 changed files with 113688 additions and 129 deletions

View File

@ -755,11 +755,11 @@ public final class OngoingGroupCallContext {
isConference: isConference, isConference: isConference,
isActiveByDefault: audioIsActiveByDefault, isActiveByDefault: audioIsActiveByDefault,
encryptDecrypt: encryptionContext.flatMap { encryptionContext in encryptDecrypt: encryptionContext.flatMap { encryptionContext in
return { data, isEncrypt in return { data, userId, isEncrypt in
if isEncrypt { if isEncrypt {
return encryptionContext.encrypt(message: data) return encryptionContext.encrypt(message: data)
} else { } else {
return encryptionContext.decrypt(message: data) return encryptionContext.decrypt(message: data, userId: userId)
} }
} }
} }
@ -899,7 +899,6 @@ public final class OngoingGroupCallContext {
} }
return OngoingGroupCallRequestedVideoChannel( return OngoingGroupCallRequestedVideoChannel(
audioSsrc: channel.audioSsrc, audioSsrc: channel.audioSsrc,
userId: channel.peerId,
endpointId: channel.endpointId, endpointId: channel.endpointId,
ssrcGroups: channel.ssrcGroups.map { group in ssrcGroups: channel.ssrcGroups.map { group in
return OngoingGroupCallSsrcGroup( return OngoingGroupCallSsrcGroup(

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,888 @@
#pragma once
#include "td/tl/TlObject.h"
#include "td/utils/UInt.h"
#include <cstdint>
#include <utility>
#include <vector>
namespace td {
class TlStorerCalcLength;
class TlStorerUnsafe;
class TlStorerToString;
class TlParser;
namespace e2e_api {
using int32 = std::int32_t;
using int53 = std::int64_t;
using int64 = std::int64_t;
using string = std::string;
using bytes = std::string;
using secure_string = std::string;
using secure_bytes = std::string;
template <class Type>
using array = std::vector<Type>;
using BaseObject = ::td::TlObject;
template <class Type>
using object_ptr = ::td::tl_object_ptr<Type>;
template <class Type, class... Args>
object_ptr<Type> make_object(Args &&... args) {
return object_ptr<Type>(new Type(std::forward<Args>(args)...));
}
template <class ToType, class FromType>
object_ptr<ToType> move_object_as(FromType &&from) {
return object_ptr<ToType>(static_cast<ToType *>(from.release()));
}
std::string to_string(const BaseObject &value);
template <class T>
std::string to_string(const object_ptr<T> &value) {
if (value == nullptr) {
return "null";
}
return to_string(*value);
}
template <class T>
std::string to_string(const std::vector<object_ptr<T>> &values) {
std::string result = "{\n";
for (const auto &value : values) {
if (value == nullptr) {
result += "null\n";
} else {
result += to_string(*value);
}
}
result += "}\n";
return result;
}
class Object: public TlObject {
public:
static object_ptr<Object> fetch(TlParser &p);
};
class Function: public TlObject {
public:
static object_ptr<Function> fetch(TlParser &p);
};
class ok final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
static const std::int32_t ID = -722616727;
static object_ptr<ok> fetch(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_HandshakePrivate: public Object {
public:
static object_ptr<e2e_HandshakePrivate> fetch(TlParser &p);
};
class e2e_handshakePrivateAccept final : public e2e_HandshakePrivate {
std::int32_t get_id() const final {
return ID;
}
public:
UInt256 alice_PK_;
UInt256 bob_PK_;
int64 alice_user_id_;
int64 bob_user_id_;
UInt256 alice_nonce_;
UInt256 bob_nonce_;
e2e_handshakePrivateAccept(UInt256 const &alice_PK_, UInt256 const &bob_PK_, int64 alice_user_id_, int64 bob_user_id_, UInt256 const &alice_nonce_, UInt256 const &bob_nonce_);
static const std::int32_t ID = -1711729321;
static object_ptr<e2e_HandshakePrivate> fetch(TlParser &p);
explicit e2e_handshakePrivateAccept(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_handshakePrivateFinish final : public e2e_HandshakePrivate {
std::int32_t get_id() const final {
return ID;
}
public:
UInt256 alice_PK_;
UInt256 bob_PK_;
int64 alice_user_id_;
int64 bob_user_id_;
UInt256 alice_nonce_;
UInt256 bob_nonce_;
e2e_handshakePrivateFinish(UInt256 const &alice_PK_, UInt256 const &bob_PK_, int64 alice_user_id_, int64 bob_user_id_, UInt256 const &alice_nonce_, UInt256 const &bob_nonce_);
static const std::int32_t ID = 353768245;
static object_ptr<e2e_HandshakePrivate> fetch(TlParser &p);
explicit e2e_handshakePrivateFinish(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_HandshakePublic: public Object {
public:
static object_ptr<e2e_HandshakePublic> fetch(TlParser &p);
};
class e2e_handshakeQR final : public e2e_HandshakePublic {
std::int32_t get_id() const final {
return ID;
}
public:
UInt256 bob_ephemeral_PK_;
UInt256 bob_nonce_;
e2e_handshakeQR(UInt256 const &bob_ephemeral_PK_, UInt256 const &bob_nonce_);
static const std::int32_t ID = -746741414;
static object_ptr<e2e_HandshakePublic> fetch(TlParser &p);
explicit e2e_handshakeQR(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_handshakeEncryptedMessage final : public e2e_HandshakePublic {
std::int32_t get_id() const final {
return ID;
}
public:
bytes message_;
explicit e2e_handshakeEncryptedMessage(bytes const &message_);
static const std::int32_t ID = -1757409540;
static object_ptr<e2e_HandshakePublic> fetch(TlParser &p);
explicit e2e_handshakeEncryptedMessage(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_handshakeLoginExport final : public e2e_HandshakePublic {
std::int32_t get_id() const final {
return ID;
}
public:
bytes accept_;
bytes encrypted_key_;
e2e_handshakeLoginExport(bytes const &accept_, bytes const &encrypted_key_);
static const std::int32_t ID = -152012972;
static object_ptr<e2e_HandshakePublic> fetch(TlParser &p);
explicit e2e_handshakeLoginExport(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_Key: public Object {
public:
static object_ptr<e2e_Key> fetch(TlParser &p);
};
class e2e_keyContactByUserId final : public e2e_Key {
std::int32_t get_id() const final {
return ID;
}
public:
int64 user_id_;
explicit e2e_keyContactByUserId(int64 user_id_);
static const std::int32_t ID = 1925266987;
static object_ptr<e2e_Key> fetch(TlParser &p);
explicit e2e_keyContactByUserId(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_keyContactByPublicKey final : public e2e_Key {
std::int32_t get_id() const final {
return ID;
}
public:
UInt256 public_key_;
explicit e2e_keyContactByPublicKey(UInt256 const &public_key_);
static const std::int32_t ID = 1817152664;
static object_ptr<e2e_Key> fetch(TlParser &p);
explicit e2e_keyContactByPublicKey(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_Personal: public Object {
public:
static object_ptr<e2e_Personal> fetch(TlParser &p);
};
class e2e_personalUserId final : public e2e_Personal {
std::int32_t get_id() const final {
return ID;
}
public:
int64 user_id_;
explicit e2e_personalUserId(int64 user_id_);
static const std::int32_t ID = 380090592;
static object_ptr<e2e_Personal> fetch(TlParser &p);
explicit e2e_personalUserId(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_personalName final : public e2e_Personal {
std::int32_t get_id() const final {
return ID;
}
public:
string first_name_;
string last_name_;
e2e_personalName(string const &first_name_, string const &last_name_);
static const std::int32_t ID = 1760192213;
static object_ptr<e2e_Personal> fetch(TlParser &p);
explicit e2e_personalName(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_personalPhoneNumber final : public e2e_Personal {
std::int32_t get_id() const final {
return ID;
}
public:
string phone_number_;
explicit e2e_personalPhoneNumber(string const &phone_number_);
static const std::int32_t ID = 1124597274;
static object_ptr<e2e_Personal> fetch(TlParser &p);
explicit e2e_personalPhoneNumber(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_personalContactState final : public e2e_Personal {
std::int32_t get_id() const final {
return ID;
}
public:
int32 flags_;
bool is_contact_;
enum Flags : std::int32_t { IS_CONTACT_MASK = 1 };
e2e_personalContactState();
e2e_personalContactState(int32 flags_, bool is_contact_);
static const std::int32_t ID = -1052064682;
static object_ptr<e2e_Personal> fetch(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_personalEmojiNonces final : public e2e_Personal {
std::int32_t get_id() const final {
return ID;
}
public:
int32 flags_;
UInt256 self_nonce_;
UInt256 contact_nonce_hash_;
UInt256 contact_nonce_;
enum Flags : std::int32_t { SELF_NONCE_MASK = 1, CONTACT_NONCE_HASH_MASK = 2, CONTACT_NONCE_MASK = 4 };
e2e_personalEmojiNonces();
e2e_personalEmojiNonces(int32 flags_, UInt256 const &self_nonce_, UInt256 const &contact_nonce_hash_, UInt256 const &contact_nonce_);
static const std::int32_t ID = -2046934345;
static object_ptr<e2e_Personal> fetch(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_personalOnServer;
class e2e_personalData final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
UInt256 public_key_;
array<object_ptr<e2e_personalOnServer>> data_;
e2e_personalData(UInt256 const &public_key_, array<object_ptr<e2e_personalOnServer>> &&data_);
static const std::int32_t ID = 1037793350;
static object_ptr<e2e_personalData> fetch(TlParser &p);
explicit e2e_personalData(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_Personal;
class e2e_personalOnClient final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
int32 signed_at_;
object_ptr<e2e_Personal> personal_;
e2e_personalOnClient(int32 signed_at_, object_ptr<e2e_Personal> &&personal_);
static const std::int32_t ID = -341421551;
static object_ptr<e2e_personalOnClient> fetch(TlParser &p);
explicit e2e_personalOnClient(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_Personal;
class e2e_personalOnServer final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
UInt512 signature_;
int32 signed_at_;
object_ptr<e2e_Personal> personal_;
e2e_personalOnServer(UInt512 const &signature_, int32 signed_at_, object_ptr<e2e_Personal> &&personal_);
static const std::int32_t ID = -800248701;
static object_ptr<e2e_personalOnServer> fetch(TlParser &p);
explicit e2e_personalOnServer(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_personalOnClient;
class e2e_Value: public Object {
public:
static object_ptr<e2e_Value> fetch(TlParser &p);
};
class e2e_valueContactByUserId final : public e2e_Value {
std::int32_t get_id() const final {
return ID;
}
public:
array<UInt256> public_keys_;
explicit e2e_valueContactByUserId(array<UInt256> &&public_keys_);
static const std::int32_t ID = 113903379;
static object_ptr<e2e_Value> fetch(TlParser &p);
explicit e2e_valueContactByUserId(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_valueContactByPublicKey final : public e2e_Value {
std::int32_t get_id() const final {
return ID;
}
public:
array<object_ptr<e2e_personalOnClient>> entries_;
explicit e2e_valueContactByPublicKey(array<object_ptr<e2e_personalOnClient>> &&entries_);
static const std::int32_t ID = -1418478879;
static object_ptr<e2e_Value> fetch(TlParser &p);
explicit e2e_valueContactByPublicKey(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_Change;
class e2e_chain_stateProof;
class e2e_chain_block final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
UInt512 signature_;
int32 flags_;
UInt256 prev_block_hash_;
array<object_ptr<e2e_chain_Change>> changes_;
int32 height_;
object_ptr<e2e_chain_stateProof> state_proof_;
UInt256 signature_public_key_;
enum Flags : std::int32_t { SIGNATURE_PUBLIC_KEY_MASK = 1 };
e2e_chain_block();
e2e_chain_block(UInt512 const &signature_, int32 flags_, UInt256 const &prev_block_hash_, array<object_ptr<e2e_chain_Change>> &&changes_, int32 height_, object_ptr<e2e_chain_stateProof> &&state_proof_, UInt256 const &signature_public_key_);
static const std::int32_t ID = 1671052726;
static object_ptr<e2e_chain_block> fetch(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_groupState;
class e2e_chain_sharedKey;
class e2e_chain_Change: public Object {
public:
static object_ptr<e2e_chain_Change> fetch(TlParser &p);
};
class e2e_chain_changeNoop final : public e2e_chain_Change {
std::int32_t get_id() const final {
return ID;
}
public:
UInt256 nonce_;
explicit e2e_chain_changeNoop(UInt256 const &nonce_);
static const std::int32_t ID = -558586853;
static object_ptr<e2e_chain_Change> fetch(TlParser &p);
explicit e2e_chain_changeNoop(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_changeSetValue final : public e2e_chain_Change {
std::int32_t get_id() const final {
return ID;
}
public:
bytes key_;
bytes value_;
e2e_chain_changeSetValue(bytes const &key_, bytes const &value_);
static const std::int32_t ID = -33474100;
static object_ptr<e2e_chain_Change> fetch(TlParser &p);
explicit e2e_chain_changeSetValue(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_changeSetGroupState final : public e2e_chain_Change {
std::int32_t get_id() const final {
return ID;
}
public:
object_ptr<e2e_chain_groupState> group_state_;
explicit e2e_chain_changeSetGroupState(object_ptr<e2e_chain_groupState> &&group_state_);
static const std::int32_t ID = 754020678;
static object_ptr<e2e_chain_Change> fetch(TlParser &p);
explicit e2e_chain_changeSetGroupState(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_changeSetSharedKey final : public e2e_chain_Change {
std::int32_t get_id() const final {
return ID;
}
public:
object_ptr<e2e_chain_sharedKey> shared_key_;
explicit e2e_chain_changeSetSharedKey(object_ptr<e2e_chain_sharedKey> &&shared_key_);
static const std::int32_t ID = -1736826536;
static object_ptr<e2e_chain_Change> fetch(TlParser &p);
explicit e2e_chain_changeSetSharedKey(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_GroupBroadcast: public Object {
public:
static object_ptr<e2e_chain_GroupBroadcast> fetch(TlParser &p);
};
class e2e_chain_groupBroadcastNonceCommit final : public e2e_chain_GroupBroadcast {
std::int32_t get_id() const final {
return ID;
}
public:
UInt512 signature_;
int64 user_id_;
int32 chain_height_;
UInt256 chain_hash_;
UInt256 nonce_hash_;
e2e_chain_groupBroadcastNonceCommit(UInt512 const &signature_, int64 user_id_, int32 chain_height_, UInt256 const &chain_hash_, UInt256 const &nonce_hash_);
static const std::int32_t ID = -783209753;
static object_ptr<e2e_chain_GroupBroadcast> fetch(TlParser &p);
explicit e2e_chain_groupBroadcastNonceCommit(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_groupBroadcastNonceReveal final : public e2e_chain_GroupBroadcast {
std::int32_t get_id() const final {
return ID;
}
public:
UInt512 signature_;
int64 user_id_;
int32 chain_height_;
UInt256 chain_hash_;
UInt256 nonce_;
e2e_chain_groupBroadcastNonceReveal(UInt512 const &signature_, int64 user_id_, int32 chain_height_, UInt256 const &chain_hash_, UInt256 const &nonce_);
static const std::int32_t ID = -2081097256;
static object_ptr<e2e_chain_GroupBroadcast> fetch(TlParser &p);
explicit e2e_chain_groupBroadcastNonceReveal(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_groupParticipant final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
int64 user_id_;
UInt256 public_key_;
int32 flags_;
bool add_users_;
bool remove_users_;
int32 version_;
enum Flags : std::int32_t { ADD_USERS_MASK = 1, REMOVE_USERS_MASK = 2 };
e2e_chain_groupParticipant();
e2e_chain_groupParticipant(int64 user_id_, UInt256 const &public_key_, int32 flags_, bool add_users_, bool remove_users_, int32 version_);
static const std::int32_t ID = 418617119;
static object_ptr<e2e_chain_groupParticipant> fetch(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_groupParticipant;
class e2e_chain_groupState final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
array<object_ptr<e2e_chain_groupParticipant>> participants_;
int32 external_permissions_;
e2e_chain_groupState(array<object_ptr<e2e_chain_groupParticipant>> &&participants_, int32 external_permissions_);
static const std::int32_t ID = 500987268;
static object_ptr<e2e_chain_groupState> fetch(TlParser &p);
explicit e2e_chain_groupState(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_sharedKey final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
UInt256 ek_;
string encrypted_shared_key_;
array<int64> dest_user_id_;
array<bytes> dest_header_;
e2e_chain_sharedKey(UInt256 const &ek_, string const &encrypted_shared_key_, array<int64> &&dest_user_id_, array<bytes> &&dest_header_);
static const std::int32_t ID = -1971028353;
static object_ptr<e2e_chain_sharedKey> fetch(TlParser &p);
explicit e2e_chain_sharedKey(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_groupState;
class e2e_chain_sharedKey;
class e2e_chain_stateProof final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
int32 flags_;
UInt256 kv_hash_;
object_ptr<e2e_chain_groupState> group_state_;
object_ptr<e2e_chain_sharedKey> shared_key_;
enum Flags : std::int32_t { GROUP_STATE_MASK = 1, SHARED_KEY_MASK = 2 };
e2e_chain_stateProof();
e2e_chain_stateProof(int32 flags_, UInt256 const &kv_hash_, object_ptr<e2e_chain_groupState> &&group_state_, object_ptr<e2e_chain_sharedKey> &&shared_key_);
static const std::int32_t ID = -692684314;
static object_ptr<e2e_chain_stateProof> fetch(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_nop final : public Function {
std::int32_t get_id() const final {
return ID;
}
public:
static const std::int32_t ID = 1479594067;
using ReturnType = bool;
static object_ptr<e2e_nop> fetch(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
static ReturnType fetch_result(TlParser &p);
};
} // namespace e2e_api
} // namespace td

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,7 @@ struct GroupParticipant {
td::int64 user_id{0}; td::int64 user_id{0};
td::int32 flags{0}; td::int32 flags{0};
PublicKey public_key{}; PublicKey public_key{};
td::int32 version{0};
bool add_users() const { bool add_users() const {
return (flags & GroupParticipantFlags::AddUsers) != 0; return (flags & GroupParticipantFlags::AddUsers) != 0;
} }
@ -50,7 +51,8 @@ struct GroupParticipant {
return (flags & GroupParticipantFlags::RemoveUsers) != 0; return (flags & GroupParticipantFlags::RemoveUsers) != 0;
} }
bool operator==(const GroupParticipant &other) const { bool operator==(const GroupParticipant &other) const {
return user_id == other.user_id && flags == other.flags && public_key == other.public_key; return user_id == other.user_id && flags == other.flags && public_key == other.public_key &&
version == other.version;
} }
bool operator!=(const GroupParticipant &other) const { bool operator!=(const GroupParticipant &other) const {
return !(other == *this); return !(other == *this);
@ -61,7 +63,8 @@ struct GroupParticipant {
}; };
inline td::StringBuilder &operator<<(td::StringBuilder &sb, const GroupParticipant &part) { inline td::StringBuilder &operator<<(td::StringBuilder &sb, const GroupParticipant &part) {
return sb << "(uid=" << part.user_id << ", flags=" << part.flags << ", pk=" << part.public_key << ")"; return sb << "(uid=" << part.user_id << ", flags=" << part.flags << ", pk=" << part.public_key
<< ", version=" << part.version << ")";
} }
struct GroupState; struct GroupState;
@ -94,9 +97,10 @@ struct GroupState {
bool empty() const { bool empty() const {
return participants.empty(); return participants.empty();
} }
td::int32 version() const;
td::Result<GroupParticipant> get_participant(td::int64 user_id) const; td::Result<GroupParticipant> get_participant(td::int64 user_id) const;
td::Result<GroupParticipant> get_participant(const PublicKey &public_key) const; td::Result<GroupParticipant> get_participant(const PublicKey &public_key) const;
Permissions get_permissions(const PublicKey &public_key) const; Permissions get_permissions(const PublicKey &public_key, td::int32 limit_permissions) const;
static GroupStateRef from_tl(const td::e2e_api::e2e_chain_groupState &state); static GroupStateRef from_tl(const td::e2e_api::e2e_chain_groupState &state);
e2e::object_ptr<e2e::e2e_chain_groupState> to_tl() const; e2e::object_ptr<e2e::e2e_chain_groupState> to_tl() const;
static GroupStateRef empty_state(); static GroupStateRef empty_state();
@ -119,6 +123,9 @@ struct GroupSharedKey {
static GroupSharedKeyRef from_tl(const td::e2e_api::e2e_chain_sharedKey &shared_key); static GroupSharedKeyRef from_tl(const td::e2e_api::e2e_chain_sharedKey &shared_key);
e2e::object_ptr<e2e::e2e_chain_sharedKey> to_tl() const; e2e::object_ptr<e2e::e2e_chain_sharedKey> to_tl() const;
static GroupSharedKeyRef empty_shared_key(); static GroupSharedKeyRef empty_shared_key();
bool empty() const {
return *this == *empty_shared_key();
}
bool operator==(const GroupSharedKey &other) const { bool operator==(const GroupSharedKey &other) const {
return ek == other.ek && encrypted_shared_key == other.encrypted_shared_key && dest_user_id == other.dest_user_id && return ek == other.ek && encrypted_shared_key == other.encrypted_shared_key && dest_user_id == other.dest_user_id &&
dest_header == other.dest_header; dest_header == other.dest_header;
@ -201,13 +208,20 @@ struct StateProof {
static StateProof from_tl(const td::e2e_api::e2e_chain_stateProof &proof); static StateProof from_tl(const td::e2e_api::e2e_chain_stateProof &proof);
e2e::object_ptr<e2e::e2e_chain_stateProof> to_tl() const; e2e::object_ptr<e2e::e2e_chain_stateProof> to_tl() const;
}; };
td::StringBuilder &operator<<(td::StringBuilder &sb, const StateProof &state); td::StringBuilder &operator<<(td::StringBuilder &sb, const StateProof &state);
struct ValidateOptions {
bool validate_state_hash{true};
bool validate_signature{true};
td::int32 permissions{GroupParticipantFlags::AllPermissions};
};
struct Block; struct Block;
struct State { struct State {
KeyValueState key_value_state_; KeyValueState key_value_state_;
GroupStateRef group_state_; GroupStateRef group_state_;
GroupSharedKeyRef shared_key_; GroupSharedKeyRef shared_key_;
bool has_set_value_{};
bool has_shared_key_change_{}; bool has_shared_key_change_{};
bool has_group_state_change_{}; bool has_group_state_change_{};
@ -223,18 +237,19 @@ struct State {
static State create_empty(); static State create_empty();
static td::Result<State> create_from_block(const Block &block, td::optional<td::Slice> o_snapshot = {}); static td::Result<State> create_from_block(const Block &block, td::optional<td::Slice> o_snapshot = {});
// TODO snapshot..
// TODO apply
td::Status set_value(td::Slice key, td::Slice value, const Permissions &permissions); td::Status set_value(td::Slice key, td::Slice value, const Permissions &permissions);
td::Status set_group_state(GroupStateRef group_state, const Permissions &permissions); td::Status set_group_state(GroupStateRef group_state, const Permissions &permissions);
td::Status clear_shared_key(const Permissions &permissions); td::Status clear_shared_key(const Permissions &permissions);
td::Status set_shared_key(GroupSharedKeyRef shared_key, const Permissions &permissions); td::Status set_shared_key(GroupSharedKeyRef shared_key, const Permissions &permissions);
td::Status set_value_fast(KeyValueHash key_value_hash); td::Status set_value_fast(const KeyValueHash &key_value_hash);
td::Status apply_change(const Change &change_outer, const PublicKey &public_key, bool full_apply); td::Status apply_change(const Change &change_outer, const PublicKey &public_key, const ValidateOptions &options);
td::Status apply(Block &block, bool validate_state_hash = true); td::Status apply(Block &block, ValidateOptions validate_options = {});
td::Status validate_state(const StateProof &state_proof) const; td::Status validate_state(const StateProof &state_proof) const;
static td::Status validate_group_state(const GroupStateRef &group_state);
static td::Status validate_shared_key(const GroupSharedKeyRef &shared_key, const GroupStateRef &group_state);
}; };
struct Block { struct Block {
@ -270,8 +285,13 @@ struct Blockchain {
} }
static td::Result<Blockchain> create_from_block(Block block, td::optional<td::Slice> o_snapshot = {}); static td::Result<Blockchain> create_from_block(Block block, td::optional<td::Slice> o_snapshot = {});
static bool is_from_server(td::Slice block);
static td::Result<std::string> from_any_to_local(std::string block);
static td::Result<std::string> from_server_to_local(std::string block);
static td::Result<std::string> from_local_to_server(std::string block);
td::Result<Block> build_block(std::vector<Change> changes, const PrivateKey &private_key) const; td::Result<Block> build_block(std::vector<Change> changes, const PrivateKey &private_key) const;
td::Status try_apply_block(Block block, bool validate_state_hash = true); td::Status try_apply_block(Block block, ValidateOptions validate_options);
Block set_value(td::Slice key, td::Slice value, const PrivateKey &private_key) const; Block set_value(td::Slice key, td::Slice value, const PrivateKey &private_key) const;
td::int64 get_height() const; td::int64 get_height() const;

View File

@ -39,16 +39,21 @@ struct CallVerificationChain {
void on_new_main_block(const Blockchain &blockhain); void on_new_main_block(const Blockchain &blockhain);
td::Status try_apply_block(td::Slice message); td::Status try_apply_block(td::Slice message);
std::string to_short_string(e2e::object_ptr<e2e::e2e_chain_GroupBroadcast> &broadcast); std::string to_short_string(e2e::object_ptr<e2e::e2e_chain_GroupBroadcast> &broadcast);
td::Status process_broadcast(std::string message, e2e::object_ptr<e2e::e2e_chain_GroupBroadcast> broadcast);
CallVerificationState get_verification_state() const; CallVerificationState get_verification_state() const;
CallVerificationWords get_verification_words() const; CallVerificationWords get_verification_words() const;
td::Span<std::string> received_messages() const; void allow_delay() {
delay_allowed_ = true;
}
void skip_signatures_validation() {
may_skip_signatures_validation_ = true;
}
friend td::StringBuilder &operator<<(td::StringBuilder &sb, const CallVerificationChain &chain); friend td::StringBuilder &operator<<(td::StringBuilder &sb, const CallVerificationChain &chain);
private: private:
td::Status process_broadcast(std::string message, e2e::object_ptr<e2e::e2e_chain_GroupBroadcast> broadcast);
td::Status process_broadcast(e2e::e2e_chain_groupBroadcastNonceCommit &nonce_commit); td::Status process_broadcast(e2e::e2e_chain_groupBroadcastNonceCommit &nonce_commit);
td::Status process_broadcast(e2e::e2e_chain_groupBroadcastNonceReveal &nonce_reveal); td::Status process_broadcast(e2e::e2e_chain_groupBroadcastNonceReveal &nonce_reveal);
@ -57,60 +62,62 @@ struct CallVerificationChain {
CallVerificationWords verification_words_; CallVerificationWords verification_words_;
td::int32 height_{-1}; td::int32 height_{-1};
td::UInt256 last_block_hash_{}; td::UInt256 last_block_hash_{};
std::map<PublicKey, td::int64> participant_keys_; std::map<td::int64, PublicKey> participant_keys_;
std::map<PublicKey, std::string> committed_; std::map<td::int64, std::string> committed_;
std::map<PublicKey, std::string> revealed_; std::map<td::int64, std::string> revealed_;
std::vector<std::string> received_messages_;
bool delay_allowed_{false};
bool may_skip_signatures_validation_{false};
std::map<td::int32, std::vector<std::pair<std::string, e2e::object_ptr<e2e::e2e_chain_GroupBroadcast>>>> std::map<td::int32, std::vector<std::pair<std::string, e2e::object_ptr<e2e::e2e_chain_GroupBroadcast>>>>
delayed_broadcasts_; delayed_broadcasts_;
}; };
class CallEncryption { class CallEncryption {
public: public:
explicit CallEncryption(PrivateKey private_key); explicit CallEncryption(td::int64 user_id, PrivateKey private_key);
td::Status add_shared_key(td::int32 epoch, td::SecureString key, GroupStateRef group_state); td::Status add_shared_key(td::int32 epoch, td::SecureString key, GroupStateRef group_state);
void forget_shared_key(td::int32 epoch);
td::Result<std::string> decrypt(td::Slice encrypted_data); td::Result<std::string> decrypt(td::int64 expected_user_id, td::int32 expected_channel_id, td::Slice encrypted_data);
td::Result<std::string> encrypt(td::int32 channel_id, td::Slice decrypted_data);
td::Result<std::string> encrypt(td::Slice decrypted_data);
private: private:
static constexpr double FORGET_EPOCH_DELAY = 10;
static constexpr int MAX_ACTIVE_EPOCHS = 15;
td::int64 user_id_{};
PrivateKey private_key_; PrivateKey private_key_;
class EpochEncryptor { struct EpochInfo {
public: EpochInfo(td::int32 epoch, td::int64 user_id, td::SecureString secret, GroupStateRef group_state)
EpochEncryptor(td::int32 epoch, td::int64 user_id, td::SecureString secret, GroupStateRef group_state, : epoch_(epoch), user_id_(user_id), secret_(std::move(secret)), group_state_(std::move(group_state)) {
PrivateKey private_key); }
td::Result<std::string> decrypt(td::Slice encrypted_data); td::int32 epoch_{};
td::Result<std::string> encrypt(td::Slice decrypted_data); td::int64 user_id_{};
td::Status check_not_seen(td::int64 user_id, td::uint32 seqno);
void mark_as_seen(td::int64 user_id, td::uint32 seqno);
private:
td::int32 epoch_;
td::int64 user_id_;
td::uint32 seqno_{0};
td::SecureString secret_; td::SecureString secret_;
GroupStateRef group_state_; GroupStateRef group_state_;
PrivateKey private_key_;
std::unordered_map<td::int64, std::set<td::uint32>, td::Hash<td::int64>> seen_;
}; };
td::optional<td::int32> o_last_epoch_; std::map<td::int32, td::uint32> seqno_;
std::map<td::int32, EpochEncryptor> encryptor_by_epoch_; std::map<td::int32, EpochInfo> epochs_;
td::VectorQueue<std::pair<td::Timestamp, td::int32>> epochs_to_forget_; td::VectorQueue<std::pair<td::Timestamp, td::int32>> epochs_to_forget_;
std::map<std::pair<PublicKey, td::int32>, std::set<td::uint32>> seen_;
void forget_old_epochs(); void sync();
td::Result<std::string> encrypt_packet_with_secret(td::int32 channel_id, td::Slice header, td::Slice packet,
td::Slice one_time_secret);
td::Result<std::string> decrypt_packet_with_secret(td::int64 expected_user_id, td::int32 expected_channel_id,
td::Slice unencrypted_packet, td::Slice encrypted_packet,
td::Slice one_time_secret, const GroupStateRef &group_state);
td::Status check_not_seen(const PublicKey &public_key, td::int32 channel_id, td::uint32 seqno);
void mark_as_seen(const PublicKey &public_key, td::int32 channel_id, td::uint32 seqno);
static td::Status validate_channel_id(td::int32 channel_id);
}; };
class CallVerification { class CallVerification {
public: public:
static CallVerification create(PrivateKey private_key, const Blockchain &blockchain); static CallVerification create(td::int64 user_id, PrivateKey private_key, const Blockchain &blockchain);
void on_new_main_block(const Blockchain &blockhain); void on_new_main_block(const Blockchain &blockhain);
CallVerificationState get_verification_state() const; CallVerificationState get_verification_state() const;
std::vector<std::string> pull_outbound_messages(); std::vector<std::string> pull_outbound_messages();
@ -120,68 +127,89 @@ class CallVerification {
friend td::StringBuilder &operator<<(td::StringBuilder &sb, const CallVerification &verification); friend td::StringBuilder &operator<<(td::StringBuilder &sb, const CallVerification &verification);
private: private:
td::int64 user_id_{};
PrivateKey private_key_; PrivateKey private_key_;
CallVerificationChain chain_; CallVerificationChain chain_;
std::vector<tde2e_api::Bytes> pending_outbound_messages_; std::vector<tde2e_api::Bytes> pending_outbound_messages_;
bool sent_commit_{false}; bool sent_commit_{false};
bool sent_reveal_{false}; bool sent_reveal_{false};
td::int32 height_{}; td::int32 height_{-1};
td::UInt256 last_block_hash_{};
td::UInt256 nonce_{}; td::UInt256 nonce_{};
}; };
struct Call { struct Call {
Call(PrivateKey pk, ClientBlockchain blockchain);
static td::Result<std::string> create_zero_block(const PrivateKey &private_key, GroupStateRef group_state); static td::Result<std::string> create_zero_block(const PrivateKey &private_key, GroupStateRef group_state);
static td::Result<std::string> create_self_add_block(const PrivateKey &private_key, td::Slice previous_block, static td::Result<std::string> create_self_add_block(const PrivateKey &private_key, td::Slice previous_block,
const GroupParticipant &self); const GroupParticipant &self);
static td::Result<Call> create(PrivateKey private_key, td::Slice last_block); static td::Result<Call> create(td::int64 user_id, PrivateKey private_key, td::Slice last_block);
td::Result<std::string> build_change_state(GroupStateRef new_group_state) const;
static td::Result<std::vector<Change>> make_changes_for_new_state(GroupStateRef group_state); static td::Result<std::vector<Change>> make_changes_for_new_state(GroupStateRef group_state);
td::int32 get_height() const;
td::Result<std::string> build_change_state(GroupStateRef new_group_state) const;
td::Result<td::int32> get_height() const;
td::Result<GroupStateRef> get_group_state() const; td::Result<GroupStateRef> get_group_state() const;
// TODO: add self user_id
// TODO: verify that call contains us
// changes CallVerificationState
td::Status apply_block(td::Slice block); td::Status apply_block(td::Slice block);
td::Slice shared_key() const { td::Status get_status() const {
return group_shared_key_; if (status_.is_error()) {
return Error(E::CallFailed, PSLICE() << status_);
} }
td::Result<std::string> decrypt(td::Slice encrypted_data) { return td::Status::OK();
return call_encryption_.decrypt(encrypted_data);
}
td::Result<std::string> encrypt(td::Slice decrypted_data) {
return call_encryption_.encrypt(decrypted_data);
} }
std::vector<std::string> pull_outbound_messages() { td::Result<td::SecureString> shared_key() const {
TRY_STATUS(get_status());
return group_shared_key_.copy();
}
td::Result<std::string> decrypt(td::int64 user_id, td::int32 channel_id, td::Slice encrypted_data) {
TRY_STATUS(get_status());
return call_encryption_.decrypt(user_id, channel_id, encrypted_data);
}
td::Result<std::string> encrypt(td::int32 channel_id, td::Slice decrypted_data) {
TRY_STATUS(get_status());
return call_encryption_.encrypt(channel_id, decrypted_data);
}
td::Result<std::vector<std::string>> pull_outbound_messages() {
TRY_STATUS(get_status());
return call_verification_.pull_outbound_messages(); return call_verification_.pull_outbound_messages();
} }
td::Result<CallVerificationState> get_verification_state() const { td::Result<CallVerificationState> get_verification_state() const {
TRY_STATUS(get_status());
return call_verification_.get_verification_state(); return call_verification_.get_verification_state();
} }
td::Result<CallVerificationWords> get_verification_words() const { td::Result<CallVerificationWords> get_verification_words() const {
TRY_STATUS(get_status());
return call_verification_.get_verification_words(); return call_verification_.get_verification_words();
} }
td::Result<CallVerificationState> receive_inbound_message(td::Slice verification_message) { td::Result<CallVerificationState> receive_inbound_message(td::Slice verification_message) {
TRY_STATUS(call_verification_.receive_inbound_message(verification_message)); TRY_STATUS(get_status());
// For now, don't fail the call in case of some errors
TRY_RESULT(local_verification_message, Blockchain::from_server_to_local(verification_message.str()));
TRY_STATUS(call_verification_.receive_inbound_message(local_verification_message));
return get_verification_state(); return get_verification_state();
} }
friend td::StringBuilder &operator<<(td::StringBuilder &builder, const Call &call); friend td::StringBuilder &operator<<(td::StringBuilder &builder, const Call &call);
private: private:
td::Status status_{td::Status::OK()};
td::int64 user_id_{0};
PrivateKey private_key_; PrivateKey private_key_;
ClientBlockchain blockchain_; ClientBlockchain blockchain_;
td::SecureString group_shared_key_;
CallVerification call_verification_; CallVerification call_verification_;
CallEncryption call_encryption_; CallEncryption call_encryption_;
td::SecureString group_shared_key_;
Call(td::int64 user_id, PrivateKey pk, ClientBlockchain blockchain);
td::Status update_group_shared_key(); td::Status update_group_shared_key();
td::Status do_apply_block(td::Slice block); td::Status do_apply_block(td::Slice block);
td::Result<td::SecureString> decrypt_shared_key();
}; };
} // namespace tde2e_core } // namespace tde2e_core

View File

@ -18,6 +18,7 @@ namespace tde2e_core {
struct DecryptedKey; struct DecryptedKey;
struct EncryptedKey { struct EncryptedKey {
static constexpr int PBKDF_ITERATIONS = 100000; static constexpr int PBKDF_ITERATIONS = 100000;
static constexpr int PBKDF_FAST_ITERATIONS = 1;
td::SecureString encrypted_data; td::SecureString encrypted_data;
td::optional<PublicKey> o_public_key; td::optional<PublicKey> o_public_key;
td::SecureString secret; td::SecureString secret;

View File

@ -323,9 +323,9 @@ struct EncryptedStorage {
static td::Result<EncryptedStorage> create(td::Slice last_block, PrivateKey pk) { static td::Result<EncryptedStorage> create(td::Slice last_block, PrivateKey pk) {
auto public_key = pk.to_public_key(); auto public_key = pk.to_public_key();
auto secret_for_key = MessageEncryption::combine_secrets("EncryptedStorage::secret_for_key", pk.to_secure_string()); auto secret_for_key = MessageEncryption::hmac_sha512(pk.to_secure_string(), "EncryptedStorage::secret_for_key");
auto secret_for_value = auto secret_for_value =
MessageEncryption::combine_secrets("EncryptedStorage::secret_for_value", pk.to_secure_string()); MessageEncryption::hmac_sha512(pk.to_secure_string(), "EncryptedStorage::secret_for_value");
ClientBlockchain blockchain; ClientBlockchain blockchain;
if (last_block.empty()) { if (last_block.empty()) {
TRY_RESULT_ASSIGN(blockchain, ClientBlockchain::create_empty()); TRY_RESULT_ASSIGN(blockchain, ClientBlockchain::create_empty());

View File

@ -17,20 +17,23 @@ class MessageEncryption {
public: public:
static td::SecureString encrypt_data(td::Slice data, td::Slice secret); static td::SecureString encrypt_data(td::Slice data, td::Slice secret);
static td::Result<td::SecureString> decrypt_data(td::Slice encrypted_data, td::Slice secret); static td::Result<td::SecureString> decrypt_data(td::Slice encrypted_data, td::Slice secret);
static td::SecureString combine_secrets(td::Slice a, td::Slice b); static td::SecureString hmac_sha512(td::Slice key, td::Slice message);
static td::SecureString kdf(td::Slice secret, td::Slice password, int iterations); static td::SecureString kdf(td::Slice secret, td::Slice password, int iterations);
static td::SecureString encrypt_header(td::Slice decrypted_header, td::Slice encrypted_message, td::Slice secret); static td::Result<td::SecureString> encrypt_header(td::Slice decrypted_header, td::Slice encrypted_message, td::Slice secret);
static td::Result<td::SecureString> decrypt_header(td::Slice encrypted_header, td::Slice encrypted_message, static td::Result<td::SecureString> decrypt_header(td::Slice encrypted_header, td::Slice encrypted_message,
td::Slice secret); td::Slice secret);
private: private:
static td::AesCbcState calc_aes_cbc_state_from_hash(td::Slice hash); static td::AesCbcState calc_aes_cbc_state_from_hash(td::Slice hash);
static td::AesCbcState calc_aes_cbc_state_from_secret(td::Slice seed);
static td::SecureString gen_random_prefix(td::int64 data_size, td::int64 min_padding); static td::SecureString gen_random_prefix(td::int64 data_size, td::int64 min_padding);
static td::SecureString gen_deterministic_prefix(td::int64 data_size, td::int64 min_padding);
static td::SecureString encrypt_data_with_prefix(td::Slice data, td::Slice secret); static td::SecureString encrypt_data_with_prefix(td::Slice data, td::Slice secret);
static td::SecureString kdf_expand(td::Slice random_secret, td::Slice info);
friend class SimpleEncryptionV2; friend class SimpleEncryptionV2;
friend class EncryptionTest;
}; };
} // namespace tde2e_core } // namespace tde2e_core

View File

@ -140,6 +140,8 @@ struct BlockBuilder {
bool has_signature{false}; bool has_signature{false};
tde2e_core::Block block; tde2e_core::Block block;
KeyValueState kv_state_;
void sign(const PrivateKey &private_key); void sign(const PrivateKey &private_key);
void zero_sign(); void zero_sign();
std::string hash_key(td::Slice key) const; std::string hash_key(td::Slice key) const;
@ -162,7 +164,7 @@ struct BlockchainTester {
void reindex(); void reindex();
td::Result<std::vector<std::string>> get_values(const std::vector<std::string> &keys); td::Result<std::vector<std::string>> get_values(const std::vector<std::string> &keys);
td::Result<std::string> get_block(td::int64 height, int sub_chain = 0); td::Result<std::string> get_block_from_server(td::int64 height, int sub_chain = 0);
td::Result<std::string> get_value(td::Slice key); td::Result<std::string> get_value(td::Slice key);

View File

@ -98,6 +98,8 @@ struct EncryptedMessageForMany {
std::string encrypted_message; std::string encrypted_message;
}; };
Result<Ok> set_log_verbosity_level(int level);
// Keys management // Keys management
// private keys will stay inside the library when it is possible // private keys will stay inside the library when it is possible
// all keys are stored only in memory and should be created or imported before usage // all keys are stored only in memory and should be created or imported before usage
@ -116,6 +118,10 @@ Result<Int512> key_sign(PrivateKeyId key, Slice data);
Result<Ok> key_destroy(AnyKeyId key_id); Result<Ok> key_destroy(AnyKeyId key_id);
Result<Ok> key_destroy_all(); Result<Ok> key_destroy_all();
// Used to encrypt key between processes, secret_id must be generated with key_from_ecdh
Result<Bytes> key_to_encrypted_private_key_internal(PrivateKeyId key_id, SymmetricKeyId secret_id);
Result<PrivateKeyId> key_from_encrypted_private_key_internal(Slice encrypted_key, SymmetricKeyId secret_id);
Result<EncryptedMessageForMany> encrypt_message_for_many(const std::vector<SymmetricKeyId> &key_ids, Result<EncryptedMessageForMany> encrypt_message_for_many(const std::vector<SymmetricKeyId> &key_ids,
SecureSlice message); SecureSlice message);
// keeps encrypted_message empty in result // keeps encrypted_message empty in result
@ -168,6 +174,7 @@ Result<PrivateKeyId> login_finish_for_bob(LoginId bob_login_id, UserId alice_use
Result<Ok> login_destroy(LoginId login_id); Result<Ok> login_destroy(LoginId login_id);
Result<Ok> login_destroy_all(); Result<Ok> login_destroy_all();
// Personal info // Personal info
// TODO: UserId // TODO: UserId
@ -276,6 +283,7 @@ Result<Ok> storage_blockchain_add_proof(StorageId storage_id, Slice proof, const
Result<StorageBlockchainState> storage_get_blockchain_state(StorageId); Result<StorageBlockchainState> storage_get_blockchain_state(StorageId);
using CallId = std::int64_t; using CallId = std::int64_t;
using CallChannelId = std::int32_t;
struct CallParticipant { struct CallParticipant {
UserId user_id; UserId user_id;
PublicKeyId public_key_id; PublicKeyId public_key_id;
@ -289,15 +297,15 @@ struct CallState {
Result<Bytes> call_create_zero_block(PrivateKeyId private_key_id, const CallState &initial_state); Result<Bytes> call_create_zero_block(PrivateKeyId private_key_id, const CallState &initial_state);
Result<Bytes> call_create_self_add_block(PrivateKeyId private_key_id, Slice previous_block, const CallParticipant &self); Result<Bytes> call_create_self_add_block(PrivateKeyId private_key_id, Slice previous_block, const CallParticipant &self);
Result<CallId> call_create(PrivateKeyId private_key_id, Slice last_block); Result<CallId> call_create(UserId user_id, PrivateKeyId private_key_id, Slice last_block);
Result<std::string> call_describe(CallId call);
Result<std::string> call_describe_block(Slice block); Result<std::string> call_describe_block(Slice block);
Result<std::string> call_describe_message(Slice message); Result<std::string> call_describe_message(Slice message);
Result<Bytes> call_create_change_state_block(CallId call_id, const CallState &new_state); Result<Bytes> call_create_change_state_block(CallId call_id, const CallState &new_state);
Result<SecureBytes> call_export_shared_key(CallId call_id); Result<Bytes> call_encrypt(CallId call_id, CallChannelId channel_id, SecureSlice message);
Result<Bytes> call_encrypt(CallId call_id, SecureSlice message); Result<SecureBytes> call_decrypt(CallId call_id, UserId user_id, CallChannelId channel_id, Slice message);
Result<SecureBytes> call_decrypt(CallId call_id, Slice message);
Result<int> call_get_height(CallId call_id); Result<int> call_get_height(CallId call_id);
Result<CallState> call_apply_block(CallId call_id, Slice block); Result<CallState> call_apply_block(CallId call_id, Slice block);
@ -324,32 +332,4 @@ struct CallVerificationWords {
Result<CallVerificationWords> call_get_verification_words(CallId call_id); Result<CallVerificationWords> call_get_verification_words(CallId call_id);
Result<Ok> call_destroy(CallId call_id); Result<Ok> call_destroy(CallId call_id);
Result<Ok> call_destroy_all(); Result<Ok> call_destroy_all();
// TODO: pull values from blockchain state
// 1. we have a lot of contacts with information about contacts
// 2. PublicKey -> info
// 3. UserId -> List<PublicKey>
// 4. api should check all signatures before saving data
// 5. it should also handle timestamp in signature to apply the latest info
// 6. Changes will be synchronized with blockchain
// 7. blockchain logic will be mostly hidden
// 1. One must synchronize state of blockchain
// 2. One may need to get proofs for keys from the server
// 3. One must save changes and handle races
// interesting moment - we may speculatively return new data if signature is checked
// But it becomes complicated, when we are talking about public key itself.
// one MUST NOT use public key in any way before it is saved into blockchain
// It is more or less OK do decrypt.
// It is NOT OK to encrypt.
// Case I am worried about - sever may send public keys of user and then it may refuse to save it into blockchain.
// What it means - we must persist public key before it is used
// TODO: maybe we could forbid usage of unchecked public keys?
//
// TODO: backup OR recovery key?
// Maybe we shouldn't keep the key on device AT ALL?
//
} // namespace tde2e_api } // namespace tde2e_api

View File

@ -11,21 +11,33 @@
namespace tde2e_api { namespace tde2e_api {
enum class ErrorCode : int { enum class ErrorCode : int {
UnknownError = 1, UnknownError = 100,
Any, Any = 101,
InvalidInput, InvalidInput = 102,
InvalidKeyId, InvalidKeyId = 103,
InvalidId, InvalidId = 104,
InvalidBlock, InvalidBlock = 200,
InvalidBlock_InvalidSignature, InvalidBlock_NoChanges = 201,
InvalidBlock_HashMismatch, InvalidBlock_InvalidSignature = 202,
InvalidBlock_HeightMismatch, InvalidBlock_HashMismatch = 203,
InvalidBlock_InvalidStateProof_Group, InvalidBlock_HeightMismatch = 204,
InvalidBlock_InvalidStateProof_Secret, InvalidBlock_InvalidStateProof_Group = 205,
InvalidBlock_NoPermissions, InvalidBlock_InvalidStateProof_Secret = 206,
InvalidBlock_InvalidGroupState, InvalidBlock_NoPermissions = 207,
Decrypt_UnknownEpoch, InvalidBlock_InvalidGroupState = 208,
Encrypt_UnknownEpoch, InvalidCallGroupState_NotParticipant = 300,
InvalidCallGroupState_WrongUserId = 301,
Decrypt_UnknownEpoch = 400,
Encrypt_UnknownEpoch = 401,
InvalidBroadcast_InFuture = 500,
InvalidBroadcast_NotInCommit = 501,
InvalidBroadcast_NotInReveal = 502,
InvalidBroadcast_UnknownUserId = 503,
InvalidBroadcast_AlreadyApplied = 504,
InvalidBroadcast_InvalidReveal = 505,
InvalidBroadcast_InvalidBlockHash = 506,
InvalidCallChannelId = 600,
CallFailed = 601
}; };
inline std::string_view error_string(ErrorCode error_code) { inline std::string_view error_string(ErrorCode error_code) {
switch (error_code) { switch (error_code) {
@ -41,6 +53,8 @@ inline std::string_view error_string(ErrorCode error_code) {
return "INVALID_ID"; return "INVALID_ID";
case ErrorCode::InvalidBlock: case ErrorCode::InvalidBlock:
return "INVALID_BLOCK"; return "INVALID_BLOCK";
case ErrorCode::InvalidBlock_NoChanges:
return "INVALID_BLOCK__NO_CHANGES";
case ErrorCode::InvalidBlock_InvalidSignature: case ErrorCode::InvalidBlock_InvalidSignature:
return "INVALID_BLOCK__INVALID_SIGNATURE"; return "INVALID_BLOCK__INVALID_SIGNATURE";
case ErrorCode::InvalidBlock_HashMismatch: case ErrorCode::InvalidBlock_HashMismatch:
@ -55,10 +69,32 @@ inline std::string_view error_string(ErrorCode error_code) {
return "INVALID_BLOCK__INVALID_GROUP_STATE"; return "INVALID_BLOCK__INVALID_GROUP_STATE";
case ErrorCode::InvalidBlock_NoPermissions: case ErrorCode::InvalidBlock_NoPermissions:
return "INVALID_BLOCK__NO_PERMISSIONS"; return "INVALID_BLOCK__NO_PERMISSIONS";
case ErrorCode::InvalidCallGroupState_NotParticipant:
return "INVALID_CALL_GROUP_STATE__NOT_PARTICIPANT";
case ErrorCode::InvalidCallGroupState_WrongUserId:
return "INVALID_CALL_GROUP_STATE__WRONG_USER_ID";
case ErrorCode::Decrypt_UnknownEpoch: case ErrorCode::Decrypt_UnknownEpoch:
return "DECRYPT__UNKNOWN_EPOCH"; return "DECRYPT__UNKNOWN_EPOCH";
case ErrorCode::Encrypt_UnknownEpoch: case ErrorCode::Encrypt_UnknownEpoch:
return "ENCRYPT__UNKNOWN_EPOCH"; return "ENCRYPT__UNKNOWN_EPOCH";
case ErrorCode::InvalidBroadcast_InFuture:
return "INVALID_BROADCAST__IN_FUTURE";
case ErrorCode::InvalidBroadcast_NotInCommit:
return "INVALID_BROADCAST__NOT_IN_COMMIT";
case ErrorCode::InvalidBroadcast_NotInReveal:
return "INVALID_BROADCAST__NOT_IN_REVEAL";
case ErrorCode::InvalidBroadcast_UnknownUserId:
return "INVALID_BROADCAST__UNKNOWN_USER_ID";
case ErrorCode::InvalidBroadcast_AlreadyApplied:
return "INVALID_BROADCAST__ALREADY_APPLIED";
case ErrorCode::InvalidBroadcast_InvalidReveal:
return "INVALID_BROADCAST__INVALID_REVEAL";
case ErrorCode::InvalidBroadcast_InvalidBlockHash:
return "INVALID_BROADCAST__INVALID_BLOCK_HASH";
case ErrorCode::CallFailed:
return "CALL_FAILED";
case ErrorCode::InvalidCallChannelId:
return "INVALID_CALL_CHANNEL_ID";
} }
return "UNKNOWN_ERROR"; return "UNKNOWN_ERROR";
} }

View File

@ -23,6 +23,31 @@
#include <string> #include <string>
#include <utility> #include <utility>
namespace tde2e_api {
inline Error to_error(const td::Status &status) {
auto error_code = ErrorCode(status.code());
if (error_string(error_code) == "UNKNOWN_ERROR") {
return Error{ErrorCode::UnknownError, status.message().str()};
}
return Error{error_code, status.message().str()};
}
template <class T>
Result<T> to_result(td::Result<T> &value) {
if (value.is_ok()) {
return Result<T>(value.move_as_ok());
}
return Result<T>(to_error(value.error()));
}
template <typename T>
Result<T>::Result(td::Result<T> &&value) : Result(to_result(value)) {
}
template <typename T>
Result<T>::Result(td::Status &&status) : Result(to_error(status)) {
}
} // namespace tde2e_api
namespace tde2e_core { namespace tde2e_core {
using E = tde2e_api::ErrorCode; using E = tde2e_api::ErrorCode;

View File

@ -0,0 +1,78 @@
#pragma once
#include <string>
#include <vector>
namespace tde2e_core {
struct TestVector {
std::string name;
std::string secret;
std::string data;
std::string header;
std::string encrypted;
std::string encrypted_header;
};
inline std::vector<TestVector> get_test_vectors() {
return {
{
"empty_message",
"5a08a19b447df98136a4502e01b286011b2d148084a7ca17e3a93616d279eb2a",
"",
"a36c57ad5e8d6a30e80e010ab903b60da0206db1b4fd981cd61e059bbd8c0d4f",
"9e2476ad849d22a44d9135c5c3c5e8b52d4f88473ae8745f3a9cec4d54780caf",
"de3539a5e10b20a3a0cffc24dbbd76b3a7e0eeab402cb38396d64785a3ab7c25"
},
{
"simple_message",
"5a08a19b447df98136a4502e01b286011b2d148084a7ca17e3a93616d279eb2a",
"48656c6c6f2c20576f726c6421",
"a36c57ad5e8d6a30e80e010ab903b60da0206db1b4fd981cd61e059bbd8c0d4f",
"872b141f6d1e3554ead471dffd0fee5c04a0b04260eafcca9187158ce84c4487e9429df876706753913de61029402478",
"013037e02dc8dbf13598d96eb333a69a930efe043bac7dce0d6edfd1abc6bd2f"
},
{
"long_message",
"5a08a19b447df98136a4502e01b286011b2d148084a7ca17e3a93616d279eb2a",
"7878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878",
"a36c57ad5e8d6a30e80e010ab903b60da0206db1b4fd981cd61e059bbd8c0d4f",
"0fd497802c755b9c6fb9d58d38b9fb5fbd7dc9ccf78af3eb003a22d46bfa38894135d976bbec0f3cadc2b61a4d8648120dada26b2c3153def20fb9e370def31c802e202846946b5cb1bc2c01a7b46605292d6043ffb8f4040aaf18914e1c93fe9e683f088e23ee5e1551f00068a23fa3ebb8d6b9dcbf7a9072b12323b1a64247ba9bc7d277b08cfcc37387a0d24afca170dc027d8f0212eb62bccd9555de98936047c9bfc6a03aa539073f458795bd94b9b43003fe2299805f90c1d30ca631c8054242687e41e890bf4d744b529d7e96ea48a5bcec700993b5e980173049cf9df6f93d62ccc06d933fd6d7063890fa2d",
"697558ba60e789622ee90dffc55f1f1148cfea568c573b257fcf2083cf8aad0a"
},
{
"random_message",
"5a08a19b447df98136a4502e01b286011b2d148084a7ca17e3a93616d279eb2a",
"e61d2b05302c49faa9fac6a893957a846a2b30801dc171cf62ffec92297b10bfc4a82445839ecb4c5800ffb37c5356d4b95fc565ddb2e7f3e21f2936a952373c",
"a36c57ad5e8d6a30e80e010ab903b60da0206db1b4fd981cd61e059bbd8c0d4f",
"515f0223f27302ca5e952ec978ec66bcdf04e7f72ae3a8e011e21457b355891d12e158c9b2dfb921520a0e5f531e6a20e95d42635b084a0b38a6e658f4a4181f85ea83756d316cea538cc34592491eef3e3530c34c63a693e3372cbdd0076628",
"b5bdfe6a3400c5d299d94756af4c18bbb8cca4a2635beeba3d89bbaa0025d9d3"
},
{
"very_long_message",
"5a08a19b447df98136a4502e01b286011b2d148084a7ca17e3a93616d279eb2a",
"de6e0dbde23e04b6be3d4c46868a1171c6b879227b19e370765823390501b195783c356af2156e828e511473d5698c9bd1cb4a70b7e209bbb02f8dda044af02ab6869478b211e3a17d72fbe6289c1b2e6132cb141e89cf72cf70defd67a23fbfe8e718a09a9c6a345565ebdc73e1f59927744801eb4e6f0b30d2705ea181e02a4030252330ac73bc4a4d51d2ccafb2f3f62abe3e81163be325ac823571c8dfae739f70bff39164e3cec7f53b88f97735dc25ac0c0630b1b41a131a979ba5164ab92e103716e9096e2fb5a6434b31d2c3673fca7e54dcdcce3807bfd43ee7bc3422868094305a9847ce7666bf57e49fb3c2009cb30eb3ba955942b923ec2c2a4e0341d86b524b198974bdce9cf863ab3526e9e03e53399dad20fc218554567c440536a31e05573f4cb930ba6a",
"a36c57ad5e8d6a30e80e010ab903b60da0206db1b4fd981cd61e059bbd8c0d4f",
"e296a98cd96154b27d4b94cc520a8f028c61bd5ea69d22f0c3c13658c4bd5db0bd6661d0d17fac791c5cc06b3a54a853916bd7bf8a00644acc53cca43b6f51c66bc6a6cb98cf8d9f23dcd639089d1d9d3dfbc8829a1a81638317bbd3edb070c1dae181d97605eb42a6111b8696a16cc3e42639e38e93f872111fd67e934740f73a57df0e6edc6726c9aff99682bfcb7ddd99a3bef30da70d3c21e590fd02defc23be9f7f243e45a56b13562b8ecea09a14ac5af3a0500cb52f73f1bffea4a6624644da0bc4d112e5ee684b13a2ae8dbf401a5a8e581295a9dc876eaeb8ae4d732fb78d50a92c302d15c0a2308e43fc6e147ec162b28a534d6c95a2020fa141f3ce7f7dd25ff000d35f732a145abf31b3ff4d0da015d39da3b0fc70e692b567a9507be59e8c91a63fe809c495d76e70ec857cc24978771fc9314251e2bc4b1b24e0448514f97a6d438255cba8c1854019",
"8dab56b50ce6a4315b6e0b4eb32c39dfe817cb462ee9e070e2a60bb843c16107"
},
{
"message_with_special_chars",
"5a08a19b447df98136a4502e01b286011b2d148084a7ca17e3a93616d279eb2a",
"2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
"a36c57ad5e8d6a30e80e010ab903b60da0206db1b4fd981cd61e059bbd8c0d4f",
"2014d1125081316a334896cbe5aed251d9fba6f3422afbc7e7bc9019e10e184241d18f71ef86603b5ce03e1c351e3dfff8adfb8f3498300a712ec134b367c533",
"6f5a5de410db3606ff94fa14d0e084a6ba5a51241a2abf45ac593e4748c477ce"
},
{
"message_with_unicode",
"5a08a19b447df98136a4502e01b286011b2d148084a7ca17e3a93616d279eb2a",
"48656c6c6f2c20e4b896e7958c21",
"a36c57ad5e8d6a30e80e010ab903b60da0206db1b4fd981cd61e059bbd8c0d4f",
"7ae70cb905f23109477b4d758d3907238ff4c37e2f351f086268ba3e85cef0257af58a70d8838c7b9c044f30382c2ccf",
"7dfb2d2e76df39b2fafdf01de009088a7e4d045b8630941986111ef2010d7c4a"
},
};
}
} // namespace tde2e_core

View File

@ -95,7 +95,7 @@ class StatusTest : public Test {
LOG(INFO) << "Test " << get_test_name() << " PASSED"; LOG(INFO) << "Test " << get_test_name() << " PASSED";
} else { } else {
// Include debug context in error message if available // Include debug context in error message if available
LOG(ERROR) << "Test " << get_test_name() << " FAILED: " << status.message() LOG(FATAL) << "Test " << get_test_name() << " FAILED: " << status.message()
<< simple_test::DebugContext::instance(); << simple_test::DebugContext::instance();
} }
} }

View File

@ -1,24 +1,43 @@
#!/bin/bash #!/bin/bash
# Usage: ./keep_headers.sh /path/to/your/folder # Usage: ./macos-copy-and-cleanup.sh /source/folder /target/folder
TARGET_DIR="$1" SOURCE_DIR="$1"
TARGET_DIR="$2"
if [ -z "$TARGET_DIR" ]; then if [ -z "$SOURCE_DIR" ] || [ -z "$TARGET_DIR" ]; then
echo "Usage: $0 /path/to/your/folder" echo "Usage: $0 /source/folder /target/folder"
exit 1 exit 1
fi fi
# Ensure the path exists # Ensure source exists
if [ ! -d "$TARGET_DIR" ]; then if [ ! -d "$SOURCE_DIR" ]; then
echo "Directory not found: $TARGET_DIR" echo "Source directory not found: $SOURCE_DIR"
exit 1 exit 1
fi fi
# Find and delete everything except .h files # Clean up the entire target folder first
find "$TARGET_DIR" \( ! -name "*.h" -a ! -type d \) -delete if [ -d "$TARGET_DIR" ]; then
echo "Cleaning target directory: $TARGET_DIR"
rm -rf "$TARGET_DIR"
fi
# Remove empty directories (excluding root) # Recreate the target directory
find "$TARGET_DIR" -type d -empty -not -path "$TARGET_DIR" -delete mkdir -p "$TARGET_DIR"
echo "Cleanup completed. Only .h files remain." # Get the base folder name from the source (e.g., "td")
SOURCE_BASENAME=$(basename "$SOURCE_DIR")
# Copy the entire source folder into the target
cp -R "$SOURCE_DIR" "$TARGET_DIR/"
# Path to the copied folder
COPIED_DIR="$TARGET_DIR/$SOURCE_BASENAME"
# Delete everything inside the copied folder except .h files
find "$COPIED_DIR" \( ! -name "*.h" -a ! -type d \) -delete
# Remove all empty directories inside, except the root
find "$COPIED_DIR" -type d -empty -not -path "$COPIED_DIR" -delete
echo "✅ Copied $SOURCE_BASENAME into $TARGET_DIR and kept only .h files."