我想计算我的应用程序(在我的 APK 中)中特定文件(活动)的 CRC 或 MD5,以便我可以比较另一个文件中的值并确保第一个文件没有被篡改。
我可以这样做吗?是这样,你能指导我吗?
例子:
假设我有文件 A.java 和 B.java。我想计算 A.java CRC32/MD5 并将此值存储在 B.java 中,以便在 B.java 执行时重新计算 A.java 并将其与已知值进行比较
你不能这样做。Android 上没有单独的类文件,你会得到一个包含所有类和库的单一 DEX 文件。你必须计算 classes.dex 文件的哈希并将其存储在资源文件中,因为将它放在类文件中将改变整体哈希值。但是,如果我反编译您的应用程序并更改您的 classes.dex,我也可以更改资源,因此这并不能真正提供任何真正的保护。当然,您可以尝试混淆或隐藏该值以使其更难,但某些工具会查找 CRC/MessageDigest 引用并简单地将它们挂钩以每次返回相同的值。
public static void calculate(Context context) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
ZipInputStream fis = get(context);
System.out.println("fis: " + fis);
byte[] dataBytes = new byte[1024];
int nread = 0;
while ((nread = fis.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
};
byte[] mdbytes = md.digest();
//convert the byte to hex format method 1
StringBuffer sb = new StringBuffer();
for (int i = 0; i < mdbytes.length; i++) {
sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
System.out.println("Digest(in hex format):: " + sb.toString());
//convert the byte to hex format method 2
StringBuffer hexString = new StringBuffer();
for (int i=0;i<mdbytes.length;i++) {
String hex=Integer.toHexString(0xff & mdbytes[i]);
if(hex.length()==1) hexString.append('0');
hexString.append(hex);
}
System.out.println("Digest(in hex format):: " + hexString.toString());
if(fis!=null){
fis.close();
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static ZipInputStream get(Context context){
// Get the path to the apk container.
String apkPath = context.getApplicationInfo().sourceDir;
JarFile containerJar = null;
try {
// Open the apk container as a jar..
containerJar = new JarFile(apkPath);
// Look for the "classes.dex" entry inside the container.
ZipEntry zzz = containerJar.getEntry("classes.dex");
// If this entry is present in the jar container
if (zzz != null) {
System.out.println("long " + zzz.getCrc());
// Get an Input Stream for the "classes.dex" entry
InputStream in = containerJar.getInputStream(zzz);
ZipInputStream zin = new ZipInputStream(in);
return zin;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (containerJar != null)
try {
containerJar.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
使用java.io.BufferedReader将 A.java 的内容转换为字符串,然后执行以下操作:
public byte[] getMD5(String fileAContents) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(fileAContents.getBytes());
return messageDigest.digest();
}