通过jni获取应用签名

时间:2021-09-07 20:16:09

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