在 jni 中返回错误的 md5 哈希
Returning wrong md5 hash in jni
我正在尝试使用 original/untouched md5.h 和 md5c.c(github 源文件:https://github.com/sinhpn92/encryption-in-C/tree/master/app/src/main/cpp)为字符串生成 MD5 哈希。但是我的结果在任何时候都不对。当我使用三星 galaxy j 设备进行测试时,我的结果是正确的。但是当我使用 samsung galaxy s7 设备进行测试时,我的结果是错误的。我的代码有什么问题?有解决这个问题的建议吗?感谢您的支持。
这是我的项目:https://github.com/sinhpn92/encryption-in-C
我使用 cmake 配置 jni 库:
cmake_minimum_required(VERSION 3.4.1)
set(MD5SOURCES
src/main/cpp/md5.c)
add_library(native-lib
SHARED
src/main/cpp/native-lib.cpp
${MD5SOURCES})
find_library(log-lib
log )
target_link_libraries(native-lib
${log-lib} )
这是本机库:
#include <jni.h>
#include <string>
#include "md5.h"
extern "C"
jstring
Java_test_sinhpn_md5test_MainActivity_stringFromJNI(JNIEnv *env, jobject /* this */, jstring data) {
char *cstr = (char *) (env)->GetStringUTFChars(data, 0);
MD5_CTX context = {0};
MD5Init(&context);
MD5Update(&context, (unsigned char *) cstr, strlen(cstr));
unsigned char dest[16] = {0};
MD5Final(dest, &context);
env->ReleaseStringUTFChars(data, cstr);
int i;
char destination[32] = {0};
for (i = 0; i < 16; i++) {
sprintf(destination, "%s%02x", destination, dest[i]);
}
return env->NewStringUTF(destination);
}
我的build.gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "test.sinhpn.md5test"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.1.1'
testCompile 'junit:junit:4.12'
}
这是我的测试结果:
这两款手机使用不同的 ARM 指令集。
Galaxy J使用armeabi-v7a,而S7使用arm64-v8a。
根据您上面的构建,cmake 正在为所有架构制作 .so 文件,这会导致问题,因为本机代码中存在 32 位与 64 位转换问题。
但是,您的情况有一个简单的修复方法。您可以在默认配置中将构建限制为 abiFilters "armeabi-v7a"、"armeabi",如下所示
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
abiFilters "armeabi-v7a", "armeabi"
}
}
这应该仍然有效,因为 arm64v8a 向后兼容旧的 v7a 架构。
我已经通过替换解决了我的问题:
typedef unsigned long int UINT4;
在 md5.c -> typedef uint32_t UINT4;
。
我在两台设备上再次测试,一切正常。在 64 位机器上,long int(通常)是 64 位长而不是 32
我正在尝试使用 original/untouched md5.h 和 md5c.c(github 源文件:https://github.com/sinhpn92/encryption-in-C/tree/master/app/src/main/cpp)为字符串生成 MD5 哈希。但是我的结果在任何时候都不对。当我使用三星 galaxy j 设备进行测试时,我的结果是正确的。但是当我使用 samsung galaxy s7 设备进行测试时,我的结果是错误的。我的代码有什么问题?有解决这个问题的建议吗?感谢您的支持。
这是我的项目:https://github.com/sinhpn92/encryption-in-C
我使用 cmake 配置 jni 库:
cmake_minimum_required(VERSION 3.4.1)
set(MD5SOURCES
src/main/cpp/md5.c)
add_library(native-lib
SHARED
src/main/cpp/native-lib.cpp
${MD5SOURCES})
find_library(log-lib
log )
target_link_libraries(native-lib
${log-lib} )
这是本机库:
#include <jni.h>
#include <string>
#include "md5.h"
extern "C"
jstring
Java_test_sinhpn_md5test_MainActivity_stringFromJNI(JNIEnv *env, jobject /* this */, jstring data) {
char *cstr = (char *) (env)->GetStringUTFChars(data, 0);
MD5_CTX context = {0};
MD5Init(&context);
MD5Update(&context, (unsigned char *) cstr, strlen(cstr));
unsigned char dest[16] = {0};
MD5Final(dest, &context);
env->ReleaseStringUTFChars(data, cstr);
int i;
char destination[32] = {0};
for (i = 0; i < 16; i++) {
sprintf(destination, "%s%02x", destination, dest[i]);
}
return env->NewStringUTF(destination);
}
我的build.gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "test.sinhpn.md5test"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.1.1'
testCompile 'junit:junit:4.12'
}
这是我的测试结果:
这两款手机使用不同的 ARM 指令集。 Galaxy J使用armeabi-v7a,而S7使用arm64-v8a。
根据您上面的构建,cmake 正在为所有架构制作 .so 文件,这会导致问题,因为本机代码中存在 32 位与 64 位转换问题。
但是,您的情况有一个简单的修复方法。您可以在默认配置中将构建限制为 abiFilters "armeabi-v7a"、"armeabi",如下所示
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
abiFilters "armeabi-v7a", "armeabi"
}
}
这应该仍然有效,因为 arm64v8a 向后兼容旧的 v7a 架构。
我已经通过替换解决了我的问题:
typedef unsigned long int UINT4;
在 md5.c -> typedef uint32_t UINT4;
。
我在两台设备上再次测试,一切正常。在 64 位机器上,long int(通常)是 64 位长而不是 32