Generate token for access server resources

試著忘記壹切 提交于 2020-01-03 03:16:10

问题


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.


回答1:


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



回答2:


The signing certificate's fingerprint will be unique across all the devices. Would you please try this solution to get that fingerprint as String and use it as token.

https://stackoverflow.com/a/22506133/4586742




回答3:


@Om Infowave Developers,

I Suggest you to use a Android Keystore System to generate a KeyPair then use KeyPair to encrypt a Token, Store a token in shared preference. whenever you need a token decrypt token using KeyPair.

  1. This way you get unique token every time.
  2. Token is encrypted and secured.
  3. KeyPair is different for every device hence more secure.

Also I just notice that you are returning zero-index based key. Their might be chances that key you are looking for present in subsequent indices. Suggest you to log all key stored in Signature[] sigs;

Hope this help.



来源:https://stackoverflow.com/questions/45371571/generate-token-for-access-server-resources

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!