通过jni获取应用签名

SignUtil.h

#ifndef BWL_SIGN_UTIL_H
#define BWL_SIGN_UTIL_H

#include <jni.h>

// 获取当前应用的签名
char *getSign(JNIEnv *env);

#endif //BWL_SIGN_UTIL_H

SignUtil.cpp

//
// Created by wenlongbai on 8/15/17.
//

#include <malloc.h>
#include <string.h>
#include "SignUtil.h"
#include "Util.h"

// http://blog.csdn.net/gaoshouxiaodi/article/details/37821659
jobject getApplication(JNIEnv *env) {
    jclass localClass = env->FindClass("android/app/ActivityThread");
    if (localClass != NULL) {
        jmethodID getapplication = env->GetStaticMethodID(localClass, "currentApplication",
                                                          "()Landroid/app/Application;");
        if (getapplication != NULL) {
            jobject application = env->CallStaticObjectMethod(localClass, getapplication);
            return application;
        }
        return NULL;
    }
    return NULL;
}

char *getDefaultSign() {
    int len = strlen(APP_SIGN_LAUNCHER);
    char *defaultSign = (char *) malloc(len + 1);
    strcpy(defaultSign, APP_SIGN_LAUNCHER);
    return defaultSign;
}

char *getSign(JNIEnv *env) {
    LOGI("getSign start");
    jobject context = getApplication(env);
    if (context == NULL) {
        LOGI("getSign: not found context, return default value");
        return getDefaultSign();
    }
    jclass activity = env->GetObjectClass(context);
    // 得到 getPackageManager 方法的 ID
    jmethodID methodID_func = env->GetMethodID(activity, "getPackageManager",
                                               "()Landroid/content/pm/PackageManager;");
    // 获得PackageManager对象
    jobject packageManager = env->CallObjectMethod(context, methodID_func);
    jclass packageManagerclass = env->GetObjectClass(packageManager);
    //得到 getPackageName 方法的 ID
    jmethodID methodID_pack = env->GetMethodID(activity, "getPackageName", "()Ljava/lang/String;");
    //获取包名
    jstring name_str = static_cast<jstring>(env->CallObjectMethod(context, methodID_pack));
    // 得到 getPackageInfo 方法的 ID
    jmethodID methodID_pm = env->GetMethodID(packageManagerclass, "getPackageInfo",
                                             "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
    // 获得应用包的信息
    jobject package_info = env->CallObjectMethod(packageManager, methodID_pm, name_str, 64);
    // 获得 PackageInfo 类
    jclass package_infoclass = env->GetObjectClass(package_info);
    // 获得签名数组属性的 ID
    jfieldID fieldID_signatures = env->GetFieldID(package_infoclass, "signatures",
                                                  "[Landroid/content/pm/Signature;");
    // 得到签名数组,待修改
    jobject signatur = env->GetObjectField(package_info, fieldID_signatures);
    jobjectArray signatures = reinterpret_cast<jobjectArray>(signatur);
    // 得到签名
    jobject signature = env->GetObjectArrayElement(signatures, 0);
    // 获得 Signature 类,待修改
    jclass signature_clazz = env->GetObjectClass(signature);
    // 获取toByteArray方法ID
    jmethodID signature_method_toByteArray = env->GetMethodID(signature_clazz, "toByteArray",
                                                              "()[B");
    jobject signatureBytes = env->CallObjectMethod(signature, signature_method_toByteArray);
    // 获取InputStream对象
    jclass inputStreamClass = env->FindClass("java/io/ByteArrayInputStream");
    jobject inputStreamObj = env->NewObject(
            inputStreamClass,
            env->GetMethodID(inputStreamClass, "<init>", "([B)V"),
            signatureBytes
    );
    // 获取CertificateFactory对象
    jclass certificateClass = env->FindClass("java/security/cert/CertificateFactory");
    jmethodID  certificateClass_getInstance = env->GetStaticMethodID(certificateClass, "getInstance", "(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;");
    jobject certificateFactoryObj = env->CallStaticObjectMethod(certificateClass,
                                                                certificateClass_getInstance, env->NewStringUTF("X509"));

    // 生成X509Certificate对象
    jmethodID certificateFactoryClass_method_generateCertificate = env->GetMethodID(
            certificateClass, "generateCertificate",
            "(Ljava/io/InputStream;)Ljava/security/cert/Certificate;");
    jobject x509CertificateObj = env->CallObjectMethod(certificateFactoryObj,
                                                       certificateFactoryClass_method_generateCertificate,
                                                       inputStreamObj);
    // 获取X509Certificate的c.getEncoded数据
    jmethodID X509Certificate_method_getEncoded = env->GetMethodID(
            env->FindClass("java/security/cert/Certificate"),
            "getEncoded", "()[B");
    jobject x509CertificateObj_encoded = env->CallObjectMethod(x509CertificateObj,
                                                               X509Certificate_method_getEncoded);
    // 生成MessageDigest
    jclass MessageDigestClass = env->FindClass("java/security/MessageDigest");
    jmethodID MessageDigestClass_getInstance = env->GetStaticMethodID(MessageDigestClass, "getInstance", "(Ljava/lang/String;)Ljava/security/MessageDigest;");
    jobject MessageDigestObj = env->CallStaticObjectMethod(MessageDigestClass, MessageDigestClass_getInstance, env->NewStringUTF("SHA1"));

    // 获取MessageDigestObj.digest
    jmethodID MessageDigestClass_method_digest = env->GetMethodID(MessageDigestClass, "digest",
                                                                  "([B)[B");
    jobject publicKey = env->CallObjectMethod(MessageDigestObj, MessageDigestClass_method_digest,
                                              x509CertificateObj_encoded);
    jbyteArray publicKeyArr = reinterpret_cast<jbyteArray>(publicKey);
    LOGI("getSign convert to 0x");
    // 对获取的key进程16进制转换
    int length = env->GetArrayLength(publicKeyArr);
    jbyte *bytes = env->GetByteArrayElements(publicKeyArr, 0);
    char *retValue = (char *) malloc(length * 3);
    int retValueIndex = 0;
    char tempHex[3];
    for (int i = 0; i < length; i++) {
        char2Hex(bytes[i], tempHex);
        retValue[retValueIndex++] = tempHex[0];
        retValue[retValueIndex++] = tempHex[1];
        if (i < length - 1) {
            retValue[retValueIndex++] = ':';
        } else {
            retValue[retValueIndex++] = 0;
        }
    }

    LOGI("getSign finish");

    return retValue;
}

Util.h

//
// Created by wenlongbai on 8/14/17.
//

#ifndef BWL_UTIL_H
#define BWL_UTIL_H

#ifdef __cplusplus
extern "C" {
#endif

#include "jni.h"
#include "Constants.h"
#include <android/log.h>

#define LOG_TAG "tvlive_pwd"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

#ifdef __DEBUG__
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#else
#define LOGD(...)
#endif

// jstring转为char*
char *jstring2cStr(JNIEnv *env, jstring jstr);

// char*转为jstring
jstring cStr2jstring(JNIEnv *env, const char *pat);

// long转为char
char *jlong2char(JNIEnv *env, jlong number);

// char转为16进制
char *char2Hex(unsigned char c, char* hexValue) ;

#ifdef __cplusplus
};
#endif

#endif //BWL_UTIL_H

Util.cpp

//
// Created by wenlongbai on 8/14/17.
//

#include <malloc.h>
#include <string.h>
#include "jni.h"
#include "Util.h"

#define HEX_VALUES "0123456789ABCDEF"

char *jstring2cStr(JNIEnv *env, jstring jstr) {
    const char *temp = (char *) env->GetStringUTFChars(jstr, NULL);
    char *ret = (char *) malloc(strlen(temp) + 1);
    strcpy(ret, temp);
    env->ReleaseStringUTFChars(jstr, temp);
    return ret;
}

jstring cStr2jstring(JNIEnv *env, const char *chars) {
    jstring ret = env->NewStringUTF(chars);
    return ret;
}

char *jlong2char(JNIEnv *env, jlong number) {
    char *chars = (char *) malloc(20);
    sprintf(chars, "%lld", number);
    return chars;
}


char *char2Hex(unsigned char c, char *hexValue) {
    if (c < 16) {
        hexValue[0] = HEX_VALUES[0];
        hexValue[1] = HEX_VALUES[c];
    } else {
        int l = c / 16;
        int r = c % 16;
        hexValue[0] = HEX_VALUES[l];
        hexValue[1] = HEX_VALUES[r];
    }
    hexValue[2] = 0;
    return hexValue;
}

 

posted on 2018-03-16 11:53  bwlcool  阅读(920)  评论(0编辑  收藏  举报

导航