1、完整性校驗原理java
所謂完整性校驗就是咱們用各類算法來計算一個文件的完整性,防止這個文件被修改。其中經常使用的方法就是計算一個文件的CRC32的值或者計算一個文件的哈希值。咱們在防止apk被反編譯的方法中也能夠採用這種方法。咱們知道apk生成的classes.dex主要由java文件生成的,它是整個apk的邏輯實現。因此咱們能夠對classes.dex文件進行完整性校驗,來保證整個程序的邏輯不被修改。若是咱們想要保證整個apk文件的完整性,也能夠對整個apk文件進行完整性校驗。下面咱們分別來實現對classes.dex文件和apk文件的完整性校驗。 linux
2、用crc32對classes.dex文件的完整性進行校驗算法
(1)能夠打印出來咱們的apk生的classes.dex文件的crc32的值,代碼以下:服務器
?網絡
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
public
class
MainActivity extendsActivity {
@Override
protected
void
onCreate(BundlesavedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String apkPath = getPackageCodePath();
Long dexCrc = Long.parseLong(getString(R.string.classesdex_crc));
try
{
ZipFile zipfile =
new
ZipFile(apkPath);
ZipEntry dexentry = zipfile.getEntry(
"classes.dex"
);
Log.i(
"verification"
,
"classes.dexcrc="
+dexentry.getCrc());
if
(dexentry.getCrc() != dexCrc){
Log.i(
"verification"
,
"Dexhas been modified!"
);
}
else
{
Log.i(
"verification"
,
"Dex hasn't been modified!"
);
}
}
catch
(IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
|
注意:R.string.classesdex_crc的值如今能夠是個隨機數。 ide
(2)運行程序打印結果,個人apk程序的classes.dex的crc32的值爲713769644spa
(3)將上面程序的classes.dex文件的crc32的值,保存在資源文件字符串中classesdex_crc中(固然也能夠保存在服務器上,而後經過網絡獲取校驗),而後再運行上面的apk程序,打印以下:.net
Dex hasn't beenmodified! code
(4)這時咱們在上面的代碼中隨便加一行或者一個空格,而後從新編譯運行會看到咱們的程序的crc32的值改變了。程序打印以下:blog
Dex has beenmodified!
3、用哈希值對整個apk完整性進行校驗
因爲咱們要對整個apk的完整性進行校驗,因此咱們的算出哈希值就不能存在資源文件中了由於apk中任何的改動都會引發最終apk生成的哈希值的不一樣。
(1)首先實現apk中計算自身哈希值的代碼,以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
public
class
MainActivity extendsActivity {
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String apkPath = getPackageCodePath();
MessageDigest msgDigest =
null
;
try
{
msgDigest = MessageDigest.getInstance(
"SHA-1"
);
byte
[] bytes =
new
byte
[
1024
];
int
byteCount;
FileInputStream fis =
new
FileInputStream(
new
File(apkPath));
while
((byteCount = fis.read(bytes)) >
0
)
{
msgDigest.update(bytes,
0
, byteCount);
}
BigInteger bi =
new
BigInteger(
1
, msgDigest.digest());
String sha = bi.toString(
16
);
fis.close();
//這裏添加從服務器中獲取哈希值而後進行對比校驗
}
catch
(Exception e) {
e.printStackTrace();
}
}
}
|
(2)用linux下的sha1sum命令計算咱們的apk的哈希值,命令以下:
sha1sum verification.apk
(3)將(2)中生成的哈希值存到服務器上,而後在咱們的代碼中從服務器獲取進行完整性比較。
上面咱們用計算crc32和哈希值的方法分別對classes.dex文件和整個apk完整性進行了校驗,固然兩個校驗方法也能夠互換使用。根據上面的講述相信你們對校驗文件完整性的方法有了必定的瞭解,