Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions library/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ set(SOURCES
ed25519.cpp
curve25519.cpp
hash.cpp
attachments.cpp
)

add_library( # Sets the name of the library.
Expand Down
79 changes: 79 additions & 0 deletions library/src/main/cpp/attachments.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include <jni.h>
#include <session/attachments.hpp>
#include "jni_utils.h"

using namespace session::attachment;
using namespace jni_utils;

extern "C"
JNIEXPORT jlong JNICALL
Java_network_loki_messenger_libsession_1util_encrypt_Attachments_encryptedSize(JNIEnv *env,
jobject thiz,
jlong plaintext_size) {
return encrypted_size(plaintext_size);
}

extern "C"
JNIEXPORT jlong JNICALL
Java_network_loki_messenger_libsession_1util_encrypt_Attachments_decryptedMaxSize(JNIEnv *env,
jobject thiz,
jlong ciphertext_size) {
auto s = decrypted_max_size(ciphertext_size);
if (s.has_value()) {
return *s;
} else {
env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"),
"ciphertext_size too small to be a valid encrypted attachment");
return 0;
}
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_network_loki_messenger_libsession_1util_encrypt_Attachments_encryptBytes(JNIEnv *env,
jobject thiz,
jbyteArray seed,
jbyteArray plaintext_in,
jint plaintext_in_offset,
jint plaintext_in_len,
jbyteArray cipher_out,
jint cipher_out_offset,
jint cipher_out_len,
jint domain) {
return run_catching_cxx_exception_or_throws<jbyteArray>(env, [=] {
auto key = encrypt(
JavaByteArrayRef(env, seed).get_as_bytes(),
JavaByteArrayRef(env, plaintext_in).get_as_bytes().subspan(plaintext_in_offset, plaintext_in_len),
static_cast<Domain>(domain),
JavaByteArrayRef(env, cipher_out).get_as_bytes().subspan(cipher_out_offset, cipher_out_len)
);


return util::bytes_from_span(env, std::span(reinterpret_cast<unsigned char *>(key.data()), key.size()));
});
}

extern "C"
JNIEXPORT jlong JNICALL
Java_network_loki_messenger_libsession_1util_encrypt_Attachments_decryptBytes(JNIEnv *env,
jobject thiz,
jbyteArray key,
jbyteArray cipher_in,
jint cipher_in_offset,
jint cipher_in_len,
jbyteArray plain_out,
jint plain_out_offset,
jint plain_out_len) {
return run_catching_cxx_exception_or_throws<jlong>(env, [=] {
JavaByteArrayRef key_ref(env, key);

return decrypt(
JavaByteArrayRef(env, cipher_in).get_as_bytes().subspan(cipher_in_offset, cipher_in_len),
std::span<std::byte, ENCRYPT_KEY_SIZE>(
reinterpret_cast<std::byte *>(key_ref.get().data()),
ENCRYPT_KEY_SIZE
),
JavaByteArrayRef(env, plain_out).get_as_bytes().subspan(plain_out_offset, plain_out_len)
);
});
}
4 changes: 4 additions & 0 deletions library/src/main/cpp/jni_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ namespace jni_utils {
return data;
}

std::span<std::byte> get_as_bytes() const {
return std::span<std::byte>(reinterpret_cast<std::byte *>(data.data()), data.size());
}

std::vector<unsigned char> copy() const {
return std::vector(data.begin(), data.end());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package network.loki.messenger.libsession_util.encrypt

import network.loki.messenger.libsession_util.LibSessionUtilCApi

/**
* Utilities for encrypting and decrypting attachments and profile pictures uploaded to the FileServer.
*/
object Attachments : LibSessionUtilCApi() {
enum class Domain(val nativeValue: Int) {
Attachment(0),
ProfilePic(1),
}

external fun encryptedSize(plaintextSize: Long): Long
fun decryptedMaxSizeOrNull(ciphertextSize: Long): Long? = runCatching {
decryptedMaxSize(ciphertextSize)
}.getOrNull()


private external fun decryptedMaxSize(ciphertextSize: Long): Long

private external fun encryptBytes(
seed: ByteArray,
plaintextIn: ByteArray,
plaintextInOffset: Int,
plaintextInLen: Int,
cipherOut: ByteArray,
cipherOutOffset: Int,
cipherOutLen: Int,
domain: Int
): ByteArray

fun encryptBytes(
seed: ByteArray,
plaintextIn: ByteArray,
cipherOut: ByteArray,
domain: Domain
): ByteArray = encryptBytes(
seed = seed,
plaintextIn = plaintextIn,
plaintextInLen = plaintextIn.size,
plaintextInOffset = 0,
cipherOut = cipherOut,
cipherOutOffset = 0,
cipherOutLen = cipherOut.size,
domain = domain.nativeValue
)

external fun decryptBytes(
key: ByteArray,
cipherIn: ByteArray,
cipherInOffset: Int,
cipherInLen: Int,
plainOut: ByteArray,
plainOutOffset: Int,
plainOutLen: Int,
): Long

fun decryptBytes(
key: ByteArray,
cipherIn: ByteArray,
plainOut: ByteArray
): Long = decryptBytes(
key = key,
cipherIn = cipherIn,
cipherInOffset = 0,
cipherInLen = cipherIn.size,
plainOut = plainOut,
plainOutOffset = 0,
plainOutLen = plainOut.size
)
}