From f088d0ab8b5a4bba363112cce913458c58a57393 Mon Sep 17 00:00:00 2001 From: frtget <96221162+frtget@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:54:03 -0400 Subject: [PATCH 1/9] keys config C API fixes - typo in function name - return false when subaccount signing value verification throws --- src/config/groups/keys.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/config/groups/keys.cpp b/src/config/groups/keys.cpp index 5bb1e1e5..9441fc1b 100644 --- a/src/config/groups/keys.cpp +++ b/src/config/groups/keys.cpp @@ -1437,7 +1437,7 @@ LIBSESSION_C_API size_t groups_keys_size(const config_group_keys* conf) { return unbox(conf).size(); } -LIBSESSION_C_API const unsigned char* group_keys_get_key(const config_group_keys* conf, size_t N) { +LIBSESSION_C_API const unsigned char* groups_keys_get_key(const config_group_keys* conf, size_t N) { auto keys = unbox(conf).group_keys(); if (N >= keys.size()) return nullptr; @@ -1655,10 +1655,14 @@ LIBSESSION_C_API bool groups_keys_swarm_verify_subaccount( const char* group_id, const unsigned char* session_ed25519_secretkey, const unsigned char* signing_value) { - return groups::Keys::swarm_verify_subaccount( - group_id, - ustring_view{session_ed25519_secretkey, 64}, - ustring_view{signing_value, 100}); + try { + return groups::Keys::swarm_verify_subaccount( + group_id, + ustring_view{session_ed25519_secretkey, 64}, + ustring_view{signing_value, 100}); + } catch (...) { + return false; + } } LIBSESSION_C_API bool groups_keys_swarm_subaccount_sign( From 98e5b5b750463e5e06ca728e584919f19669effc Mon Sep 17 00:00:00 2001 From: frtget <96221162+frtget@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:54:08 -0400 Subject: [PATCH 2/9] reserve enough memory to avoid extra copies in Keys::group_keys() when there is a pending key --- src/config/groups/keys.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/groups/keys.cpp b/src/config/groups/keys.cpp index 9441fc1b..f6a5a2ea 100644 --- a/src/config/groups/keys.cpp +++ b/src/config/groups/keys.cpp @@ -188,7 +188,7 @@ size_t Keys::size() const { std::vector Keys::group_keys() const { std::vector ret; - ret.reserve(size()); + ret.reserve(size() + !pending_key_config_.empty()); if (!pending_key_config_.empty()) ret.emplace_back(pending_key_.data(), 32); From 60fbd697a03630616eaefeffbb9e3a1d08ad6525 Mon Sep 17 00:00:00 2001 From: frtget <96221162+frtget@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:54:13 -0400 Subject: [PATCH 3/9] try decrypting messages with most recent keys first --- src/config/groups/keys.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/groups/keys.cpp b/src/config/groups/keys.cpp index f6a5a2ea..11323b54 100644 --- a/src/config/groups/keys.cpp +++ b/src/config/groups/keys.cpp @@ -1273,8 +1273,8 @@ std::pair Keys::decrypt_message(ustring_view ciphertext) c pending && try_decrypting(plain.data(), ciphertext, nonce, *pending)) { decrypt_success = true; } else { - for (auto& k : keys_) { - if (try_decrypting(plain.data(), ciphertext, nonce, k.key)) { + for (auto it = keys_.rbegin(); it != keys_.rend(); ++it) { + if (try_decrypting(plain.data(), ciphertext, nonce, it->key)) { decrypt_success = true; break; } From 6d3625200f87ac4642a1d79258272b08d3eccda3 Mon Sep 17 00:00:00 2001 From: frtget <96221162+frtget@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:54:18 -0400 Subject: [PATCH 4/9] make sure we use different hash keys in different contexts --- src/config/groups/keys.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/config/groups/keys.cpp b/src/config/groups/keys.cpp index 11323b54..c6c7d45d 100644 --- a/src/config/groups/keys.cpp +++ b/src/config/groups/keys.cpp @@ -425,6 +425,9 @@ ustring Keys::sign(ustring_view data) const { return sig; } +static constexpr auto nonce_seed_hash_key = "SessionGroupNonceSeed"sv; +static const ustring_view nonce_hash_key = to_unsigned_sv("SessionGroupNonceGen"sv); + ustring Keys::key_supplement(const std::vector& sids) const { if (!admin()) throw std::logic_error{ @@ -451,12 +454,12 @@ ustring Keys::key_supplement(const std::vector& sids) const { // H1(member0 || member1 || ... || memberN || keysdata || H2(group_secret_key)) // // where: - // - H1(.) = 24-byte BLAKE2b keyed hash with key "SessionGroupKeyGen" + // - H1(.) = 24-byte BLAKE2b keyed hash with key "SessionGroupNonceGen" // - memberI is the full session ID of each member included in this key update, expressed in hex // (66 chars), in sorted order. // - keysdata is the unencrypted inner value that we are encrypting for each supplemental member // - H2(.) = 32-byte BLAKE2b keyed hash of the sodium group secret key seed (just the 32 byte, - // not the full 64 byte with the pubkey in the second half), key "SessionGroupKeySeed" + // not the full 64 byte with the pubkey in the second half), key "SessionGroupNonceSeed" std::string supp_keys; { @@ -479,14 +482,14 @@ ustring Keys::key_supplement(const std::vector& sids) const { crypto_generichash_blake2b_state st; crypto_generichash_blake2b_init( - &st, enc_key_hash_key.data(), enc_key_hash_key.size(), h1.size()); + &st, nonce_hash_key.data(), nonce_hash_key.size(), h1.size()); for (const auto& sid : sids) crypto_generichash_blake2b_update(&st, to_unsigned(sid.data()), sid.size()); crypto_generichash_blake2b_update(&st, to_unsigned(supp_keys.data()), supp_keys.size()); - std::array h2 = seed_hash(seed_hash_key); + std::array h2 = seed_hash(nonce_seed_hash_key); crypto_generichash_blake2b_update(&st, h2.data(), h2.size()); crypto_generichash_blake2b_final(&st, h1.data(), h1.size()); @@ -552,12 +555,14 @@ ustring Keys::key_supplement(const std::vector& sids) const { return ustring{to_unsigned_sv(d.view())}; } +static constexpr auto subaccount_mask_hash_key = "SessionGroupSubaccountMask"sv; + // Blinding factor for subaccounts: H(sessionid || groupid) mod L, where H is 64-byte blake2b, using // a hash key derived from the group's seed. std::array Keys::subaccount_blind_factor( const std::array& session_xpk) const { - auto mask = seed_hash("SessionGroupSubaccountMask"); + auto mask = seed_hash(subaccount_mask_hash_key); static_assert(mask.size() == crypto_generichash_blake2b_KEYBYTES); std::array h; @@ -669,6 +674,9 @@ ustring Keys::swarm_subaccount_token(std::string_view session_id, bool write, bo return out; } +static constexpr auto subaccount_seed_hash_key = "SubaccountSeed"sv; +static constexpr auto r_hash_key = "SubaccountSig"sv; + Keys::swarm_auth Keys::swarm_subaccount_sign( ustring_view msg, ustring_view sign_val, bool binary) const { if (sign_val.size() != 100) @@ -737,16 +745,14 @@ Keys::swarm_auth Keys::swarm_subaccount_sign( // // (using the standard Ed25519 SHA-512 here for H) - constexpr auto seed_hash_key = "SubaccountSeed"sv; - constexpr auto r_hash_key = "SubaccountSig"sv; std::array hseed; crypto_generichash_blake2b( hseed.data(), hseed.size(), user_ed25519_sk.data(), 32, - to_unsigned(seed_hash_key.data()), - seed_hash_key.size()); + to_unsigned(subaccount_seed_hash_key.data()), + subaccount_seed_hash_key.size()); std::array tmp; crypto_generichash_blake2b_state st; From cbf4f0a7be8f0a0d95991d4f96b18c294b9f43b1 Mon Sep 17 00:00:00 2001 From: frtget <96221162+frtget@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:54:23 -0400 Subject: [PATCH 5/9] fix broken sodium_ptr template and non-trivially-copyable type copy in sodium_array::load we never enter the for loop in sodium_array::load because len is always equal to length after calling reset(length) --- include/session/util.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/session/util.hpp b/include/session/util.hpp index 5e906a6a..27111788 100644 --- a/include/session/util.hpp +++ b/include/session/util.hpp @@ -83,7 +83,7 @@ struct sodium_ptr { public: sodium_ptr() : x{nullptr} {} sodium_ptr(std::nullptr_t) : sodium_ptr{} {} - ~sodium_ptr() { reset(x); } + ~sodium_ptr() { reset(); } // Allocates and constructs a new `T` in-place, forwarding any given arguments to the `T` // constructor. If this sodium_ptr already has an object, `reset()` is first called implicitly @@ -225,7 +225,7 @@ struct sodium_array { if constexpr (std::is_trivially_copyable_v) std::memcpy(buf, data, sizeof(T) * length); else - for (; len < length; len++) + for (len = 0; len < length; len++) new (buf[len]) T(data[len]); } From 7755f676f7e97875179d011ce5f8b38bbf7afd44 Mon Sep 17 00:00:00 2001 From: frtget <96221162+frtget@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:54:28 -0400 Subject: [PATCH 6/9] remove unused variable --- src/config/base.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/config/base.cpp b/src/config/base.cpp index ae44ffcc..c9e49cd9 100644 --- a/src/config/base.cpp +++ b/src/config/base.cpp @@ -331,7 +331,6 @@ ustring ConfigBase::dump() { ustring ConfigBase::make_dump() const { auto data = _config->serialize(false /* disable signing for local storage */); auto data_sv = from_unsigned_sv(data); - oxenc::bt_list old_hashes; oxenc::bt_dict_producer d; d.append("!", static_cast(_state)); From 3d94b9ddaf476e14b0fcbb5384c4e9a698a3bbf4 Mon Sep 17 00:00:00 2001 From: frtget <96221162+frtget@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:54:34 -0400 Subject: [PATCH 7/9] fix some comments --- include/session/config/base.h | 4 ++-- include/session/config/contacts.h | 2 +- include/session/config/encrypt.h | 2 +- include/session/config/encrypt.hpp | 4 ++-- include/session/config/groups/info.h | 4 ++-- include/session/config/groups/info.hpp | 6 +++--- include/session/config/groups/keys.h | 2 +- include/session/config/groups/keys.hpp | 19 ++++++++++--------- include/session/config/groups/members.h | 9 +++++---- include/session/config/groups/members.hpp | 17 +++++++++-------- include/session/util.hpp | 2 +- src/config/groups/info.cpp | 2 +- src/config/groups/keys.cpp | 12 ++++++------ src/config/user_groups.cpp | 2 +- src/xed25519.cpp | 4 ++-- 15 files changed, 47 insertions(+), 44 deletions(-) diff --git a/include/session/config/base.h b/include/session/config/base.h index 8707d903..1569ff8d 100644 --- a/include/session/config/base.h +++ b/include/session/config/base.h @@ -105,7 +105,7 @@ typedef struct config_string_list { /// API: base/config_merge /// /// Merges the config object with one or more remotely obtained config strings. After this call the -/// config object may be unchanged, complete replaced, or updated and needing a push, depending on +/// config object may be unchanged, completely replaced, or updated and needing a push, depending on /// the messages that are merged; the caller should check config_needs_push(). /// /// Declaration: @@ -309,7 +309,7 @@ LIBSESSION_EXPORT config_string_list* config_current_hashes(const config_object* /// Inputs: /// - `conf` -- [in] Pointer to the config_object object /// - `len` -- [out] Pointer where the number of keys will be written (that is: the returned pointer -/// will be to a buffer which has a size of of this value times 32). +/// will be to a buffer which has a size of this value times 32). /// /// Outputs: /// - `unsigned char*` -- pointer to newly malloced key data (a multiple of 32 bytes); the pointer diff --git a/include/session/config/contacts.h b/include/session/config/contacts.h index 7c6bc0e4..50565ebc 100644 --- a/include/session/config/contacts.h +++ b/include/session/config/contacts.h @@ -160,7 +160,7 @@ LIBSESSION_EXPORT void contacts_set(config_object* conf, const contacts_contact* // contacts_contact c; // if (contacts_get_or_construct(conf, &c, some_session_id)) { // const char* new_nickname = "Joe"; -// c.approved = new_nickname; +// c.nickname = new_nickname; // contacts_set_or_create(conf, &c); // } else { // // some_session_id was invalid! diff --git a/include/session/config/encrypt.h b/include/session/config/encrypt.h index 9dbf6fa4..0cde3c71 100644 --- a/include/session/config/encrypt.h +++ b/include/session/config/encrypt.h @@ -27,7 +27,7 @@ extern "C" { /// ``` /// /// Inputs: -/// - `message` -- [in] The message to encrypted in binary +/// - `message` -- [in] The message to encrypt in binary /// - `mlen` -- [in] Length of the message provided /// - `key_base` -- [in] Key, must be binary /// - `domain` -- [in] Text diff --git a/include/session/config/encrypt.hpp b/include/session/config/encrypt.hpp index 1fd9c771..90f64a4d 100644 --- a/include/session/config/encrypt.hpp +++ b/include/session/config/encrypt.hpp @@ -29,7 +29,7 @@ namespace session::config { /// /// Inputs: /// - `message` -- message to encrypt -/// - `key_base` -- Fixed key that all clients, must be 32 bytes. +/// - `key_base` -- Fixed key that all clients can calculate independently, must be 32 bytes. /// - `domain` -- short string for the keyed hash /// /// Outputs: @@ -43,7 +43,7 @@ ustring encrypt(ustring_view message, ustring_view key_base, std::string_view do /// /// Inputs: /// - `message` -- message to encrypt -/// - `key_base` -- Fixed key that all clients, must be 32 bytes. +/// - `key_base` -- Fixed key that all clients can calculate independently, must be 32 bytes. /// - `domain` -- short string for the keyed hash void encrypt_inplace(ustring& message, ustring_view key_base, std::string_view domain); diff --git a/include/session/config/groups/info.h b/include/session/config/groups/info.h index 32da3ae9..0f18ec5a 100644 --- a/include/session/config/groups/info.h +++ b/include/session/config/groups/info.h @@ -116,7 +116,7 @@ LIBSESSION_EXPORT user_profile_pic groups_info_get_pic(const config_object* conf /// API: groups_info/groups_info_set_pic /// -/// Sets a user profile +/// Sets a profile picture /// /// Inputs: /// - `conf` -- [in] Pointer to the config object @@ -199,7 +199,7 @@ LIBSESSION_EXPORT void groups_info_set_delete_before(config_object* conf, int64_ /// - `conf` -- [in] Pointer to the config object /// /// Outputs: -/// - `int64_t` -- Unix timestamp before which messages should be deleted. Returns 0 if not set. +/// - `int64_t` -- Unix timestamp before which attachments should be deleted. Returns 0 if not set. LIBSESSION_EXPORT int64_t groups_info_get_attach_delete_before(const config_object* conf); /// API: groups_info/groups_info_set_attach_delete_before diff --git a/include/session/config/groups/info.hpp b/include/session/config/groups/info.hpp index 4010bf35..18a1740e 100644 --- a/include/session/config/groups/info.hpp +++ b/include/session/config/groups/info.hpp @@ -238,7 +238,7 @@ class Info final : public ConfigBase { /// Inputs: none. /// /// Outputs: - /// - `int64_t` -- the unix timestamp for which all older messages shall be delete + /// - `int64_t` -- the unix timestamp for which all older messages shall be deleted std::optional get_delete_before() const; /// API: groups/Info::set_delete_attach_before @@ -254,13 +254,13 @@ class Info final : public ConfigBase { /// Inputs: /// - `timestamp` -- the new unix timestamp before which clients should delete attachments. Pass /// 0 - /// (or negative) to disable the delete-attachment-before timestamp. + /// (or negative) to disable the delete-attachments-before timestamp. void set_delete_attach_before(int64_t timestamp); /// API: groups/Info::get_delete_attach_before /// /// Returns the delete-attachments-before unix timestamp (seconds) for the group; clients should - /// delete all messages from the closed group with timestamps earlier than this value, if set. + /// delete all attachments from the closed group with timestamps earlier than this value, if set. /// /// Returns std::nullopt if no delete-attachments-before timestamp is set. /// diff --git a/include/session/config/groups/keys.h b/include/session/config/groups/keys.h index 9dab2ac7..b8179535 100644 --- a/include/session/config/groups/keys.h +++ b/include/session/config/groups/keys.h @@ -111,7 +111,7 @@ LIBSESSION_EXPORT const unsigned char* groups_keys_get_key(const config_group_ke /// API: groups/groups_keys_is_admin /// /// Returns true if this object has the group private keys, i.e. the user is an all-powerful -/// wiz^H^H^Hadmin of the group. +/// admin of the group. /// /// Inputs: /// - `conf` -- the groups config object diff --git a/include/session/config/groups/keys.hpp b/include/session/config/groups/keys.hpp index f7dd59ff..df47d8ae 100644 --- a/include/session/config/groups/keys.hpp +++ b/include/session/config/groups/keys.hpp @@ -120,7 +120,7 @@ class Keys final : public ConfigSig { // Inserts a key into the correct place in `keys_`. void insert_key(std::string_view message_hash, key_info&& key); - // Returned the blinding factor for a given session X25519 pubkey. This depends on the group's + // Returns the blinding factor for a given session X25519 pubkey. This depends on the group's // seed and thus is only obtainable by an admin account. std::array subaccount_blind_factor( const std::array& session_xpk) const; @@ -134,7 +134,7 @@ class Keys final : public ConfigSig { // 75 because: // 2 // for the 'de' delimiters of the outer dict - // + 3 + 2 + 12 // for the `1:g` and `iNNNNNNNNNNe` generation keypair + // + 3 + 2 + 12 // for the `1:G` and `iNNNNNNNNNNe` generation keypair // + 3 + 3 + 24 // for the `1:n`, `24:`, and 24 byte nonce // + 3 + 3 + 48 // for the `1:K`, `48:`, and 48 byte ciphertexted key // + 3 + 6 // for the `1:k` and `NNNNN:` key and prefix of the keys pair @@ -158,10 +158,10 @@ class Keys final : public ConfigSig { /// API: groups/Keys::Keys /// - /// Constructs a group members config object from existing data (stored from `dump()`) and a + /// Constructs a group keys config object from existing data (stored from `dump()`) and a /// list of encryption keys for encrypting new and decrypting existing messages. /// - /// To construct a blank info object (i.e. with no pre-existing dumped data to load) pass + /// To construct a blank keys object (i.e. with no pre-existing dumped data to load) pass /// `std::nullopt` as the last argument. /// /// Inputs: @@ -169,8 +169,9 @@ class Keys final : public ConfigSig { /// and is used to decrypt incoming keys. It is required. /// - `group_ed25519_pubkey` is the public key of the group, used to verify message signatures /// on key updates. Required. Should not include the `03` prefix. - /// - `group_ed25519_secretkey` is the secret key of the group, used to encrypt, decrypt, and - /// sign config messages. This is only possessed by the group admin(s), and must be provided + /// - `group_ed25519_secretkey` is the secret key of the group, used to sign config messages and + /// swarm authentication tokens and to encrypt and decrypt encryption keys for regular messages. + /// This is only possessed by the group admin(s), and must be provided /// in order to make and push config changes. /// - `dumped` -- either `std::nullopt` to construct a new, empty object; or binary state data /// that was previously dumped from an instance of this class by calling `dump()`. @@ -322,7 +323,7 @@ class Keys final : public ConfigSig { /// /// Generates a supplemental key message for one or more session IDs. This is used to /// distribute existing active keys to a new member so that that member can access existing - /// keys, configs, and messages. Only admins can call this. + /// configs and messages. Only admins can call this. /// /// The recommended order of operations for adding such a member is: /// - add the member to Members @@ -374,7 +375,7 @@ class Keys final : public ConfigSig { /// (Internally this packs the flags, blinding factor, and group admin signature together and /// will be 4 + 32 + 64 = 100 bytes long). /// - /// This value must be provided to the user so that they can authentication. The user should + /// This value must be provided to the user so that they can authenticate. The user should /// call `swarm_verify_subaccount` to verify that the signing value was indeed signed by a /// group admin before using/storing it. /// @@ -579,7 +580,7 @@ class Keys final : public ConfigSig { /// call rekey()). Note that this value will also remain true until the pushed data is fetched /// and loaded via `load_key_message`. /// - /// Note that this not only tracks when an automatic `rekey()` is needed because of a key + /// Note that this only tracks when an automatic `rekey()` is needed because of a key /// collision (such as two admins removing different members at the same time); there are other /// situations in which rekey() should also be called (such as when kicking a member) that are /// not reflected by this flag. diff --git a/include/session/config/groups/members.h b/include/session/config/groups/members.h index a4624b7d..28082e0e 100644 --- a/include/session/config/groups/members.h +++ b/include/session/config/groups/members.h @@ -14,8 +14,9 @@ enum groups_members_remove_status { REMOVED_MEMBER = 1, REMOVED_MEMBER_AND_MESSA typedef struct config_group_member { char session_id[67]; // in hex; 66 hex chars + null terminator. - // These two will be 0-length strings when unset: + // This will be a 0-length string when unset: char name[101]; + user_profile_pic profile_pic; bool admin; @@ -131,7 +132,7 @@ LIBSESSION_EXPORT bool groups_members_erase(config_object* conf, const char* ses /// - `conf` -- input - Pointer to the config object /// /// Outputs: -/// - `size_t` -- number of contacts +/// - `size_t` -- number of members LIBSESSION_EXPORT size_t groups_members_size(const config_object* conf); typedef struct groups_members_iterator { @@ -146,8 +147,8 @@ typedef struct groups_members_iterator { /// /// group_member m; /// groups_members_iterator *it = groups_members_iterator_new(group); -/// for (; !groups_members_iterator_done(it, &c); groups_members_iterator_advance(it)) { -/// // c.session_id, c.name, etc. are loaded +/// for (; !groups_members_iterator_done(it, &m); groups_members_iterator_advance(it)) { +/// // m.session_id, m.name, etc. are loaded /// } /// groups_members_iterator_free(it); /// diff --git a/include/session/config/groups/members.hpp b/include/session/config/groups/members.hpp index 9a6dd4c5..5a4e4d20 100644 --- a/include/session/config/groups/members.hpp +++ b/include/session/config/groups/members.hpp @@ -112,7 +112,7 @@ struct member { /// that the invitation should be reissued). /// /// Inputs: - /// - `failed` can be specified and set to `true` to the invite status to "failed-to-send"; + /// - `failed` can be specified and set to `true` to set the invite status to "failed-to-send"; /// otherwise omitting it or giving as `false` sets the invite status to "sent." void set_invited(bool failed = false) { invite_status = failed ? INVITE_FAILED : INVITE_SENT; } @@ -276,11 +276,11 @@ class Members final : public ConfigBase { /// Constructs a group members config object from existing data (stored from `dump()`) and a /// list of encryption keys for encrypting new and decrypting existing messages. /// - /// To construct a blank info object (i.e. with no pre-existing dumped data to load) pass + /// To construct a blank members object (i.e. with no pre-existing dumped data to load) pass /// `std::nullopt` as the third argument. /// - /// Encryption keys must be loaded before the Info object can be modified or parse other Info - /// messages, and are typically loaded by providing the `Info` object to the `Keys` class. + /// Encryption keys must be loaded before the Members object can be modified or parse other Members + /// messages, and are typically loaded by providing the `Members` object to the `Keys` class. /// /// Inputs: /// - `ed25519_pubkey` is the public key of this group, used to validate config messages. @@ -371,13 +371,14 @@ class Members final : public ConfigBase { /// removed |= members.erase("050000111122223333..."); /// /// if (removed) { - /// auto new_keys_conf = keys.rekey(members); - /// members.add_key(*keys.pending_key(), true); - /// auto [seqno, new_memb_conf, obs] = members.push(); + /// auto new_keys_conf = keys.rekey(info, members); + /// auto [members_seqno, new_memb_conf, members_obs] = members.push(); + /// auto [info_seqno, new_info_conf, info_obs] = info.push(); /// - /// // Send the two new configs to the swarm (via a seqence of two `store`s): + /// // Send the three new configs to the swarm (via a sequence of three `store`s): /// // - new_keys_conf goes into the keys namespace /// // - new_memb_conf goes into the members namespace + /// // - new_info_conf goes into the info namespace /// } /// /// Inputs: diff --git a/include/session/util.hpp b/include/session/util.hpp index 27111788..fceb1818 100644 --- a/include/session/util.hpp +++ b/include/session/util.hpp @@ -214,7 +214,7 @@ struct sodium_array { } // Loads the array from a pointer and size; this first resets a value (if present), allocates a - // new array of the given size, the copies the given value(s) into the new buffer. T must be + // new array of the given size, then copies the given value(s) into the new buffer. T must be // copyable. This is *not* safe to use if `buf` points into the currently allocated data. template >> void load(const T* data, size_t length) { diff --git a/src/config/groups/info.cpp b/src/config/groups/info.cpp index 88b3a1eb..098d5c4e 100644 --- a/src/config/groups/info.cpp +++ b/src/config/groups/info.cpp @@ -344,7 +344,7 @@ LIBSESSION_C_API void groups_info_set_delete_before(config_object* conf, int64_t /// - `conf` -- [in] Pointer to the config object /// /// Outputs: -/// - `int64_t` -- Unix timestamp before which messages should be deleted. Returns 0 if not set. +/// - `int64_t` -- Unix timestamp before which attachments should be deleted. Returns 0 if not set. LIBSESSION_C_API int64_t groups_info_get_attach_delete_before(const config_object* conf) { return unbox(conf)->get_delete_attach_before().value_or(0); } diff --git a/src/config/groups/keys.cpp b/src/config/groups/keys.cpp index c6c7d45d..eee68033 100644 --- a/src/config/groups/keys.cpp +++ b/src/config/groups/keys.cpp @@ -548,7 +548,7 @@ ustring Keys::key_supplement(const std::vector& sids) const { d.append("G", keys_.back().generation); - // Finally we sign the message at put it as the ~ key (which is 0x7e, and thus comes later than + // Finally we sign the message and put the signature as the ~ key (which is 0x7e, and thus comes later than // any other printable ascii key). d.append_signature("~", [this](ustring_view to_sign) { return sign(to_sign); }); @@ -581,7 +581,7 @@ std::array Keys::subaccount_blind_factor( namespace { - // These constants are defined and explains in more detail in oxen-storage-server + // These constants are defined and explained in more detail in oxen-storage-server constexpr unsigned char SUBACC_FLAG_READ = 0b0001; constexpr unsigned char SUBACC_FLAG_WRITE = 0b0010; constexpr unsigned char SUBACC_FLAG_DEL = 0b0100; @@ -708,7 +708,7 @@ Keys::swarm_auth Keys::swarm_subaccount_sign( // token is now set: flags || kT ustring_view kT{to_unsigned(token.data() + 4), 32}; - // sub_sig is just the admin's signature, sitting at the end of sign_val (after 4f || k): + // sub_sig is just the admin's signature, sitting at the end of sign_val (after p || f || 0 || 0 || k): sub_sig = from_unsigned_sv(sign_val.substr(36)); // Our signing private scalar is kt, where t = ±s according to whether we had to negate S to @@ -723,7 +723,7 @@ Keys::swarm_auth Keys::swarm_subaccount_sign( std::array kt; crypto_core_ed25519_scalar_mul(kt.data(), k.data(), t.data()); - // We now have kt, kT, our privkey/public. (Note that kt is a scalar, not a seed). + // We now have kt, kT, our private/public keypair. (Note that kt is a scalar, not a seed). // We're going to get *close* to standard Ed25519 here, except: // @@ -986,7 +986,7 @@ bool Keys::load_key_message( // and t are 0 for some reason) of: // d -- 1 // 1:k 32:... -- +38 - // 1:g i1e -- + 6 + // 1:g iXe -- + 6 // 1:t iXe -- + 6 // e + 1 // --- @@ -1173,7 +1173,7 @@ void Keys::remove_expired() { active_msgs_.erase( active_msgs_.begin(), active_msgs_.lower_bound(keys_.front().generation)); else - // Keys is empty, which means we aren't keep *any* keys around (or they are all invalid or + // Keys is empty, which means we aren't keeping *any* keys around (or they are all invalid or // something) and so it isn't really up to us to keep them alive, since that's a history of // the group we apparently don't have access to. active_msgs_.clear(); diff --git a/src/config/user_groups.cpp b/src/config/user_groups.cpp index 9b08aa0c..0f683f00 100644 --- a/src/config/user_groups.cpp +++ b/src/config/user_groups.cpp @@ -560,7 +560,7 @@ bool UserGroups::iterator::check_it() { /// Load _val from the current iterator position; if it is invalid, skip to the next key until /// we find one that is valid (or hit the end). We also span across three different iterators: -/// first we exhaust communities, then legacy groups. +/// first we exhaust groups, then communities, then legacy groups. /// /// We *always* call this after incrementing the iterators (and after iterator initialization), /// and this is responsible for making sure that the the _it variables are set up as required. diff --git a/src/xed25519.cpp b/src/xed25519.cpp index e885ff1a..66663242 100644 --- a/src/xed25519.cpp +++ b/src/xed25519.cpp @@ -35,7 +35,7 @@ namespace { // secret key) we instead calculate `r = H(a || M || Z) mod L`. // // This deviates from Signal's XEd25519 specified derivation of r in that we use a personalized - // Black2b hash (for better performance and cryptographic properties), rather than a + // Blake2b hash (for better performance and cryptographic properties), rather than a // custom-prefixed SHA-512 hash. bytes<32> xed25519_compute_r(const bytes<32>& a, ustring_view msg) { bytes<64> random; @@ -97,7 +97,7 @@ bytes<64> sign(ustring_view curve25519_privkey, ustring_view msg) { crypto_core_ed25519_scalar_negate(neg_a.data(), a.data()); constant_time_conditional_assign(a, neg_a, negative); - // We now have our a, A privkey/public. (Note that a is just the private key scalar, *not* the + // We now have our a, A private/public keypair. (Note that a is just the private key scalar, *not* the // ed25519 secret key). bytes<32> r = xed25519_compute_r(a, msg); From 3e2407d7656c7145444772bbd6f4ccdf3d88f088 Mon Sep 17 00:00:00 2001 From: frtget <96221162+frtget@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:54:39 -0400 Subject: [PATCH 8/9] remove unnecessary includes and type aliases --- include/session/config/groups/info.h | 1 - include/session/config/groups/keys.hpp | 1 - include/session/xed25519.hpp | 4 ++-- src/config/contacts.cpp | 2 -- src/config/groups/info.cpp | 1 - src/xed25519.cpp | 2 +- tests/test_xed25519.cpp | 2 +- tests/utils.hpp | 6 +++--- 8 files changed, 7 insertions(+), 12 deletions(-) diff --git a/include/session/config/groups/info.h b/include/session/config/groups/info.h index 0f18ec5a..507939ce 100644 --- a/include/session/config/groups/info.h +++ b/include/session/config/groups/info.h @@ -6,7 +6,6 @@ extern "C" { #include "../base.h" #include "../profile_pic.h" -#include "../util.h" LIBSESSION_EXPORT extern const size_t GROUP_INFO_NAME_MAX_LENGTH; LIBSESSION_EXPORT extern const size_t GROUP_INFO_DESCRIPTION_MAX_LENGTH; diff --git a/include/session/config/groups/keys.hpp b/include/session/config/groups/keys.hpp index df47d8ae..b1dd3ff4 100644 --- a/include/session/config/groups/keys.hpp +++ b/include/session/config/groups/keys.hpp @@ -7,7 +7,6 @@ #include "../../config.hpp" #include "../base.hpp" #include "../namespaces.hpp" -#include "../profile_pic.hpp" #include "members.hpp" namespace session::config::groups { diff --git a/include/session/xed25519.hpp b/include/session/xed25519.hpp index e389e9d0..3c6fe9ab 100644 --- a/include/session/xed25519.hpp +++ b/include/session/xed25519.hpp @@ -3,9 +3,9 @@ #include #include -namespace session::xed25519 { +#include "session/types.hpp" -using ustring_view = std::basic_string_view; +namespace session::xed25519 { /// XEd25519-signs a message given the curve25519 privkey and message. std::array sign( diff --git a/src/config/contacts.cpp b/src/config/contacts.cpp index fa61e1ed..af44f06b 100644 --- a/src/config/contacts.cpp +++ b/src/config/contacts.cpp @@ -7,10 +7,8 @@ #include "internal.hpp" #include "session/config/contacts.h" -#include "session/config/error.h" #include "session/export.h" #include "session/types.hpp" -#include "session/util.hpp" using namespace std::literals; using namespace session::config; diff --git a/src/config/groups/info.cpp b/src/config/groups/info.cpp index 098d5c4e..db2fdc14 100644 --- a/src/config/groups/info.cpp +++ b/src/config/groups/info.cpp @@ -10,7 +10,6 @@ #include "session/config/groups/info.h" #include "session/export.h" #include "session/types.hpp" -#include "session/util.hpp" using namespace std::literals; diff --git a/src/xed25519.cpp b/src/xed25519.cpp index 66663242..2b2c0426 100644 --- a/src/xed25519.cpp +++ b/src/xed25519.cpp @@ -151,7 +151,7 @@ std::string pubkey(std::string_view curve25519_pubkey) { } // namespace session::xed25519 -using session::xed25519::ustring_view; +using session::ustring_view; extern "C" { diff --git a/tests/test_xed25519.cpp b/tests/test_xed25519.cpp index 67089302..3967208d 100644 --- a/tests/test_xed25519.cpp +++ b/tests/test_xed25519.cpp @@ -7,7 +7,7 @@ #include "session/xed25519.h" #include "session/xed25519.hpp" -using session::xed25519::ustring_view; +using session::ustring_view; constexpr std::array seed1{ 0xfe, 0xcd, 0x9a, 0x60, 0x34, 0xbc, 0x9a, 0xba, 0x27, 0x39, 0x25, 0xde, 0xe7, diff --git a/tests/utils.hpp b/tests/utils.hpp index 76b145c1..5d1e1c1b 100644 --- a/tests/utils.hpp +++ b/tests/utils.hpp @@ -10,10 +10,10 @@ #include #include -#include "session/config/base.h" +#include "session/types.hpp" -using ustring = std::basic_string; -using ustring_view = std::basic_string_view; +using session::ustring; +using session::ustring_view; inline ustring operator""_bytes(const char* x, size_t n) { return {reinterpret_cast(x), n}; From 89c631efd4e31e177c6953269d7f038118ebeaf7 Mon Sep 17 00:00:00 2001 From: frtget <96221162+frtget@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:54:44 -0400 Subject: [PATCH 9/9] format --- include/session/config/groups/info.hpp | 3 ++- include/session/config/groups/keys.hpp | 3 ++- include/session/config/groups/members.hpp | 5 +++-- src/config/groups/keys.cpp | 19 ++++++++++--------- src/xed25519.cpp | 4 ++-- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/include/session/config/groups/info.hpp b/include/session/config/groups/info.hpp index 18a1740e..5e144a93 100644 --- a/include/session/config/groups/info.hpp +++ b/include/session/config/groups/info.hpp @@ -260,7 +260,8 @@ class Info final : public ConfigBase { /// API: groups/Info::get_delete_attach_before /// /// Returns the delete-attachments-before unix timestamp (seconds) for the group; clients should - /// delete all attachments from the closed group with timestamps earlier than this value, if set. + /// delete all attachments from the closed group with timestamps earlier than this value, if + /// set. /// /// Returns std::nullopt if no delete-attachments-before timestamp is set. /// diff --git a/include/session/config/groups/keys.hpp b/include/session/config/groups/keys.hpp index b1dd3ff4..a2646547 100644 --- a/include/session/config/groups/keys.hpp +++ b/include/session/config/groups/keys.hpp @@ -169,7 +169,8 @@ class Keys final : public ConfigSig { /// - `group_ed25519_pubkey` is the public key of the group, used to verify message signatures /// on key updates. Required. Should not include the `03` prefix. /// - `group_ed25519_secretkey` is the secret key of the group, used to sign config messages and - /// swarm authentication tokens and to encrypt and decrypt encryption keys for regular messages. + /// swarm authentication tokens and to encrypt and decrypt encryption keys for regular + /// messages. /// This is only possessed by the group admin(s), and must be provided /// in order to make and push config changes. /// - `dumped` -- either `std::nullopt` to construct a new, empty object; or binary state data diff --git a/include/session/config/groups/members.hpp b/include/session/config/groups/members.hpp index 5a4e4d20..075f6669 100644 --- a/include/session/config/groups/members.hpp +++ b/include/session/config/groups/members.hpp @@ -279,8 +279,9 @@ class Members final : public ConfigBase { /// To construct a blank members object (i.e. with no pre-existing dumped data to load) pass /// `std::nullopt` as the third argument. /// - /// Encryption keys must be loaded before the Members object can be modified or parse other Members - /// messages, and are typically loaded by providing the `Members` object to the `Keys` class. + /// Encryption keys must be loaded before the Members object can be modified or parse other + /// Members messages, and are typically loaded by providing the `Members` object to the `Keys` + /// class. /// /// Inputs: /// - `ed25519_pubkey` is the public key of this group, used to validate config messages. diff --git a/src/config/groups/keys.cpp b/src/config/groups/keys.cpp index eee68033..f86d7d8e 100644 --- a/src/config/groups/keys.cpp +++ b/src/config/groups/keys.cpp @@ -459,7 +459,8 @@ ustring Keys::key_supplement(const std::vector& sids) const { // (66 chars), in sorted order. // - keysdata is the unencrypted inner value that we are encrypting for each supplemental member // - H2(.) = 32-byte BLAKE2b keyed hash of the sodium group secret key seed (just the 32 byte, - // not the full 64 byte with the pubkey in the second half), key "SessionGroupNonceSeed" + // not the full 64 byte with the pubkey in the second half), key + // "SessionGroupNonceSeed" std::string supp_keys; { @@ -481,8 +482,7 @@ ustring Keys::key_supplement(const std::vector& sids) const { crypto_generichash_blake2b_state st; - crypto_generichash_blake2b_init( - &st, nonce_hash_key.data(), nonce_hash_key.size(), h1.size()); + crypto_generichash_blake2b_init(&st, nonce_hash_key.data(), nonce_hash_key.size(), h1.size()); for (const auto& sid : sids) crypto_generichash_blake2b_update(&st, to_unsigned(sid.data()), sid.size()); @@ -548,8 +548,8 @@ ustring Keys::key_supplement(const std::vector& sids) const { d.append("G", keys_.back().generation); - // Finally we sign the message and put the signature as the ~ key (which is 0x7e, and thus comes later than - // any other printable ascii key). + // Finally we sign the message and put the signature as the ~ key (which is 0x7e, and thus comes + // later than any other printable ascii key). d.append_signature("~", [this](ustring_view to_sign) { return sign(to_sign); }); return ustring{to_unsigned_sv(d.view())}; @@ -708,7 +708,8 @@ Keys::swarm_auth Keys::swarm_subaccount_sign( // token is now set: flags || kT ustring_view kT{to_unsigned(token.data() + 4), 32}; - // sub_sig is just the admin's signature, sitting at the end of sign_val (after p || f || 0 || 0 || k): + // sub_sig is just the admin's signature, sitting at the end of sign_val (after p || f || 0 || 0 + // || k): sub_sig = from_unsigned_sv(sign_val.substr(36)); // Our signing private scalar is kt, where t = ±s according to whether we had to negate S to @@ -1173,9 +1174,9 @@ void Keys::remove_expired() { active_msgs_.erase( active_msgs_.begin(), active_msgs_.lower_bound(keys_.front().generation)); else - // Keys is empty, which means we aren't keeping *any* keys around (or they are all invalid or - // something) and so it isn't really up to us to keep them alive, since that's a history of - // the group we apparently don't have access to. + // Keys is empty, which means we aren't keeping *any* keys around (or they are all invalid + // or something) and so it isn't really up to us to keep them alive, since that's a history + // of the group we apparently don't have access to. active_msgs_.clear(); } diff --git a/src/xed25519.cpp b/src/xed25519.cpp index 2b2c0426..c781105d 100644 --- a/src/xed25519.cpp +++ b/src/xed25519.cpp @@ -97,8 +97,8 @@ bytes<64> sign(ustring_view curve25519_privkey, ustring_view msg) { crypto_core_ed25519_scalar_negate(neg_a.data(), a.data()); constant_time_conditional_assign(a, neg_a, negative); - // We now have our a, A private/public keypair. (Note that a is just the private key scalar, *not* the - // ed25519 secret key). + // We now have our a, A private/public keypair. (Note that a is just the private key scalar, + // *not* the ed25519 secret key). bytes<32> r = xed25519_compute_r(a, msg); bytes<64> signature; // R || S