Sinh Phan
Sinh Phan

Reputation: 1266

Returning wrong md5 hash in jni

I'm trying to generate MD5 hash for a string using the original/untouched md5.h and md5c.c (github source file: https://github.com/sinhpn92/encryption-in-C/tree/master/app/src/main/cpp). But my result is not right at anytime. When i use samsung galaxy j device for test, my result is right. But when i use samsung galaxy s7 device for test, my result is wrong. What's wrong in my code? Have any suggestion for resolve this problem? Thank your support.

This is my project: https://github.com/sinhpn92/encryption-in-C

I use cmake to config jni lib:

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} )

And this is native-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);
}

My 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'
}

This is result of my test:

enter image description here

enter image description here

Upvotes: 3

Views: 1743

Answers (2)

Sinh Phan
Sinh Phan

Reputation: 1266

I have resolved my problem by replace:

typedef unsigned long int UINT4; in md5.c -> typedef uint32_t UINT4;.

I tested again on two device and it's work fine. On a 64 bits machine long int are (usually) 64 bits long instead of 32

Upvotes: 5

Bharat Kumar Molleti
Bharat Kumar Molleti

Reputation: 141

the two phones use different ARM instruction sets. Galaxy J uses armeabi-v7a, while S7 uses arm64-v8a.

the cmake as per your above builds is making the .so file for all architectures and this causes the issue because of 32 bit vs 64 bit cast conversion issues in the native code.

however, there exists a simple fix in your case. you could restrict the build to abiFilters "armeabi-v7a", "armeabi", in your default config like below

    externalNativeBuild {
        cmake {
            cppFlags "-frtti -fexceptions"
            abiFilters "armeabi-v7a", "armeabi"
        }
    }

this should still work, because the arm64v8a is backward compatible with the older v7a architecture.

Upvotes: 0

Related Questions