1515
1616namespace 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
1978class 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