android通过jni获得包名签名信息的MD5、SHA1信息
- 获取包名
在Java代码中,可以通过以下方式获取当前应用的包名:
String packageName = getPackageName();
在JNI代码中,可以使用JNIEnv的GetObjectClass方法获取当前类的类对象,再使用GetMethodID方法获取包名方法的方法ID,最后调用CallObjectMethod方法获取包名字符串对象。具体代码如下:
jstring getPackageName(JNIEnv *env, jobject thiz) {
jclass clazz = env->GetObjectClass(thiz);
jmethodID methodID = env->GetMethodID(clazz, "getPackageName", "()Ljava/lang/String;");
return (jstring) env->CallObjectMethod(thiz, methodID);
}
- 获取应用签名的MD5信息
在Java代码中,可以通过以下方式获取当前应用签名的MD5信息:
String md5 = getSignature("MD5");
其中getSignature方法的实现如下:
private String getSignature(String algorithm) {
try {
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
byte[] signature = packageInfo.signatures[0].toByteArray();
MessageDigest md = MessageDigest.getInstance(algorithm);
byte[] digest = md.digest(signature);
return bytesToHexString(digest);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private String bytesToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xFF & b);
if (hex.length() == 1) {
sb.append('0');
}
sb.append(hex);
}
return sb.toString();
}
在JNI代码中,可以使用JNIEnv的GetObjectClass方法获取当前类的类对象,再使用GetMethodID方法获取应用签名方法的方法ID,最后调用CallObjectMethod方法获取签名字符串对象。具体代码如下:
jstring getSignature(JNIEnv *env, jobject thiz, jstring algorithm) {
jclass contextClass = env->GetObjectClass(thiz);
jclass packageManagerClass = env->FindClass("android/content/pm/PackageManager");
jfieldID packageManagerFieldID = env->GetStaticFieldID(contextClass, "GET_SIGNATURES", "I");
jint getSignatures = env->GetStaticIntField(contextClass, packageManagerFieldID);
jmethodID getPackageManagerMethodID = env->GetMethodID(contextClass, "getPackageManager", "()Landroid/content/pm/PackageManager;");
jobject packageManager = env->CallObjectMethod(thiz, getPackageManagerMethodID);
jmethodID getPackageInfoMethodID = env->GetMethodID(packageManagerClass, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
jstring packageName = getPackageName(env, thiz);
jobject packageInfo = env->CallObjectMethod(packageManager, getPackageInfoMethodID, packageName, getSignatures);
jclass signatureClass = env->FindClass("android/content/pm/Signature");
jfieldID signaturesFieldID = env->GetFieldID(packageInfoClass, "signatures", "[Landroid/content/pm/Signature;");
jobjectArray signatures = (jobjectArray) env->GetObjectField(packageInfo, signaturesFieldID);
jobject signature = env->GetObjectArrayElement(signatures, 0);
jmethodID toByteArrayMethodID = env->GetMethodID(signatureClass, "toByteArray", "()[B");
jbyteArray signatureBytes = (jbyteArray) env->CallObjectMethod(signature, toByteArrayMethodID);
jstring result = hash(env, signatureBytes, algorithm);
env->DeleteLocalRef(packageName);
env->DeleteLocalRef(packageInfo);
env->DeleteLocalRef(signatures);
env->DeleteLocalRef(signature);
env->DeleteLocalRef(signatureBytes);
return result;
}
其中,hash方法是计算MD5或SHA1值的通用方法,实现代码如下:
jstring hash(JNIEnv *env, jbyteArray data, jstring algorithm) {
jsize size = env->GetArrayLength(data);
jbyte *bytes = env->GetByteArrayElements(data, nullptr);
const char *algorithmChars = env->GetStringUTFChars(algorithm, nullptr);
const EVP_MD *md = EVP_get_digestbyname(algorithmChars);
unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int digestLength;
EVP_MD_CTX *mdCtx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdCtx, md, nullptr);
EVP_DigestUpdate(mdCtx, bytes, size);
EVP_DigestFinal_ex(mdCtx, digest, &digestLength);
EVP_MD_CTX_free(mdCtx);
env->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
env->ReleaseStringUTFChars(algorithm, algorithmChars);
return bytesToHexString(env, digest, digestLength);
}
jstring bytesToHexString(JNIEnv *env, const unsigned char *bytes, int length) {
char hex[length * 2 + 1];
for (int i = 0; i < length; i++) {
sprintf(&hex[i * 2], "%02x", bytes[i]);
}
hex[length * 2] = '\0';
return env->NewStringUTF(hex);
}
- 获取应用签名的SHA1信息
在Java代码中,可以通过以下方式获取当前应用签名的SHA1信息:
String sha1 = getSignature("SHA1");
在JNI代码中,可以使用hash方法计算SHA1值,具体代码同上,只需将getSignature方法中的algorithm参数改为"SHA1"即可
原文地址: https://www.cveoy.top/t/topic/cHyh 著作权归作者所有。请勿转载和采集!