mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-04-10 01:35:50 +00:00
multiplatform: local file encryption (#3043)
* multiplatform: file encryption * setting * fixed sharing * check * fixes, change lock icon * update JNI bindings (crashes on desktop) * fix JNI * fix errors and warnings * fix saving --------- Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
a87aaa50c7
commit
54e1e10382
@@ -1,5 +1,6 @@
|
||||
#include <jni.h>
|
||||
//#include <string.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
//#include <stdlib.h>
|
||||
//#include <android/log.h>
|
||||
|
||||
@@ -45,6 +46,10 @@ extern char *chat_recv_msg_wait(chat_ctrl ctrl, const int wait);
|
||||
extern char *chat_parse_markdown(const char *str);
|
||||
extern char *chat_parse_server(const char *str);
|
||||
extern char *chat_password_hash(const char *pwd, const char *salt);
|
||||
extern char *chat_write_file(const char *path, char *ptr, int length);
|
||||
extern char *chat_read_file(const char *path, const char *key, const char *nonce);
|
||||
extern char *chat_encrypt_file(const char *from_path, const char *to_path);
|
||||
extern char *chat_decrypt_file(const char *from_path, const char *key, const char *nonce, const char *to_path);
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_chat_simplex_common_platform_CoreKt_chatMigrateInit(JNIEnv *env, __unused jclass clazz, jstring dbPath, jstring dbKey, jstring confirm) {
|
||||
@@ -115,3 +120,76 @@ Java_chat_simplex_common_platform_CoreKt_chatPasswordHash(JNIEnv *env, __unused
|
||||
(*env)->ReleaseStringUTFChars(env, salt, _salt);
|
||||
return res;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_chat_simplex_common_platform_CoreKt_chatWriteFile(JNIEnv *env, jclass clazz, jstring path, jobject buffer) {
|
||||
const char *_path = (*env)->GetStringUTFChars(env, path, JNI_FALSE);
|
||||
jbyte *buff = (jbyte *) (*env)->GetDirectBufferAddress(env, buffer);
|
||||
jlong capacity = (*env)->GetDirectBufferCapacity(env, buffer);
|
||||
jstring res = (*env)->NewStringUTF(env, chat_write_file(_path, buff, capacity));
|
||||
(*env)->ReleaseStringUTFChars(env, path, _path);
|
||||
return res;
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_chat_simplex_common_platform_CoreKt_chatReadFile(JNIEnv *env, jclass clazz, jstring path, jstring key, jstring nonce) {
|
||||
const char *_path = (*env)->GetStringUTFChars(env, path, JNI_FALSE);
|
||||
const char *_key = (*env)->GetStringUTFChars(env, key, JNI_FALSE);
|
||||
const char *_nonce = (*env)->GetStringUTFChars(env, nonce, JNI_FALSE);
|
||||
|
||||
jbyte *res = chat_read_file(_path, _key, _nonce);
|
||||
(*env)->ReleaseStringUTFChars(env, path, _path);
|
||||
(*env)->ReleaseStringUTFChars(env, key, _key);
|
||||
(*env)->ReleaseStringUTFChars(env, nonce, _nonce);
|
||||
|
||||
jint status = (jint)res[0];
|
||||
jbyteArray arr;
|
||||
if (status == 0) {
|
||||
union {
|
||||
uint32_t w;
|
||||
uint8_t b[4];
|
||||
} len;
|
||||
len.b[0] = (uint8_t)res[1];
|
||||
len.b[1] = (uint8_t)res[2];
|
||||
len.b[2] = (uint8_t)res[3];
|
||||
len.b[3] = (uint8_t)res[4];
|
||||
arr = (*env)->NewByteArray(env, len.w);
|
||||
(*env)->SetByteArrayRegion(env, arr, 0, len.w, res + 5);
|
||||
} else {
|
||||
int len = strlen(res + 1); // + 1 offset here is to not include status byte
|
||||
arr = (*env)->NewByteArray(env, len);
|
||||
(*env)->SetByteArrayRegion(env, arr, 0, len, res + 1);
|
||||
}
|
||||
|
||||
jobjectArray ret = (jobjectArray)(*env)->NewObjectArray(env, 2, (*env)->FindClass(env, "java/lang/Object"), NULL);
|
||||
jobject statusObj = (*env)->NewObject(env, (*env)->FindClass(env, "java/lang/Integer"),
|
||||
(*env)->GetMethodID(env, (*env)->FindClass(env, "java/lang/Integer"), "<init>", "(I)V"),
|
||||
status);
|
||||
(*env)->SetObjectArrayElement(env, ret, 0, statusObj);
|
||||
(*env)->SetObjectArrayElement(env, ret, 1, arr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_chat_simplex_common_platform_CoreKt_chatEncryptFile(JNIEnv *env, jclass clazz, jstring from_path, jstring to_path) {
|
||||
const char *_from_path = (*env)->GetStringUTFChars(env, from_path, JNI_FALSE);
|
||||
const char *_to_path = (*env)->GetStringUTFChars(env, to_path, JNI_FALSE);
|
||||
jstring res = (*env)->NewStringUTF(env, chat_encrypt_file(_from_path, _to_path));
|
||||
(*env)->ReleaseStringUTFChars(env, from_path, _from_path);
|
||||
(*env)->ReleaseStringUTFChars(env, to_path, _to_path);
|
||||
return res;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_chat_simplex_common_platform_CoreKt_chatDecryptFile(JNIEnv *env, jclass clazz, jstring from_path, jstring key, jstring nonce, jstring to_path) {
|
||||
const char *_from_path = (*env)->GetStringUTFChars(env, from_path, JNI_FALSE);
|
||||
const char *_key = (*env)->GetStringUTFChars(env, key, JNI_FALSE);
|
||||
const char *_nonce = (*env)->GetStringUTFChars(env, nonce, JNI_FALSE);
|
||||
const char *_to_path = (*env)->GetStringUTFChars(env, to_path, JNI_FALSE);
|
||||
jstring res = (*env)->NewStringUTF(env, chat_decrypt_file(_from_path, _key, _nonce, _to_path));
|
||||
(*env)->ReleaseStringUTFChars(env, from_path, _from_path);
|
||||
(*env)->ReleaseStringUTFChars(env, key, _key);
|
||||
(*env)->ReleaseStringUTFChars(env, nonce, _nonce);
|
||||
(*env)->ReleaseStringUTFChars(env, to_path, _to_path);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <jni.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// from the RTS
|
||||
void hs_init(int * argc, char **argv[]);
|
||||
@@ -20,7 +21,10 @@ extern char *chat_recv_msg_wait(chat_ctrl ctrl, const int wait);
|
||||
extern char *chat_parse_markdown(const char *str);
|
||||
extern char *chat_parse_server(const char *str);
|
||||
extern char *chat_password_hash(const char *pwd, const char *salt);
|
||||
|
||||
extern char *chat_write_file(const char *path, char *ptr, int length);
|
||||
extern char *chat_read_file(const char *path, const char *key, const char *nonce);
|
||||
extern char *chat_encrypt_file(const char *from_path, const char *to_path);
|
||||
extern char *chat_decrypt_file(const char *from_path, const char *key, const char *nonce, const char *to_path);
|
||||
|
||||
// As a reference: https://stackoverflow.com/a/60002045
|
||||
jstring decode_to_utf8_string(JNIEnv *env, char *string) {
|
||||
@@ -128,3 +132,76 @@ Java_chat_simplex_common_platform_CoreKt_chatPasswordHash(JNIEnv *env, jclass cl
|
||||
(*env)->ReleaseStringUTFChars(env, salt, _salt);
|
||||
return res;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_chat_simplex_common_platform_CoreKt_chatWriteFile(JNIEnv *env, jclass clazz, jstring path, jobject buffer) {
|
||||
const char *_path = encode_to_utf8_chars(env, path);
|
||||
jbyte *buff = (jbyte *) (*env)->GetDirectBufferAddress(env, buffer);
|
||||
jlong capacity = (*env)->GetDirectBufferCapacity(env, buffer);
|
||||
jstring res = decode_to_utf8_string(env, chat_write_file(_path, buff, capacity));
|
||||
(*env)->ReleaseStringUTFChars(env, path, _path);
|
||||
return res;
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_chat_simplex_common_platform_CoreKt_chatReadFile(JNIEnv *env, jclass clazz, jstring path, jstring key, jstring nonce) {
|
||||
const char *_path = encode_to_utf8_chars(env, path);
|
||||
const char *_key = encode_to_utf8_chars(env, key);
|
||||
const char *_nonce = encode_to_utf8_chars(env, nonce);
|
||||
|
||||
jbyte *res = chat_read_file(_path, _key, _nonce);
|
||||
(*env)->ReleaseStringUTFChars(env, path, _path);
|
||||
(*env)->ReleaseStringUTFChars(env, key, _key);
|
||||
(*env)->ReleaseStringUTFChars(env, nonce, _nonce);
|
||||
|
||||
jint status = (jint)res[0];
|
||||
jbyteArray arr;
|
||||
if (status == 0) {
|
||||
union {
|
||||
uint32_t w;
|
||||
uint8_t b[4];
|
||||
} len;
|
||||
len.b[0] = (uint8_t)res[1];
|
||||
len.b[1] = (uint8_t)res[2];
|
||||
len.b[2] = (uint8_t)res[3];
|
||||
len.b[3] = (uint8_t)res[4];
|
||||
arr = (*env)->NewByteArray(env, len.w);
|
||||
(*env)->SetByteArrayRegion(env, arr, 0, len.w, res + 5);
|
||||
} else {
|
||||
int len = strlen(res + 1); // + 1 offset here is to not include status byte
|
||||
arr = (*env)->NewByteArray(env, len);
|
||||
(*env)->SetByteArrayRegion(env, arr, 0, len, res + 1);
|
||||
}
|
||||
|
||||
jobjectArray ret = (jobjectArray)(*env)->NewObjectArray(env, 2, (*env)->FindClass(env, "java/lang/Object"), NULL);
|
||||
jobject statusObj = (*env)->NewObject(env, (*env)->FindClass(env, "java/lang/Integer"),
|
||||
(*env)->GetMethodID(env, (*env)->FindClass(env, "java/lang/Integer"), "<init>", "(I)V"),
|
||||
status);
|
||||
(*env)->SetObjectArrayElement(env, ret, 0, statusObj);
|
||||
(*env)->SetObjectArrayElement(env, ret, 1, arr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_chat_simplex_common_platform_CoreKt_chatEncryptFile(JNIEnv *env, jclass clazz, jstring from_path, jstring to_path) {
|
||||
const char *_from_path = encode_to_utf8_chars(env, from_path);
|
||||
const char *_to_path = encode_to_utf8_chars(env, to_path);
|
||||
jstring res = decode_to_utf8_string(env, chat_encrypt_file(_from_path, _to_path));
|
||||
(*env)->ReleaseStringUTFChars(env, from_path, _from_path);
|
||||
(*env)->ReleaseStringUTFChars(env, to_path, _to_path);
|
||||
return res;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_chat_simplex_common_platform_CoreKt_chatDecryptFile(JNIEnv *env, jclass clazz, jstring from_path, jstring key, jstring nonce, jstring to_path) {
|
||||
const char *_from_path = encode_to_utf8_chars(env, from_path);
|
||||
const char *_key = encode_to_utf8_chars(env, key);
|
||||
const char *_nonce = encode_to_utf8_chars(env, nonce);
|
||||
const char *_to_path = encode_to_utf8_chars(env, to_path);
|
||||
jstring res = decode_to_utf8_string(env, chat_decrypt_file(_from_path, _key, _nonce, _to_path));
|
||||
(*env)->ReleaseStringUTFChars(env, from_path, _from_path);
|
||||
(*env)->ReleaseStringUTFChars(env, key, _key);
|
||||
(*env)->ReleaseStringUTFChars(env, nonce, _nonce);
|
||||
(*env)->ReleaseStringUTFChars(env, to_path, _to_path);
|
||||
return res;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user