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