Skip to content
Merged
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
2 changes: 2 additions & 0 deletions library/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ set(SOURCES
encryption.cpp
jni_utils.cpp
ed25519.cpp
curve25519.cpp
hash.cpp
)

add_library( # Sets the name of the library.
Expand Down
67 changes: 58 additions & 9 deletions library/src/main/cpp/blinded_key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,15 @@
// Created by Thomas Ruffie on 29/7/2024.
//


extern "C"
JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_util_BlindKeyAPI_blindVersionKeyPair(JNIEnv *env,
jobject thiz,
jbyteArray ed25519_secret_key) {
return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] {
const auto [pk, sk] = session::blind_version_key_pair(util::vector_from_bytes(env, ed25519_secret_key));

jclass kp_class = env->FindClass("network/loki/messenger/libsession_util/util/KeyPair");
jmethodID kp_constructor = env->GetMethodID(kp_class, "<init>", "([B[B)V");
return env->NewObject(kp_class, kp_constructor, util::bytes_from_vector(env, {pk.data(), pk.data() + pk.size()}), util::bytes_from_vector(env, {sk.data(), sk.data() + sk.size()}));
return jni_utils::new_key_pair(env, util::bytes_from_span(env, pk), util::bytes_from_span(env, sk));
});
}
extern "C"
Expand All @@ -29,7 +27,11 @@ Java_network_loki_messenger_libsession_1util_util_BlindKeyAPI_blindVersionSign(J
jbyteArray ed25519_secret_key,
jlong timestamp) {
return jni_utils::run_catching_cxx_exception_or_throws<jbyteArray>(env, [=] {
auto bytes = session::blind_version_sign(util::vector_from_bytes(env, ed25519_secret_key), session::Platform::android, timestamp);
auto bytes = session::blind_version_sign(
jni_utils::JavaByteArrayRef(env, ed25519_secret_key).get(),
session::Platform::android,
timestamp
);
return util::bytes_from_vector(env, bytes);
});
}
Expand All @@ -46,16 +48,63 @@ Java_network_loki_messenger_libsession_1util_util_BlindKeyAPI_blindVersionSignRe
return jni_utils::run_catching_cxx_exception_or_throws<jbyteArray>(env, [=] {
auto methodC = util::string_from_jstring(env, method);
auto pathC = util::string_from_jstring(env, path);
auto keyBytes = util::vector_from_bytes(env, ed25519_secret_key);
auto bodyBytes = body ? std::optional(util::vector_from_bytes(env, body)) : std::nullopt;

auto bytes = session::blind_version_sign_request(
session::to_span(keyBytes),
jni_utils::JavaByteArrayRef(env, ed25519_secret_key).get(),
timestamp,
methodC,
pathC,
body ? std::optional(session::to_span(*bodyBytes)) : std::nullopt
body ? std::make_optional(jni_utils::JavaByteArrayRef(env, body).get()) : std::nullopt
);
return util::bytes_from_vector(env, bytes);
});
}

extern "C"
JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_util_BlindKeyAPI_blind15KeyPair(JNIEnv *env,
jobject thiz,
jbyteArray ed25519_secret_key,
jbyteArray server_pub_key) {
return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] {
auto [pk, sk] = session::blind15_key_pair(
jni_utils::JavaByteArrayRef(env, ed25519_secret_key).get(),
jni_utils::JavaByteArrayRef(env, server_pub_key).get()
);
return jni_utils::new_key_pair(env, util::bytes_from_span(env, pk), util::bytes_from_span(env, sk));
});
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_network_loki_messenger_libsession_1util_util_BlindKeyAPI_blind15Sign(JNIEnv *env, jobject thiz,
jbyteArray ed25519_secret_key,
jstring server_pub_key,
jbyteArray message) {
return jni_utils::run_catching_cxx_exception_or_throws<jbyteArray>(env, [=] {
auto data = session::blind15_sign(
jni_utils::JavaByteArrayRef(env, ed25519_secret_key).get(),
jni_utils::JavaStringRef(env, server_pub_key).view(),
jni_utils::JavaByteArrayRef(env, message).get()
);
return util::bytes_from_vector(env, data);
});
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_network_loki_messenger_libsession_1util_util_BlindKeyAPI_sessionIdMatchesBlindedId(JNIEnv *env,
jobject thiz,
jstring session_id,
jstring blinded_id,
jstring server_pub_key) {
return jni_utils::run_catching_cxx_exception_or<jboolean>([=]() -> jboolean {
return session::session_id_matches_blinded_id(
jni_utils::JavaStringRef(env, session_id).view(),
jni_utils::JavaStringRef(env, blinded_id).view(),
jni_utils::JavaStringRef(env, server_pub_key).view()
);
}, [](const char *) -> jboolean {
return false;
});
}
27 changes: 27 additions & 0 deletions library/src/main/cpp/curve25519.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "jni_utils.h"

#include <session/curve25519.hpp>

extern "C"
JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_Curve25519_fromED25519(JNIEnv *env, jobject thiz,
jbyteArray ed25519_public_key,
jbyteArray ed25519_private_key) {
return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] {
auto pk = session::curve25519::to_curve25519_pubkey(jni_utils::JavaByteArrayRef(env, ed25519_public_key).get());
auto sk = session::curve25519::to_curve25519_seckey(jni_utils::JavaByteArrayRef(env, ed25519_private_key).get());

return jni_utils::new_key_pair(env, util::bytes_from_span(env, pk), util::bytes_from_span(env, sk));
});
}


extern "C"
JNIEXPORT jbyteArray JNICALL
Java_network_loki_messenger_libsession_1util_Curve25519_pubKeyFromED25519(JNIEnv *env, jobject thiz,
jbyteArray ed25519_public_key) {
return jni_utils::run_catching_cxx_exception_or_throws<jbyteArray>(env, [=] {
auto pk = session::curve25519::to_curve25519_pubkey(jni_utils::JavaByteArrayRef(env, ed25519_public_key).get());
return util::bytes_from_span(env, pk);
});
}
13 changes: 13 additions & 0 deletions library/src/main/cpp/ed25519.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,17 @@ Java_network_loki_messenger_libsession_1util_ED25519_verify(JNIEnv *env, jobject
jni_utils::JavaByteArrayRef(env, message).get()
);
});
}

extern "C"
JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_ED25519_generate(JNIEnv *env, jobject thiz,
jbyteArray seed) {
return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] {
auto [pk, sk] = seed
? session::ed25519::ed25519_key_pair(jni_utils::JavaByteArrayRef(env, seed).get())
: session::ed25519::ed25519_key_pair();

return jni_utils::new_key_pair(env, util::bytes_from_span(env, pk), util::bytes_from_span(env, sk));
});
}
34 changes: 34 additions & 0 deletions library/src/main/cpp/encryption.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,38 @@ Java_network_loki_messenger_libsession_1util_SessionEncrypt_encryptForBlindedRec

return jni_utils::session_bytes_from_range(env, data);
});
}

extern "C"
JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_SessionEncrypt_decryptPushNotification(JNIEnv *env,
jobject thiz,
jbyteArray message,
jbyteArray secret_key) {
return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] {
auto data = session::decrypt_push_notification(
jni_utils::JavaByteArrayRef(env, message).get(),
jni_utils::JavaByteArrayRef(env, secret_key).get()
);

return jni_utils::session_bytes_from_range(env, data);
});
}

extern "C"
JNIEXPORT jstring JNICALL
Java_network_loki_messenger_libsession_1util_SessionEncrypt_decryptOnsResponse(JNIEnv *env,
jobject thiz,
jstring lowercase_name,
jbyteArray ciphertext,
jbyteArray nonce) {
return jni_utils::run_catching_cxx_exception_or_throws<jstring>(env, [=] {
auto data = session::decrypt_ons_response(
jni_utils::JavaStringRef(env, lowercase_name).view(),
jni_utils::JavaByteArrayRef(env, ciphertext).get(),
nonce ? std::make_optional(jni_utils::JavaByteArrayRef(env, nonce).get()) : std::nullopt
);

return util::jstringFromOptional(env, data);
});
}
17 changes: 17 additions & 0 deletions library/src/main/cpp/hash.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "jni_utils.h"

#include <session/hash.hpp>

extern "C"
JNIEXPORT void JNICALL
Java_network_loki_messenger_libsession_1util_Hash_hash(JNIEnv *env, jobject thiz,
jbyteArray message,
jbyteArray hashOut,
jbyteArray key) {
jni_utils::run_catching_cxx_exception_or_throws<void>(env, [=] {
session::hash::hash(
jni_utils::JavaByteArrayRef(env, hashOut).get(),
jni_utils::JavaByteArrayRef(env, message).get(),
key ? std::make_optional(jni_utils::JavaByteArrayRef(env, key).get()) : std::nullopt);
});
}
6 changes: 6 additions & 0 deletions library/src/main/cpp/jni_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,10 @@ namespace jni_utils {
jmethodID constructor = env->GetMethodID(pair_class.get(), "<init>", "(Ljava/lang/Object;Ljava/lang/Object;)V");
return env->NewObject(pair_class.get(), constructor, first, second);
}

jobject new_key_pair(JNIEnv *env, jbyteArray pubKey, jbyteArray secKey) {
auto kp_class = JavaLocalRef(env, env->FindClass("network/loki/messenger/libsession_util/util/KeyPair"));
jmethodID kp_constructor = env->GetMethodID(kp_class.get(), "<init>", "([B[B)V");
return env->NewObject(kp_class.get(), kp_constructor, pubKey, secKey);
}
}
32 changes: 32 additions & 0 deletions library/src/main/cpp/jni_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,37 @@ namespace jni_utils {
*/
jobject new_kotlin_pair(JNIEnv *env, jobject first, jobject second);

/**
* Create a new KeyPair object
*/
jobject new_key_pair(JNIEnv *env, jbyteArray pubKey, jbyteArray secKey);

class JavaStringRef {
JNIEnv *env;
jstring s;
std::span<char> data;

public:
JavaStringRef(JNIEnv *env, jstring s) : env(env), s(s) {
const char *c_str = env->GetStringUTFChars(s, nullptr);
data = std::span<char>(const_cast<char *>(c_str), env->GetStringUTFLength(s));
}

~JavaStringRef() {
env->ReleaseStringUTFChars(s, data.data());
}

// Get the data as a string view. Only valid during the lifetime of this object.
std::string_view view() const {
return std::string_view(data.data(), data.size());
}

// Get the data as a span. Only valid during the lifetime of this object.
std::span<char> get() const {
return data;
}
};

/**
* A RAII wrapper for a Java byte array. This will automatically release the byte array when it goes out of scope.
*/
Expand All @@ -164,6 +195,7 @@ namespace jni_utils {
env->ReleaseByteArrayElements(byte_array, reinterpret_cast<jbyte *>(data.data()), 0);
}

// Get the data as a span. Only valid during the lifetime of this object.
std::span<unsigned char> get() const {
return data;
}
Expand Down
47 changes: 7 additions & 40 deletions library/src/main/cpp/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,43 +173,10 @@ namespace util {
}
}

extern "C"
JNIEXPORT jobject JNICALL
Java_network_loki_messenger_libsession_1util_util_Sodium_ed25519KeyPair(JNIEnv *env, jobject thiz, jbyteArray seed) {
std::array<unsigned char, 32> ed_pk; // NOLINT(cppcoreguidelines-pro-type-member-init)
std::array<unsigned char, 64> ed_sk; // NOLINT(cppcoreguidelines-pro-type-member-init)
auto seed_bytes = util::vector_from_bytes(env, seed);
crypto_sign_ed25519_seed_keypair(ed_pk.data(), ed_sk.data(), seed_bytes.data());

auto kp_class = jni_utils::JavaLocalRef(env, env->FindClass("network/loki/messenger/libsession_util/util/KeyPair"));
jmethodID kp_constructor = env->GetMethodID(kp_class.get(), "<init>", "(Lnetwork/loki/messenger/libsession_util/util/Bytes;Lnetwork/loki/messenger/libsession_util/util/Bytes;)V");

return env->NewObject(kp_class.get(), kp_constructor,
jni_utils::JavaLocalRef(env, jni_utils::session_bytes_from_range(env, ed_pk)).get(),
jni_utils::JavaLocalRef(env, jni_utils::session_bytes_from_range(env, ed_sk)).get()
);
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_network_loki_messenger_libsession_1util_util_Sodium_ed25519PkToCurve25519(JNIEnv *env,
jobject thiz,
jbyteArray pk) {
auto ed_pk = util::vector_from_bytes(env, pk);
std::array<unsigned char, 32> curve_pk; // NOLINT(cppcoreguidelines-pro-type-member-init)
int success = crypto_sign_ed25519_pk_to_curve25519(curve_pk.data(), ed_pk.data());
if (success != 0) {
jclass exception = env->FindClass("java/lang/Exception");
env->ThrowNew(exception, "Invalid crypto_sign_ed25519_pk_to_curve25519 operation");
return nullptr;
}
jbyteArray curve_pk_jarray = util::bytes_from_span(env, std::span<const unsigned char> {curve_pk.data(), curve_pk.size()});
return curve_pk_jarray;
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_network_loki_messenger_libsession_1util_util_Sodium_encryptForMultipleSimple(
Java_network_loki_messenger_libsession_1util_util_MultiEncrypt_encryptForMultipleSimple(
JNIEnv *env, jobject thiz, jobjectArray messages, jobjectArray recipients,
jbyteArray ed25519_secret_key, jstring domain) {
// messages and recipients have to be the same size
Expand Down Expand Up @@ -258,12 +225,12 @@ Java_network_loki_messenger_libsession_1util_util_Sodium_encryptForMultipleSimpl

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_network_loki_messenger_libsession_1util_util_Sodium_decryptForMultipleSimple(JNIEnv *env,
jobject thiz,
jbyteArray encoded,
jbyteArray secret_key,
jbyteArray sender_pub_key,
jstring domain) {
Java_network_loki_messenger_libsession_1util_util_MultiEncrypt_decryptForMultipleSimple(JNIEnv *env,
jobject thiz,
jbyteArray encoded,
jbyteArray secret_key,
jbyteArray sender_pub_key,
jstring domain) {
auto sk_vector = util::vector_from_bytes(env, secret_key);
auto encoded_vector = util::vector_from_bytes(env, encoded);
auto pub_vector = util::vector_from_bytes(env, sender_pub_key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import network.loki.messenger.libsession_util.util.GroupMember
import network.loki.messenger.libsession_util.util.UserPic
import java.io.Closeable

sealed class Config(initialPointer: Long): Closeable {
sealed class Config(initialPointer: Long): Closeable, LibSessionUtilCApi() {
var pointer = initialPointer
private set

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package network.loki.messenger.libsession_util

import network.loki.messenger.libsession_util.util.KeyPair

object Curve25519 : LibSessionUtilCApi() {
private external fun fromED25519(
ed25519PublicKey: ByteArray,
ed25519PrivateKey: ByteArray,
): KeyPair

fun fromED25519(keyPair: KeyPair): KeyPair =
fromED25519(
ed25519PublicKey = keyPair.pubKey.data,
ed25519PrivateKey = keyPair.secretKey.data
)

external fun pubKeyFromED25519(
ed25519PublicKey: ByteArray,
): ByteArray
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package network.loki.messenger.libsession_util

object ED25519 {
import network.loki.messenger.libsession_util.util.KeyPair

object ED25519 : LibSessionUtilCApi() {
/**
* Sign a message using the ed25519 private key
*
Expand All @@ -25,4 +27,6 @@ object ED25519 {
message: ByteArray,
signature: ByteArray,
): Boolean

external fun generate(seed: ByteArray?): KeyPair
}
Loading