Skip to content

Commit

Permalink
Add discord link
Browse files Browse the repository at this point in the history
  • Loading branch information
ospfranco committed Oct 31, 2024
1 parent 4ff8ad3 commit e999dc6
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 145 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ Modern encryption module for React Native. Uses `Keychain` on iOS and the [offic

Created by [ospfranco](https://github.com/sponsors/ospfranco).

Join the Discord

https://discord.gg/W9XmqCQCKP

## Motivation

Other React Native stores hand-roll their encryption, via OpenSSL (does not use hardware when possible) or raw implementation of algorithms (outdated algorithms or improper implementations).
Expand Down
268 changes: 123 additions & 145 deletions android/cpp-adapter.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
#include <jni.h>
#include "bindings.h"
#include "logs.h"
#include <ReactCommon/CallInvokerHolder.h>
#include <fbjni/fbjni.h>
#include <iostream>
#include <jni.h>
#include <jsi/jsi.h>
#include <typeinfo>
#include "bindings.h"
#include <iostream>

namespace jni = facebook::jni;
namespace react = facebook::react;
namespace jsi = facebook::jsi;


JavaVM *java_vm;
jclass java_class;
jobject java_object;
Expand All @@ -23,40 +21,36 @@ jobject java_object;
* See https://stackoverflow.com/a/30026231 for detailed explanation
*/

void DeferThreadDetach(JNIEnv *env)
{
static pthread_key_t thread_key;

// Set up a Thread Specific Data key, and a callback that
// will be executed when a thread is destroyed.
// This is only done once, across all threads, and the value
// associated with the key for any given thread will initially
// be NULL.
static auto run_once = []
{
const auto err = pthread_key_create(&thread_key, [](void *ts_env)
{
if (ts_env) {
java_vm->DetachCurrentThread();
} });
if (err)
{
// Failed to create TSD key. Throw an exception if you want to.
}
return 0;
}();

// For the callback to actually be executed when a thread exits
// we need to associate a non-NULL value with the key on that thread.
// We can use the JNIEnv* as that value.
const auto ts_env = pthread_getspecific(thread_key);
if (!ts_env)
{
if (pthread_setspecific(thread_key, env))
{
// Failed to set thread-specific value for key. Throw an exception if you want to.
}
void DeferThreadDetach(JNIEnv *env) {
static pthread_key_t thread_key;

// Set up a Thread Specific Data key, and a callback that
// will be executed when a thread is destroyed.
// This is only done once, across all threads, and the value
// associated with the key for any given thread will initially
// be NULL.
static auto run_once = [] {
const auto err = pthread_key_create(&thread_key, [](void *ts_env) {
if (ts_env) {
java_vm->DetachCurrentThread();
}
});
if (err) {
// Failed to create TSD key. Throw an exception if you want to.
}
return 0;
}();

// For the callback to actually be executed when a thread exits
// we need to associate a non-NULL value with the key on that thread.
// We can use the JNIEnv* as that value.
const auto ts_env = pthread_getspecific(thread_key);
if (!ts_env) {
if (pthread_setspecific(thread_key, env)) {
// Failed to set thread-specific value for key. Throw an exception if you
// want to.
}
}
}

/**
Expand All @@ -68,127 +62,111 @@ void DeferThreadDetach(JNIEnv *env)
*
* See https://stackoverflow.com/a/30026231 for detailed explanation
*/
JNIEnv *GetJniEnv()
{
JNIEnv *env = nullptr;
// We still call GetEnv first to detect if the thread already
// is attached. This is done to avoid setting up a DetachCurrentThread
// call on a Java thread.

// g_vm is a global.
auto get_env_result = java_vm->GetEnv((void **)&env, JNI_VERSION_1_6);
if (get_env_result == JNI_EDETACHED)
{
if (java_vm->AttachCurrentThread(&env, NULL) == JNI_OK)
{
DeferThreadDetach(env);
}
else
{
// Failed to attach thread. Throw an exception if you want to.
}
JNIEnv *GetJniEnv() {
JNIEnv *env = nullptr;
// We still call GetEnv first to detect if the thread already
// is attached. This is done to avoid setting up a DetachCurrentThread
// call on a Java thread.

// g_vm is a global.
auto get_env_result = java_vm->GetEnv((void **)&env, JNI_VERSION_1_6);
if (get_env_result == JNI_EDETACHED) {
if (java_vm->AttachCurrentThread(&env, NULL) == JNI_OK) {
DeferThreadDetach(env);
} else {
// Failed to attach thread. Throw an exception if you want to.
}
else if (get_env_result == JNI_EVERSION)
{
// Unsupported JNI version. Throw an exception if you want to.
}
return env;
} else if (get_env_result == JNI_EVERSION) {
// Unsupported JNI version. Throw an exception if you want to.
}
return env;
}

jstring string2jstring(JNIEnv *env, const char *str)
{
return (*env).NewStringUTF(str);
jstring string2jstring(JNIEnv *env, const char *str) {
return (*env).NewStringUTF(str);
}

void set(const char* key, const char* value, bool withBiometrics)
{
JNIEnv *jniEnv = GetJniEnv();
java_class = jniEnv->GetObjectClass(java_object);
jmethodID mid = jniEnv->GetMethodID(java_class, "setItem", "(Ljava/lang/String;Ljava/lang/String;Z)V");
jstring jKey = string2jstring(jniEnv, key);
jstring jVal = string2jstring(jniEnv, value);
jvalue params[3];
params[0].l = jKey;
params[1].l = jVal;
params[2].z = withBiometrics;


jniEnv->CallVoidMethodA(java_object, mid, params);

jthrowable exObj = jniEnv->ExceptionOccurred();
if(exObj) {
jniEnv->ExceptionClear();

jclass clazz = jniEnv->GetObjectClass(exObj);
jmethodID getMessage = jniEnv->GetMethodID(clazz,
"toString",
"()Ljava/lang/String;");
jstring message = (jstring)jniEnv->CallObjectMethod(exObj, getMessage);
const char *mstr = jniEnv->GetStringUTFChars(message, NULL);
throw std::runtime_error(std::string(mstr));
}

void set(const char *key, const char *value, bool withBiometrics) {
JNIEnv *jniEnv = GetJniEnv();
java_class = jniEnv->GetObjectClass(java_object);
jmethodID mid = jniEnv->GetMethodID(
java_class, "setItem", "(Ljava/lang/String;Ljava/lang/String;Z)V");
jstring jKey = string2jstring(jniEnv, key);
jstring jVal = string2jstring(jniEnv, value);
jvalue params[3];
params[0].l = jKey;
params[1].l = jVal;
params[2].z = withBiometrics;

jniEnv->CallVoidMethodA(java_object, mid, params);

jthrowable exObj = jniEnv->ExceptionOccurred();
if (exObj) {
jniEnv->ExceptionClear();

jclass clazz = jniEnv->GetObjectClass(exObj);
jmethodID getMessage =
jniEnv->GetMethodID(clazz, "toString", "()Ljava/lang/String;");
jstring message = (jstring)jniEnv->CallObjectMethod(exObj, getMessage);
const char *mstr = jniEnv->GetStringUTFChars(message, NULL);
throw std::runtime_error(std::string(mstr));
}
}

std::string get(const char* key, bool withBiometrics)
{
JNIEnv *jniEnv = GetJniEnv();
java_class = jniEnv->GetObjectClass(java_object);
jmethodID mid = jniEnv->GetMethodID(java_class, "getItem", "(Ljava/lang/String;Z)Ljava/lang/String;");
jstring jKey = string2jstring(jniEnv, key);
jvalue params[3];
params[0].l = jKey;
params[1].z = withBiometrics;


jstring result = (jstring)jniEnv->CallObjectMethodA(java_object, mid, params);
jthrowable exObj = jniEnv->ExceptionOccurred();
if(exObj) {
jniEnv->ExceptionClear();

jclass clazz = jniEnv->GetObjectClass(exObj);
jmethodID getMessage = jniEnv->GetMethodID(clazz,
"toString",
"()Ljava/lang/String;");
jstring message = (jstring)jniEnv->CallObjectMethod(exObj, getMessage);
const char *mstr = jniEnv->GetStringUTFChars(message, NULL);
throw std::runtime_error(std::string(mstr));
}

if (result == NULL)
{
// TODO revisit this
return "";
}

std::string str = jniEnv->GetStringUTFChars(result, NULL);
return str;
std::string get(const char *key, bool withBiometrics) {
JNIEnv *jniEnv = GetJniEnv();
java_class = jniEnv->GetObjectClass(java_object);
jmethodID mid = jniEnv->GetMethodID(
java_class, "getItem", "(Ljava/lang/String;Z)Ljava/lang/String;");
jstring jKey = string2jstring(jniEnv, key);
jvalue params[3];
params[0].l = jKey;
params[1].z = withBiometrics;

jstring result = (jstring)jniEnv->CallObjectMethodA(java_object, mid, params);
jthrowable exObj = jniEnv->ExceptionOccurred();
if (exObj) {
jniEnv->ExceptionClear();

jclass clazz = jniEnv->GetObjectClass(exObj);
jmethodID getMessage =
jniEnv->GetMethodID(clazz, "toString", "()Ljava/lang/String;");
jstring message = (jstring)jniEnv->CallObjectMethod(exObj, getMessage);
const char *mstr = jniEnv->GetStringUTFChars(message, NULL);
throw std::runtime_error(std::string(mstr));
}

if (result == NULL) {
// TODO revisit this
return "";
}

std::string str = jniEnv->GetStringUTFChars(result, NULL);
return str;
}

void del(const char* key, bool withBiometrics)
{
JNIEnv *jniEnv = GetJniEnv();
java_class = jniEnv->GetObjectClass(java_object);
jmethodID mid = jniEnv->GetMethodID(java_class, "deleteItem", "(Ljava/lang/String;Z)V");
jstring jKey = string2jstring(jniEnv, key);
jvalue params[2];
params[0].l = jKey;
params[1].z = withBiometrics;

jniEnv->CallVoidMethodA(java_object, mid, params);
void del(const char *key, bool withBiometrics) {
JNIEnv *jniEnv = GetJniEnv();
java_class = jniEnv->GetObjectClass(java_object);
jmethodID mid =
jniEnv->GetMethodID(java_class, "deleteItem", "(Ljava/lang/String;Z)V");
jstring jKey = string2jstring(jniEnv, key);
jvalue params[2];
params[0].l = jKey;
params[1].z = withBiometrics;

jniEnv->CallVoidMethodA(java_object, mid, params);
}

extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved)
{
java_vm = jvm;
return JNI_VERSION_1_6;
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
java_vm = jvm;
return JNI_VERSION_1_6;
}

extern "C"
JNIEXPORT void JNICALL
extern "C" JNIEXPORT void JNICALL
Java_com_op_s2_OPS2Bridge_initialize(JNIEnv *env, jobject thiz, jlong jsi_ptr) {
auto rt = reinterpret_cast<jsi::Runtime *>(jsi_ptr);
java_object = env->NewGlobalRef(thiz);
auto rt = reinterpret_cast<jsi::Runtime *>(jsi_ptr);
java_object = env->NewGlobalRef(thiz);

ops2::install(*rt, &set, &get, &del);
ops2::install(*rt, &set, &get, &del);
}

0 comments on commit e999dc6

Please sign in to comment.