Search code examples
androidweb-servicesauthenticationandroid-security

Generate token for access server resources


I am trying to generate token at run time using sign certificate and verify that token on server to access any resources. I don't want to store token in XML file because it is available after reverse engineering of APK

Code for generating token is

public String getToken() {
    Signature[] sigs;
    try {
        sigs = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES).signatures;

        String token = sigs[0].toCharsString();
        return token;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

Issue is some device return different token even apk is generated from the same certificate, don't know the reason why it is returning different token for some devices.

All i want is generate a token which could be used to access web resources, and i don't want to store token in apk no one can get the token by decompiling apk.


Solution

  • you can store token with C or C++ and add signature verification

    public static String getSignature(Context context) {
    try {
        PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
        Signature[] signatures = packageInfo.signatures;
        return signatures[0].toCharsString();
    } catch(PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    return null;
    

    }

    const char * app_signature = "singsing";
    static int is_valid = 0;
    void
    Java_com_xxx_xxx_nativeInit(JNIEnv *env, jobject thiz, jobject context_object){
        jclass context_class = (*env)->GetObjectClass(env, context_object);
    
        //context.getPackageManager()
        jmethodID methodId = (*env)->GetMethodID(env, context_class, "getPackageManager", "()Landroid/content/pm/PackageManager;");
        jobject package_manager_object = (*env)->CallObjectMethod(env, context_object, methodId);
        if (package_manager_object == NULL) {
            return;
        }
    
        //context.getPackageName()
        methodId = (*env)->GetMethodID(env, context_class, "getPackageName", "()Ljava/lang/String;");
        jstring package_name_string = (jstring)(*env)->CallObjectMethod(env, context_object, methodId);
        if (package_name_string == NULL) {
            return ;
        }
        (*env)->DeleteLocalRef(env,context_class);
    
        //PackageManager.getPackageInfo(Sting, int)
        //public static final int GET_SIGNATURES= 0x00000040;
        jclass pack_manager_class = (*env)->GetObjectClass(env, package_manager_object);
        methodId = (*env)->GetMethodID(env, pack_manager_class, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
        (*env)->DeleteLocalRef(env,pack_manager_class);
        jobject package_info_object = (*env)->CallObjectMethod(env, package_manager_object, methodId, package_name_string, 0x40);
        if (package_info_object == NULL) {
            return ;
        }
        (*env)->DeleteLocalRef(env,package_manager_object);
    
        //PackageInfo.signatures[0]
        jclass package_info_class = (*env)->GetObjectClass(env, package_info_object);
        jfieldID fieldId = (*env)->GetFieldID(env, package_info_class, "signatures", "[Landroid/content/pm/Signature;");
        (*env)->DeleteLocalRef(env,package_info_class);
        jobjectArray signature_object_array = (jobjectArray)(*env)->GetObjectField(env,package_info_object, fieldId);
        if (signature_object_array == NULL) {
            return ;
        }
        jobject signature_object = (*env)->GetObjectArrayElement(env,signature_object_array, 0);
        (*env)->DeleteLocalRef(env,package_info_object);
        jclass signature_class = (*env)->GetObjectClass(env, signature_object); 
        methodId = (*env)->GetMethodID(env, signature_class,  "toCharsString", "()Ljava/lang/String;");
        (*env)->DeleteLocalRef(env,signature_class);
        jstring signature_jstirng = (jstring) (*env)->CallObjectMethod(env, signature_object, methodId);
        const  char *sign=(*env)->GetStringUTFChars(env, signature_jstirng,NULL); 
        if (strcmp(sign,app_signature)==0 || strcmp(sign,app_j_s)==0) {
            is_valid= 1;
        } 
        return;
    }