从 JNI 调用 getWritableDatabase (SQLCipher java 方法)
Calling getWritableDatabase (SQLCipher java method) from JNI
我有一个Java代码来打开SqlCipher数据库。我想从JNI调用getWritable数据库函数来隐藏密码。
在方法(sqlauth.cpp(中从SQLiteOpenHelper类调用getWritableDatabas方法时出错Java_com_company_pos_DbHelper_getWritableSqlite我的代码有什么问题?
数据库助手.java
public class DbHelper extends SQLiteOpenHelper {
//private final static String PASSWORD= "MyPassword"
private final static String TAG = "DbHelper";
private static SQLiteDatabase db = null;
/* This method works only password is not secure.
public void open() {
try {
//The password isn't hidden
db = getWritableDatabase(PASSWORD);
} catch (SQLiteException e) {
Log.e(TAG, e.getMessage());
}
}
*/
static {
System.loadLibrary("sqlauth");
}
private native SQLiteDatabase getWritableSqlite();
public void open() {
try {
//The password is hidden in jNI
db = getWritableSqlite();
} catch (SQLiteException e) {
Log.e(TAG, e.getMessage());
}
}
}
杰尼
斯劳斯·
#include <jni.h>
#include <string.h>
#include <iostream>
#ifndef SQLAUTH_H
#define SQLAUTH_H
#endif
static char *CLS_SQLITEOPENHELPER = (char *) "net/sqlcipher/database/SQLiteOpenHelper";
static char *MID_GETWRITABLEDATABASE = (char *) "getWritableDatabase";
static char *SIG_GETWRITABLEDATABASE = (char *) "(Ljava/lang/String;)Lnet/sqlcipher/database/SQLiteDatabase;";
#ifdef __cplusplus
extern "C" {
#endif
JavaVM *_jvm;
jclass _clsSQLiteOpenHelper;
jobject _objGetWritableDatabase;
jmethodID _midGetWritableDatabase;
JNIEnv *getEnv();
jboolean tryCatch();
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved);
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *jvm, void *reserved);
JNIEXPORT jobject JNICALL Java_com_company_pos_DbHelper_getWritableSqlite(JNIEnv *e, jobject obj);
#ifdef __cplusplus
}
#endif
斯劳斯.cpp
#include "sqlauth.h"
#ifdef __cplusplus
extern "C" {
#endif
JNIEnv *getEnv() {
JNIEnv *env;
_jvm->GetEnv((void **) &env, JNI_VERSION_1_6);
return env;
}
jboolean tryCatch() {
JNIEnv *env = getEnv();
if (env == NULL) {
return JNI_TRUE;
}
jthrowable ex = env->ExceptionOccurred();
if (ex) {
env->ExceptionClear();
return JNI_TRUE;
}
return JNI_FALSE;
}
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *jvm, void *reserved) {
JNIEnv *env;
jclass clsDbHelper, clsSqliteDatabase, clsSQLiteOpenHelper;
_jvm = jvm;
if (jvm->GetEnv((void **) &env, JNI_VERSION_1_6)) {
return JNI_ERR;
}
// SQLiteOpenHelper.java
clsSQLiteOpenHelper = env->FindClass(CLS_SQLITEOPENHELPER);
if (clsSQLiteOpenHelper == NULL) {
return JNI_ERR;
}
_clsSQLiteOpenHelper = (jclass) env->NewWeakGlobalRef(clsSQLiteOpenHelper);
if (_clsSQLiteOpenHelper == NULL) {
return JNI_ERR;
}
_midGetWritableDatabase = env->GetMethodID(_clsSQLiteOpenHelper, MID_GETWRITABLEDATABASE, SIG_GETWRITABLEDATABASE);
if (_midGetWritableDatabase == NULL) {
return JNI_ERR;
}
return JNI_VERSION_1_6;
}
JNIEXPORT void JNICALL
JNI_OnUnload(JavaVM *jvm, void *reserved) {
JNIEnv *env;
if (jvm->GetEnv((void **) &env, JNI_VERSION_1_6)) {
return;
}
env->DeleteWeakGlobalRef(_clsSQLiteOpenHelper);
return;
}
JNIEXPORT jobject JNICALL
Java_com_company_pos_DbHelper_getWritableSqlite(JNIEnv *e, jobject obj) {
JNIEnv *env = getEnv();
if (env == NULL || obj == NULL) {
return NULL;
}
// Error in here when calling getWritableDatabase
// from net/sqlcipher/database/SQLiteOpenHelper
_objGetWritableDatabase = env->CallObjectMethod(_clsSQLiteOpenHelper, _midGetWritableDatabase, env->NewStringUTF("MyPassword"));
if (_objGetWritableDatabase == NULL || tryCatch()) {
return NULL; // Program stop in here.
}
return _objGetWritableDatabase;
}
#ifdef __cplusplus
}
#endif
SQLiteOpenHelper.class
public synchronized SQLiteDatabase getWritableDatabase(String password) {
return this.getWritableDatabase(password == null?null:password.toCharArray());
}
根据 pskink 的指导,我可以通过更改代码来解决上述问题,如下所示:
JNIEXPORT jobject JNICALL
Java_com_company_pos_DbHelper_getWritableSqlite(JNIEnv *e, jobject obj) {
JNIEnv *env = getEnv();
if (env == NULL || obj == NULL) {
return NULL;
}
// Error in here when calling getWritableDatabase from net/sqlcipher/database/SQLiteOpenHelper
_objGetWritableDatabase = env->CallObjectMethod(_clsSQLiteOpenHelper, _midGetWritableDatabase, env->NewStringUTF("MyPassword"));
if (_objGetWritableDatabase == NULL || tryCatch()) {
return NULL; // Program stop in here.
}
return _objGetWritableDatabase;
}
自
JNIEXPORT jobject JNICALL
Java_com_company_pos_DbHelper_getWritableSqlite(JNIEnv *e, jobject obj) {
JNIEnv *env = getEnv();
if (env == NULL || obj == NULL) {
return NULL;
}
_objGetWritableDatabase = env->CallObjectMethod(obj, _midGetWritableDatabase, env->NewStringUTF("MyPassword"));
if (_objGetWritableDatabase == NULL || tryCatch()) {
return NULL;
}
return _objGetWritableDatabase;
}
不安全的密码
您可以使用十六进制字符串值(以 16 为基数(更改 MyPassword。 但是字符串形式的存储密码是不安全的,我们可以查看 使用记事本++打开.so文件的pasword
static char *MyPassword = (char *) "93CEFC75923EA0370B6B04CECA4E7A99"
安全密码
将加密的密码以字节数组的形式存储比较难读取。读取时解密密码。像这样的例子:
const size_t BIT_LENGTH = 16;
static unsigned char bit_pwd[] = {0x13, 0x4E, 0x83, 0xF4, 0xEC, 0xBC, 0xDD, 0xB4, 0x77, 0xEF, 0x7F, 0x4B, 0xB0, 0xC8, 0x03, 0x1E};
static unsigned char chr_pwd[BIT_LENGTH * 2];
char *getPwd() {
unsigned char c1 = 0x80;
unsigned char c2 = c1;
unsigned char *p = chr_pwd;
memset(chr_pwd, ' ', BIT_LENGTH * 2);
for (jint i = 0; i < BIT_LENGTH; i++) {
if (i % 2 != 0) {
bit_pwd[i] ^= c1++;
}
else {
bit_pwd[i] ^= c2--;
}
p += sprintf((char *) p, "%02X", bit_pwd[i]);
}
chr_pwd[BIT_LENGTH * 2] = ' ';
return (char *) chr_pwd;
}
// You will get real password ("93CEFC75923EA0370B6B04CECA4E7A99") from getPwd method.
_objGetWritableDatabase = env->CallObjectMethod(obj, _midGetWritableDatabase, env->NewStringUTF(getPwd()));
相关文章:
- Android:使用 c++ 中的 byte[] 参数调用 java 方法
- 如何在JNI中从线程内部调用JAVA方法
- Qt 调用具有 1 个以上参数的 java 方法
- Android 无法从本机代码调用 Java 方法 JNI
- 是否可以在SO库中公开C API以访问Android JAVA方法
- 如何从 NDK(JNI) 调用特定的 Java 方法
- 从 JNI 调用 getWritableDatabase (SQLCipher java 方法)
- 使用C 修改Java方法/字节码
- 使用 JNI 从 cpp 调用 java 方法时出现异常
- 在Qt中从C ++调用Java方法
- 使用C 获取Java对象来调用Java方法
- JNI:从C++调用JAVA方法,返回对象,引用和GC
- 从 Java 调用 c++,然后从相同的 c++ 方法调用 java 方法
- 使用jni.h在C++中编译java方法时出现构建错误
- 如何从C++/Qt调用QtActivity中的非静态Java方法
- 从Android NDK SIGSEGV调用Java方法
- 从c++调用非静态java方法时出错
- 使本机代码访问java方法和数据成员
- Android NDK调用java方法表单cpp
- 当我从C++调用Java方法时,我应该调用PushLocalFrame和PopLocalFrame吗