アプリケーション(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参照を検索し、それらをフックして毎回同じ値を返すようにします。
java.io.BufferedReaderを使用してA.javaの内容を文字列に取得し、次の手順に従います。
public byte[] getMD5(String fileAContents) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(fileAContents.getBytes());
return messageDigest.digest();
}
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;
}