Skip to content

Commit ab784e8

Browse files
committed
feat: added encode for a bunch for other destinations
1 parent f5384c3 commit ab784e8

File tree

2 files changed

+287
-71
lines changed

2 files changed

+287
-71
lines changed

include/multi_encrypt/multi_encrypt.hpp

Lines changed: 242 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,65 @@
1515

1616
namespace session::nodeapi {
1717

18+
inline std::vector<unsigned char> extractPlaintext(
19+
const Napi::Object& obj, const std::string identifier) {
20+
assertIsUInt8Array(obj.Get("plaintext"), identifier);
21+
auto plaintext = toCppBuffer(obj.Get("plaintext"), identifier);
22+
return plaintext;
23+
}
24+
25+
inline std::chrono::milliseconds extractSentTimestampMs(
26+
const Napi::Object& obj, const std::string identifier) {
27+
assertIsNumber(obj.Get("sentTimestampMs"), identifier);
28+
auto sentTimestampMs = toCppMs(obj.Get("sentTimestampMs"), identifier);
29+
return sentTimestampMs;
30+
}
31+
32+
inline std::span<const unsigned char> extractSenderEd25519PrivkeyAsSpan(
33+
const Napi::Object& obj, const std::string identifier) {
34+
assertIsString(obj.Get("senderEd25519Privkey"));
35+
auto ed25519PrivkeyHex = toCppString(obj.Get("senderEd25519Privkey"), identifier);
36+
return from_hex_to_span(ed25519PrivkeyHex);
37+
}
38+
39+
inline session::array_uc33 extractRecipientPubkeyAsArray(
40+
const Napi::Object& obj, const std::string identifier) {
41+
assertIsString(obj.Get("recipientPubkey"));
42+
auto recipientPubkeyHex = toCppString(obj.Get("recipientPubkey"), identifier);
43+
return from_hex_to_array<33>(recipientPubkeyHex);
44+
}
45+
46+
inline session::array_uc32 extractCommunityPubkeyAsArray(
47+
const Napi::Object& obj, const std::string identifier) {
48+
assertIsString(obj.Get("communityPubkey"));
49+
auto communityPubkeyHex = toCppString(obj.Get("communityPubkey"), identifier);
50+
return from_hex_to_array<32>(communityPubkeyHex);
51+
}
52+
53+
inline session::array_uc33 extractGroupEd25519PubkeyAsArray(
54+
const Napi::Object& obj, const std::string identifier) {
55+
assertIsString(obj.Get("groupEd25519Pubkey"));
56+
auto communityPubkeyHex = toCppString(obj.Get("groupEd25519Pubkey"), identifier);
57+
return from_hex_to_array<33>(communityPubkeyHex);
58+
}
59+
60+
inline cleared_uc32 extractGroupEncPrivKeyAsArray(
61+
const Napi::Object& obj, const std::string identifier) {
62+
assertIsString(obj.Get("groupEncPrivKey"));
63+
auto groupEncPrivKeyHex = toCppString(obj.Get("groupEncPrivKey"), identifier);
64+
auto arr = from_hex_to_array<32>(groupEncPrivKeyHex);
65+
cleared_uc32 result;
66+
std::copy(arr.begin(), arr.end(), result.begin());
67+
return result;
68+
}
69+
70+
inline std::span<const unsigned char> extractProRotatingEd25519PrivkeyAsSpan(
71+
const Napi::Object& obj, const std::string identifier) {
72+
assertIsStringOrNull(obj.Get("proRotatingEd25519Privkey"));
73+
auto proRotatingEd25519PrivkeyHex =
74+
maybeNonemptyString(obj.Get("proRotatingEd25519Privkey"), identifier);
75+
return from_hex_to_span(proRotatingEd25519PrivkeyHex.value_or(""));
76+
}
1877

1978
class MultiEncryptWrapper : public Napi::ObjectWrap<MultiEncryptWrapper> {
2079
public:
@@ -54,18 +113,18 @@ class MultiEncryptWrapper : public Napi::ObjectWrap<MultiEncryptWrapper> {
54113
static_cast<napi_property_attributes>(
55114
napi_writable | napi_configurable)),
56115

57-
// StaticMethod<&MultiEncryptWrapper::encryptForCommunity>(
58-
// "encryptForCommunity",
59-
// static_cast<napi_property_attributes>(
60-
// napi_writable | napi_configurable)),
61-
// StaticMethod<&MultiEncryptWrapper::encryptForCommunityInbox>(
62-
// "encryptForCommunityInbox",
63-
// static_cast<napi_property_attributes>(
64-
// napi_writable | napi_configurable)),
65-
// StaticMethod<&MultiEncryptWrapper::encryptForGroup>(
66-
// "encryptForGroup",
67-
// static_cast<napi_property_attributes>(
68-
// napi_writable | napi_configurable)),
116+
StaticMethod<&MultiEncryptWrapper::encryptForCommunity>(
117+
"encryptForCommunity",
118+
static_cast<napi_property_attributes>(
119+
napi_writable | napi_configurable)),
120+
StaticMethod<&MultiEncryptWrapper::encryptForCommunityInbox>(
121+
"encryptForCommunityInbox",
122+
static_cast<napi_property_attributes>(
123+
napi_writable | napi_configurable)),
124+
StaticMethod<&MultiEncryptWrapper::encryptForGroup>(
125+
"encryptForGroup",
126+
static_cast<napi_property_attributes>(
127+
napi_writable | napi_configurable)),
69128
});
70129
}
71130

@@ -203,14 +262,58 @@ class MultiEncryptWrapper : public Napi::ObjectWrap<MultiEncryptWrapper> {
203262
});
204263
};
205264

265+
static Napi::Value attachmentDecrypt(const Napi::CallbackInfo& info) {
266+
return wrapResult(info, [&] {
267+
assertInfoLength(info, 1);
268+
assertIsObject(info[0]);
269+
auto obj = info[0].As<Napi::Object>();
270+
271+
if (obj.IsEmpty())
272+
throw std::invalid_argument("attachmentDecrypt received empty");
273+
274+
assertIsUInt8Array(obj.Get("encryptedData"), "attachmentDecrypt.encryptedData");
275+
auto encrypted_data =
276+
toCppBuffer(obj.Get("encryptedData"), "attachmentDecrypt.encryptedData");
277+
278+
assertIsUInt8Array(obj.Get("decryptionKey"), "attachmentDecrypt.decryptionKey");
279+
auto decryption_key =
280+
toCppBuffer(obj.Get("decryptionKey"), "attachmentDecrypt.decryptionKey");
281+
282+
std::vector<std::byte> encrypted_data_bytes(
283+
reinterpret_cast<const std::byte*>(encrypted_data.data()),
284+
reinterpret_cast<const std::byte*>(
285+
encrypted_data.data() + encrypted_data.size()));
286+
287+
std::vector<std::byte> decryption_key_bytes(
288+
reinterpret_cast<const std::byte*>(decryption_key.data()),
289+
reinterpret_cast<const std::byte*>(
290+
decryption_key.data() + decryption_key.size()));
291+
292+
if (decryption_key_bytes.size() != session::attachment::ENCRYPT_KEY_SIZE) {
293+
throw std::invalid_argument("Key size mismatch");
294+
}
295+
296+
std::span<const std::byte, session::attachment::ENCRYPT_KEY_SIZE> decryption_key_span(
297+
decryption_key_bytes.data(), session::attachment::ENCRYPT_KEY_SIZE);
298+
299+
auto decrypted =
300+
session::attachment::decrypt(encrypted_data_bytes, decryption_key_span);
301+
302+
auto ret = Napi::Object::New(info.Env());
303+
ret.Set("decryptedData", toJs(info.Env(), decrypted));
304+
305+
return ret;
306+
});
307+
};
308+
206309
static Napi::Value encryptFor1o1(const Napi::CallbackInfo& info) {
207310
return wrapResult(info, [&] {
208311
// we expect an single argument which is an array of objects with the following
209312
// properties:
210313
// {
211314
// "plaintext": Uint8Array,
212315
// "sentTimestampMs": Number,
213-
// "ed25519Privkey": Hexstring,
316+
// "senderEd25519Privkey": Hexstring,
214317
// "recipientPubkey": Hexstring,
215318
// "proRotatingEd25519Privkey": Hexstring | null,
216319
// }
@@ -232,31 +335,65 @@ class MultiEncryptWrapper : public Napi::ObjectWrap<MultiEncryptWrapper> {
232335
}
233336
auto obj = itemValue.As<Napi::Object>();
234337

235-
assertIsUInt8Array(obj.Get("plaintext"), "encryptFor1o1.obj.message");
236-
auto plaintext = toCppBuffer(obj.Get("plaintext"), "encryptFor1o1.obj.message");
338+
ready_to_send[i] = session::encode_for_1o1(
339+
extractPlaintext(obj, "encryptFor1o1.obj.plaintext"),
340+
extractSenderEd25519PrivkeyAsSpan(
341+
obj, "encryptFor1o1.obj.senderEd25519Privkey"),
342+
extractSentTimestampMs(obj, "encryptFor1o1.obj.sentTimestampMs"),
343+
extractRecipientPubkeyAsArray(obj, "encryptFor1o1.obj.recipientPubkey"),
344+
extractProRotatingEd25519PrivkeyAsSpan(
345+
obj, "encryptFor1o1.obj.proRotatingEd25519Privkey"));
346+
}
237347

238-
assertIsNumber(obj.Get("sentTimestampMs"), "encryptFor1o1.obj.sentTimestampMs");
239-
auto sentTimestampMs =
240-
toCppMs(obj.Get("sentTimestampMs"), "encryptFor1o1.obj.sentTimestampMs");
348+
auto ret = Napi::Object::New(info.Env());
349+
ret.Set("encryptedData", toJs(info.Env(), ready_to_send));
241350

242-
assertIsString(obj.Get("ed25519Privkey"));
243-
auto ed25519PrivkeyHex =
244-
toCppString(obj.Get("ed25519Privkey"), "encryptFor1o1.obj.ed25519Privkey");
351+
return ret;
352+
});
353+
};
245354

246-
assertIsString(obj.Get("recipientPubkey"));
247-
auto recipientPubkeyHex = toCppString(
248-
obj.Get("recipientPubkey"), "encryptFor1o1.obj.recipientPubkey");
355+
static Napi::Value encryptForCommunityInbox(const Napi::CallbackInfo& info) {
356+
return wrapResult(info, [&] {
357+
// we expect an single argument which is an array of objects with the following
358+
// properties:
359+
// {
360+
// "plaintext": Uint8Array,
361+
// "senderEd25519Privkey": Hexstring,
362+
// "sentTimestampMs": Number,
363+
// "recipientPubkey": Hexstring,
364+
// "communityPubkey": Hexstring,
365+
// "proRotatingEd25519Privkey": Hexstring | null,
366+
// }
367+
//
249368

250-
assertIsStringOrNull(obj.Get("proRotatingEd25519Privkey"));
251-
auto proRotatingEd25519PrivkeyHex = maybeNonemptyString(
252-
obj.Get("proRotatingEd25519Privkey"),
253-
"encryptFor1o1.obj.proRotatingEd25519Privkey");
254-
ready_to_send[i] = session::encode_for_1o1(
255-
plaintext,
256-
from_hex_to_span(ed25519PrivkeyHex),
257-
sentTimestampMs,
258-
from_hex_to_array<33>(recipientPubkeyHex),
259-
from_hex_to_span(proRotatingEd25519PrivkeyHex.value_or("")));
369+
assertInfoLength(info, 1);
370+
assertIsArray(info[0], "encryptForCommunityInbox info[0]");
371+
372+
auto array = info[0].As<Napi::Array>();
373+
374+
if (array.IsEmpty())
375+
throw std::invalid_argument("encryptForCommunityInbox received empty");
376+
377+
std::vector<std::vector<uint8_t>> ready_to_send(array.Length());
378+
for (uint32_t i = 0; i < array.Length(); i++) {
379+
auto itemValue = array.Get(i);
380+
if (!itemValue.IsObject()) {
381+
throw std::invalid_argument(
382+
"encryptForCommunityInbox itemValue is not an object");
383+
}
384+
auto obj = itemValue.As<Napi::Object>();
385+
386+
ready_to_send[i] = session::encode_for_community_inbox(
387+
extractPlaintext(obj, "encryptForCommunityInbox.obj.plaintext"),
388+
extractSenderEd25519PrivkeyAsSpan(
389+
obj, "encryptForCommunityInbox.obj.senderEd25519Privkey"),
390+
extractSentTimestampMs(obj, "encryptForCommunityInbox.obj.sentTimestampMs"),
391+
extractRecipientPubkeyAsArray(
392+
obj, "encryptForCommunityInbox.obj.recipientPubkey"),
393+
extractCommunityPubkeyAsArray(
394+
obj, "encryptForCommunityInbox.obj.communityPubkey"),
395+
extractProRotatingEd25519PrivkeyAsSpan(
396+
obj, "encryptForCommunityInbox.obj.proRotatingEd25519Privkey"));
260397
}
261398

262399
auto ret = Napi::Object::New(info.Env());
@@ -266,49 +403,92 @@ class MultiEncryptWrapper : public Napi::ObjectWrap<MultiEncryptWrapper> {
266403
});
267404
};
268405

269-
static Napi::Value attachmentDecrypt(const Napi::CallbackInfo& info) {
406+
static Napi::Value encryptForCommunity(const Napi::CallbackInfo& info) {
270407
return wrapResult(info, [&] {
408+
// we expect an single argument which is an array of objects with the following
409+
// properties:
410+
// {
411+
// "plaintext": Uint8Array,
412+
// "proRotatingEd25519Privkey": Hexstring | null,
413+
// }
414+
//
415+
271416
assertInfoLength(info, 1);
272-
assertIsObject(info[0]);
273-
auto obj = info[0].As<Napi::Object>();
417+
assertIsArray(info[0], "encryptForCommunity info[0]");
274418

275-
if (obj.IsEmpty())
276-
throw std::invalid_argument("attachmentDecrypt received empty");
419+
auto array = info[0].As<Napi::Array>();
277420

278-
assertIsUInt8Array(obj.Get("encryptedData"), "attachmentDecrypt.encryptedData");
279-
auto encrypted_data =
280-
toCppBuffer(obj.Get("encryptedData"), "attachmentDecrypt.encryptedData");
421+
if (array.IsEmpty())
422+
throw std::invalid_argument("encryptForCommunity received empty");
281423

282-
assertIsUInt8Array(obj.Get("decryptionKey"), "attachmentDecrypt.decryptionKey");
283-
auto decryption_key =
284-
toCppBuffer(obj.Get("decryptionKey"), "attachmentDecrypt.decryptionKey");
424+
std::vector<std::vector<uint8_t>> ready_to_send(array.Length());
425+
for (uint32_t i = 0; i < array.Length(); i++) {
426+
auto itemValue = array.Get(i);
427+
if (!itemValue.IsObject()) {
428+
throw std::invalid_argument("encryptForCommunity itemValue is not an object");
429+
}
430+
auto obj = itemValue.As<Napi::Object>();
285431

286-
std::vector<std::byte> encrypted_data_bytes(
287-
reinterpret_cast<const std::byte*>(encrypted_data.data()),
288-
reinterpret_cast<const std::byte*>(
289-
encrypted_data.data() + encrypted_data.size()));
432+
ready_to_send[i] = session::encode_for_community(
433+
extractPlaintext(obj, "encryptForCommunity.obj.plaintext"),
434+
extractProRotatingEd25519PrivkeyAsSpan(
435+
obj, "encryptForCommunity.obj.proRotatingEd25519Privkey"));
436+
}
290437

291-
std::vector<std::byte> decryption_key_bytes(
292-
reinterpret_cast<const std::byte*>(decryption_key.data()),
293-
reinterpret_cast<const std::byte*>(
294-
decryption_key.data() + decryption_key.size()));
438+
auto ret = Napi::Object::New(info.Env());
439+
ret.Set("encryptedData", toJs(info.Env(), ready_to_send));
295440

296-
if (decryption_key_bytes.size() != session::attachment::ENCRYPT_KEY_SIZE) {
297-
throw std::invalid_argument("Key size mismatch");
298-
}
441+
return ret;
442+
});
443+
};
299444

300-
std::span<const std::byte, session::attachment::ENCRYPT_KEY_SIZE> decryption_key_span(
301-
decryption_key_bytes.data(), session::attachment::ENCRYPT_KEY_SIZE);
445+
static Napi::Value encryptForGroup(const Napi::CallbackInfo& info) {
446+
return wrapResult(info, [&] {
447+
// we expect an single argument which is an array of objects with the following
448+
// properties:
449+
// {
450+
// "plaintext": Uint8Array,
451+
// "senderEd25519Privkey": Hexstring,
452+
// "sentTimestampMs": Number,
453+
// "groupEd25519Pubkey": Hexstring,
454+
// "groupEncPrivKey": Hexstring,
455+
// "proRotatingEd25519Privkey": Hexstring | null,
456+
// }
457+
//
302458

303-
auto decrypted =
304-
session::attachment::decrypt(encrypted_data_bytes, decryption_key_span);
459+
assertInfoLength(info, 1);
460+
assertIsArray(info[0], "encryptForGroup info[0]");
461+
462+
auto array = info[0].As<Napi::Array>();
463+
464+
if (array.IsEmpty())
465+
throw std::invalid_argument("encryptForGroup received empty");
466+
467+
std::vector<std::vector<uint8_t>> ready_to_send(array.Length());
468+
for (uint32_t i = 0; i < array.Length(); i++) {
469+
auto itemValue = array.Get(i);
470+
if (!itemValue.IsObject()) {
471+
throw std::invalid_argument("encryptForGroup itemValue is not an object");
472+
}
473+
auto obj = itemValue.As<Napi::Object>();
474+
475+
ready_to_send[i] = session::encode_for_group(
476+
extractPlaintext(obj, "encryptForGroup.obj.plaintext"),
477+
extractSenderEd25519PrivkeyAsSpan(
478+
obj, "encryptForGroup.obj.senderEd25519Privkey"),
479+
extractSentTimestampMs(obj, "encryptForGroup.obj.sentTimestampMs"),
480+
extractGroupEd25519PubkeyAsArray(
481+
obj, "encryptForGroup.obj.recipientPubkey"),
482+
extractGroupEncPrivKeyAsArray(obj, "encryptForGroup.obj.groupEncPrivKey"),
483+
extractProRotatingEd25519PrivkeyAsSpan(
484+
obj, "encryptForGroup.obj.proRotatingEd25519Privkey"));
485+
}
305486

306487
auto ret = Napi::Object::New(info.Env());
307-
ret.Set("decryptedData", toJs(info.Env(), decrypted));
488+
ret.Set("encryptedData", toJs(info.Env(), ready_to_send));
308489

309490
return ret;
310491
});
311492
};
312493
};
313-
314494
}; // namespace session::nodeapi

0 commit comments

Comments
 (0)