Skip to content

Commit a401bd1

Browse files
authored
Merge pull request #33 from session-foundation/feat-add-pro-backend-fns
add libsession encrypt/decrypt with pro proof
2 parents ea13c80 + 23e08f2 commit a401bd1

33 files changed

+2616
-356
lines changed

.github/workflows/test.yml

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ on:
44
push:
55
branches:
66
- main
7+
- feat-add-pro-backend-fns
78
pull_request:
89
branches:
910
- main
11+
- feat-add-pro-backend-fns
1012

1113
concurrency:
1214
group: ${{ github.workflow }}
@@ -19,7 +21,7 @@ jobs:
1921
strategy:
2022
fail-fast: false
2123
matrix:
22-
os: [windows-2022, macos-13, macos-14, ubuntu-22.04]
24+
os: [windows-2022, macos-13, macos-14, ubuntu-24.04]
2325
env:
2426
SIGNAL_ENV: production
2527
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -29,16 +31,21 @@ jobs:
2931
- name: Checkout git repo
3032
uses: actions/checkout@v4
3133
with:
32-
submodules: 'recursive'
34+
submodules: "recursive"
35+
36+
- name: Install correct clang versions
37+
if: runner.os == 'Linux'
38+
run: sudo apt update && sudo apt search clang && sudo apt install clang-format-19 #clang-tidy-19
39+
shell: bash
3340

3441
- name: Install node
3542
uses: actions/setup-node@v3
3643
with:
37-
node-version-file: '.nvmrc'
44+
node-version-file: ".nvmrc"
3845

3946
- uses: actions/setup-python@v4
4047
with:
41-
python-version: '3.11'
48+
python-version: "3.11"
4249

4350
- name: Add msbuild to PATH
4451
uses: microsoft/[email protected]
@@ -47,3 +54,12 @@ jobs:
4754
- name: build libsession-util-nodejs
4855
shell: bash
4956
run: yarn install --frozen-lockfile
57+
58+
- name: Check formatting
59+
if: runner.os == 'Linux'
60+
run: clang-format-19 --dry-run --Werror src/*.cpp include/*.hpp src/**/*.cpp include/**/*.hpp
61+
shell: bash
62+
63+
# - name: Run clang-tidy
64+
# run: clang-tidy-19 -p build src/*.cpp include/*.hpp src/**/*.cpp include/**/*.hpp
65+
# shell: bash

CMakeLists.txt

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,22 +58,39 @@ set(ENABLE_ONIONREQ OFF)
5858
# as it is not part of the archive. We actually don't care about it on session-desktop
5959
set(SUBMODULE_CHECK OFF)
6060

61-
file(GLOB SOURCE_FILES src/*.cpp src/groups/*.cpp src/multi_encrypt/*.cpp)
61+
file(GLOB SOURCE_FILES src/*.cpp src/groups/*.cpp src/encrypt_decrypt/*.cpp src/pro/*.cpp src/meta/*.cpp )
6262

6363
add_subdirectory(libsession-util)
6464

65-
6665
if(MSVC)
6766
# Windows is horrible
6867
add_compile_definitions(NOMINMAX)
6968
endif()
7069

70+
71+
7172
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})
72-
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_JS_INC} "include/" "node_modules/node-addon-api" "../../node_modules/node-addon-api" "node_modules/node-api-headers/include" "../../node_modules/node-api-headers/include")
73+
74+
# Mark the node-addon-api headers as system so the -Werror=switch-enum does not apply to them
75+
target_include_directories(${PROJECT_NAME}
76+
SYSTEM PRIVATE
77+
${CMAKE_JS_INC}
78+
${CMAKE_CURRENT_SOURCE_DIR}/node_modules/node-addon-api
79+
${CMAKE_CURRENT_SOURCE_DIR}/node_modules
80+
${CMAKE_CURRENT_SOURCE_DIR}/node_modules/node-api-headers/include
81+
)
82+
83+
target_include_directories(${PROJECT_NAME} PRIVATE "include/" )
7384

7485
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
7586
target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_JS_LIB} ${LIBSESSION_STATIC_BUNDLE_LIBS})
7687

88+
89+
if(UNIX AND NOT APPLE)
90+
target_compile_options(${PROJECT_NAME} PRIVATE -Werror=switch-enum)
91+
endif()
92+
93+
7794
if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET)
7895
# Generate node.lib
7996
execute_process(COMMAND ${CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS})

include/base_config.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@
66
#include <cassert>
77
#include <memory>
88
#include <oxen/log.hpp>
9-
#include <span>
109
#include <stdexcept>
1110
#include <unordered_set>
1211

1312
#include "session/config/base.hpp"
14-
#include "session/logging.hpp"
15-
#include "session/types.hpp"
1613
#include "utilities.hpp"
1714

1815
namespace session::nodeapi {
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#pragma once
2+
3+
#include <napi.h>
4+
#include <oxenc/base64.h>
5+
#include <oxenc/hex.h>
6+
7+
#include "meta/meta_base_wrapper.hpp"
8+
9+
namespace session::nodeapi {
10+
11+
class MultiEncryptWrapper : public Napi::ObjectWrap<MultiEncryptWrapper> {
12+
public:
13+
MultiEncryptWrapper(const Napi::CallbackInfo& info) :
14+
Napi::ObjectWrap<MultiEncryptWrapper>{info} {
15+
throw std::invalid_argument(
16+
"MultiEncryptWrapper is static and doesn't need to be constructed");
17+
}
18+
19+
static void Init(Napi::Env env, Napi::Object exports) {
20+
MetaBaseWrapper::NoBaseClassInitHelper<MultiEncryptWrapper>(
21+
env,
22+
exports,
23+
"MultiEncryptWrapperNode",
24+
{
25+
StaticMethod<&MultiEncryptWrapper::multiEncrypt>(
26+
"multiEncrypt",
27+
static_cast<napi_property_attributes>(
28+
napi_writable | napi_configurable)),
29+
StaticMethod<&MultiEncryptWrapper::multiDecryptEd25519>(
30+
"multiDecryptEd25519",
31+
static_cast<napi_property_attributes>(
32+
napi_writable | napi_configurable)),
33+
// Attachments encrypt/decrypt
34+
StaticMethod<&MultiEncryptWrapper::attachmentDecrypt>(
35+
"attachmentDecrypt",
36+
static_cast<napi_property_attributes>(
37+
napi_writable | napi_configurable)),
38+
StaticMethod<&MultiEncryptWrapper::attachmentEncrypt>(
39+
"attachmentEncrypt",
40+
static_cast<napi_property_attributes>(
41+
napi_writable | napi_configurable)),
42+
43+
// Destination encrypt
44+
StaticMethod<&MultiEncryptWrapper::encryptFor1o1>(
45+
"encryptFor1o1",
46+
static_cast<napi_property_attributes>(
47+
napi_writable | napi_configurable)),
48+
49+
StaticMethod<&MultiEncryptWrapper::encryptForCommunity>(
50+
"encryptForCommunity",
51+
static_cast<napi_property_attributes>(
52+
napi_writable | napi_configurable)),
53+
StaticMethod<&MultiEncryptWrapper::encryptForCommunityInbox>(
54+
"encryptForCommunityInbox",
55+
static_cast<napi_property_attributes>(
56+
napi_writable | napi_configurable)),
57+
StaticMethod<&MultiEncryptWrapper::encryptForGroup>(
58+
"encryptForGroup",
59+
static_cast<napi_property_attributes>(
60+
napi_writable | napi_configurable)),
61+
62+
// Destination decrypt
63+
StaticMethod<&MultiEncryptWrapper::decryptForCommunity>(
64+
"decryptForCommunity",
65+
static_cast<napi_property_attributes>(
66+
napi_writable | napi_configurable)),
67+
StaticMethod<&MultiEncryptWrapper::decryptFor1o1>(
68+
"decryptFor1o1",
69+
static_cast<napi_property_attributes>(
70+
napi_writable | napi_configurable)),
71+
StaticMethod<&MultiEncryptWrapper::decryptForGroup>(
72+
"decryptForGroup",
73+
static_cast<napi_property_attributes>(
74+
napi_writable | napi_configurable)),
75+
});
76+
}
77+
78+
private:
79+
static Napi::Value multiEncrypt(const Napi::CallbackInfo& info);
80+
static Napi::Value multiDecryptEd25519(const Napi::CallbackInfo& info);
81+
82+
/**
83+
* ===========================================
84+
* =========== ATTACHMENTS CALLS =============
85+
* ===========================================
86+
*/
87+
88+
static Napi::Value attachmentEncrypt(const Napi::CallbackInfo& info);
89+
static Napi::Value attachmentDecrypt(const Napi::CallbackInfo& info);
90+
91+
/**
92+
* ===========================================
93+
* ============= ENCRYPT CALLS ===============
94+
* ===========================================
95+
*/
96+
97+
static Napi::Value encryptFor1o1(const Napi::CallbackInfo& info);
98+
static Napi::Value encryptForCommunityInbox(const Napi::CallbackInfo& info);
99+
static Napi::Value encryptForCommunity(const Napi::CallbackInfo& info);
100+
static Napi::Value encryptForGroup(const Napi::CallbackInfo& info);
101+
/**
102+
* ===========================================
103+
* ============= DECRYPT CALLS ===============
104+
* ===========================================
105+
*/
106+
107+
static Napi::Value decryptForCommunity(const Napi::CallbackInfo& info);
108+
static Napi::Value decryptFor1o1(const Napi::CallbackInfo& info);
109+
static Napi::Value decryptForGroup(const Napi::CallbackInfo& info);
110+
};
111+
}; // namespace session::nodeapi

include/groups/meta_group.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <napi.h>
4+
45
#include <vector>
56

67
#include "session/config/groups/info.hpp"
@@ -35,7 +36,10 @@ class MetaGroup {
3536
shared_ptr<config::groups::Keys> keys,
3637
std::vector<unsigned char> edGroupPubKey,
3738
std::optional<std::vector<unsigned char>> edGroupSecKey) :
38-
info{info}, members{members}, keys{keys}, edGroupPubKey{oxenc::to_hex(edGroupPubKey.begin(), edGroupPubKey.end())} {
39+
info{info},
40+
members{members},
41+
keys{keys},
42+
edGroupPubKey{oxenc::to_hex(edGroupPubKey.begin(), edGroupPubKey.end())} {
3943

4044
if (edGroupSecKey.has_value()) {
4145
this->edGroupSecKey = oxenc::to_hex(edGroupSecKey->begin(), edGroupSecKey->end());

include/groups/meta_group_wrapper.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class MetaGroupWrapper : public Napi::ObjectWrap<MetaGroupWrapper> {
8080
Napi::Value keysNeedsRekey(const Napi::CallbackInfo& info);
8181
Napi::Value keyRekey(const Napi::CallbackInfo& info);
8282
Napi::Value keyGetAll(const Napi::CallbackInfo& info);
83+
Napi::Value keyGetEncryptionKeyHex(const Napi::CallbackInfo& info);
8384
Napi::Value loadKeyMessage(const Napi::CallbackInfo& info);
8485
Napi::Value keyGetCurrentGen(const Napi::CallbackInfo& info);
8586
Napi::Value activeHashes(const Napi::CallbackInfo& info);

include/meta/meta_base_wrapper.hpp

Lines changed: 5 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22

33
#include <napi.h>
44

5-
#include <optional>
6-
#include <span>
5+
#include <memory>
76
#include <vector>
87

98
#include "../base_config.hpp"
10-
#include "../groups/meta_group.hpp"
9+
#include "groups/meta_group.hpp"
10+
1111
namespace session::nodeapi {
1212

1313
class MetaBaseWrapper {
1414

1515
public:
16-
explicit MetaBaseWrapper(){};
16+
explicit MetaBaseWrapper() {};
1717

1818
virtual ~MetaBaseWrapper() = default;
1919

@@ -35,86 +35,7 @@ class MetaBaseWrapper {
3535
}
3636

3737
static std::unique_ptr<session::nodeapi::MetaGroup> constructGroupWrapper(
38-
const Napi::CallbackInfo& info, const std::string& class_name) {
39-
return wrapExceptions(info, [&] {
40-
if (!info.IsConstructCall())
41-
throw std::invalid_argument{
42-
"You need to call the constructor with the `new` syntax"};
43-
44-
assertInfoLength(info, 1);
45-
auto arg = info[0];
46-
assertIsObject(arg);
47-
auto obj = arg.As<Napi::Object>();
48-
49-
if (obj.IsEmpty())
50-
throw std::invalid_argument("constructGroupWrapper received empty");
51-
52-
assertIsUInt8Array(obj.Get("userEd25519Secretkey"), "constructGroupWrapper userEd");
53-
auto user_ed25519_secretkey = toCppBuffer(
54-
obj.Get("userEd25519Secretkey"),
55-
class_name + ":constructGroupWrapper.userEd25519Secretkey");
56-
57-
assertIsUInt8Array(obj.Get("groupEd25519Pubkey"), "constructGroupWrapper groupEd");
58-
auto group_ed25519_pubkey = toCppBuffer(
59-
obj.Get("groupEd25519Pubkey"),
60-
class_name + ":constructGroupWrapper.groupEd25519Pubkey");
61-
62-
std::optional<std::vector<unsigned char>> group_ed25519_secretkey = maybeNonemptyBuffer(
63-
obj.Get("groupEd25519Secretkey"),
64-
class_name + ":constructGroupWrapper.groupEd25519Secretkey");
65-
66-
std::optional<std::vector<unsigned char>> dumped_meta = maybeNonemptyBuffer(
67-
obj.Get("metaDumped"), class_name + ":constructGroupWrapper.metaDumped");
68-
69-
std::optional<std::string> dumped_info;
70-
std::optional<std::string> dumped_members;
71-
std::optional<std::string> dumped_keys;
72-
73-
if (dumped_meta) {
74-
auto dumped_meta_str = to_string(*dumped_meta);
75-
76-
oxenc::bt_dict_consumer combined{dumped_meta_str};
77-
// NB: must read in ascii-sorted order:
78-
if (!combined.skip_until("info"))
79-
throw std::runtime_error{"info dump not found in combined dump!"};
80-
dumped_info = combined.consume_string();
81-
82-
if (!combined.skip_until("keys"))
83-
throw std::runtime_error{"keys dump not found in combined dump!"};
84-
dumped_keys = combined.consume_string();
85-
86-
if (!combined.skip_until("members"))
87-
throw std::runtime_error{"members dump not found in combined dump!"};
88-
dumped_members = combined.consume_string();
89-
}
90-
91-
// Note, we keep shared_ptr for those as the Keys one need a reference to Members and
92-
// Info on its own currently.
93-
auto info = std::make_shared<config::groups::Info>(
94-
group_ed25519_pubkey,
95-
group_ed25519_secretkey,
96-
(dumped_info ? std::make_optional(session::to_span(*dumped_info))
97-
: std::nullopt));
98-
99-
auto members = std::make_shared<config::groups::Members>(
100-
group_ed25519_pubkey,
101-
group_ed25519_secretkey,
102-
(dumped_members ? std::make_optional(session::to_span(*dumped_members))
103-
: std::nullopt));
104-
105-
auto keys = std::make_shared<config::groups::Keys>(
106-
user_ed25519_secretkey,
107-
group_ed25519_pubkey,
108-
group_ed25519_secretkey,
109-
(dumped_keys ? std::make_optional(session::to_span(*dumped_keys))
110-
: std::nullopt),
111-
*info,
112-
*members);
113-
114-
return std::make_unique<session::nodeapi::MetaGroup>(
115-
info, members, keys, group_ed25519_pubkey, group_ed25519_secretkey);
116-
});
117-
}
38+
const Napi::CallbackInfo& info, const std::string& class_name);
11839
};
11940

12041
} // namespace session::nodeapi

0 commit comments

Comments
 (0)