編輯:關於Android編程
1.文件完整性效驗
這裡字符串取MD5就不做贅述了.既然要效驗文件的完整性,那麼就牽扯到取文件MD5摘要,這裡是用JDK中的MessageDigest通過讀取文件的二進制流,使用update累計更新文件流的MD5摘要來獲取整個文件的MD5摘要.拿到文件MD5之後跟接口下發的對比就OK了.所以單純做文件完整性效驗還是很簡單的.
/**
* get file md5
* @param file
* @return
* @throws NoSuchAlgorithmException
* @throws IOException
*/
private static String getFileMD5(File file) throws NoSuchAlgorithmException, IOException {
if (!file.isFile()) {
return null;
}
MessageDigest digest;
FileInputStream in;
byte buffer[] = new byte[1024];
int len;
digest = MessageDigest.getInstance(MD5);
in = new FileInputStream(file);
while ((len = in.read(buffer, 0, 1024)) != -1) {
digest.update(buffer, 0, len);
}
in.close();
BigInteger bigInt = new BigInteger(1, digest.digest());
return bigInt.toString(16);
}
2.文件合法性效驗
文件合法性的效驗相比完整性效驗就要復雜不少,這裡合法性是根據簽名來做的,所以起碼要簡單了解簽名的過程,簽名之後文件發生了什麼變化和怎麼獲取文件的簽名信息等.
1)簽名後產出
生成簽名文件和簽名的過程這裡就不細說了,主要分析一下簽名之後的一些情況.解壓簽名之後的文件可以看到經過簽名生成出來了一個META-INF文件夾,裡面一般都是三個文件用來存放所有文件的效驗以及簽名信息.

MANIFEST.MF:可以明文查看,對所有文件取BASE64哈希值.

ANDROIDK.SF:可以明文查看,對所有文件的前三行取BASE64哈希值.

ANDROIDK.RSA:前面兩個文件都只是對文件做了一個哈希摘要,並沒有簽名公鑰等信息,RSA文件裡面就包含了我們所需要的信息,其中包含有開發者信息,開發者公鑰以及CA根據前兩個文件的摘要信息經過私鑰加密後的密文.RSA文件是不能查看明文的,這裡可以使用openssl的命令來輸出該文件的信息.openssl pkcs7 -inform DER -in ANDROIDK.RSA -noout -print_certs -text, 從這個文件的數據結構來看本章需要用到的其實就是公鑰,獲取文件自身證書信息的公鑰,然後對比app自身的簽名公鑰就可以判斷文件的合法性.

2)獲取app自身簽名
通過上面的介紹可以了解到簽過名的文件都可以獲取到一個基於RSA算法的RSA public key,這裡就通過效驗這個公鑰的方式來驗證合法性,app自身的簽名信息可以通過PackageInfo獲取,獲取到之後經過字符串轉換和截取,將RSA public key部分摘取出來就OK了.
/**
* get local app rsa public key
* @param ctx
* @return
* @throws IOException
* @throws PackageManager.NameNotFoundException
* @throws CertificateException
*/
private static String getLocalSignature(Context ctx) throws IOException,
PackageManager.NameNotFoundException, CertificateException {
String signCode = null;
//get signature info depends on package name
PackageInfo packageInfo = ctx.getPackageManager().getPackageInfo(
ctx.getPackageName(), PackageManager.GET_SIGNATURES);
Signature[] signs = packageInfo.signatures;
Signature sign = signs[0];
CertificateFactory certFactory = CertificateFactory
.getInstance(X.509);
X509Certificate cert = (X509Certificate) certFactory
.generateCertificate(new ByteArrayInputStream(sign.toByteArray()));
String pubKey = cert.getPublicKey().toString();
String ss = subPublicSignature(pubKey);
ss = ss.replace(,, );
ss = ss.toLowerCase();
int aa = ss.indexOf(modulus);
int bb = ss.indexOf(publicexponent);
signCode = ss.substring(aa + 8, bb);
return signCode;
}
3)獲取外部文件簽名
/**
* Package archive parsing
*
* {@hide}
*/
public class PackageParser {
//source/frameworks/base/core/java/android/content/pm
}
在當前的使用場景下不推薦使用反射,一是使用反射降低效率還有風險,二是效驗這部分並沒有依賴Android其他部分,只是依賴了JDK中的JarFile.所以扣源碼自己實現來得比較實在,這裡就不分析使用反射驗證的過程了,直接上源碼.
從PackageParser類中的collectCertificates方法中可以看到如下代碼片段.首先根據文件路徑將簽名後的apk,jar或zip文件裝載到JarFile中(JarFile是繼承自ZipFile),然後獲取文件內容部的某個文件(這部分代碼塊是獲取的manifest文件),再獲取到該文件的證書信息.只要能拿到證書信息,那麼拿到公鑰什麼的都是小case了.
public boolean collectCertificates(Package pkg, int flags) {
//.................
JarFile jarFile = new JarFile(mArchiveSourcePath);
//.................
JarEntry jarEntry = jarFile.getJarEntry(ANDROID_MANIFEST_FILENAME);
//.................
certs = loadCertificates(jarFile, jarEntry, readBuffer);
pkg.mSignatures = null;
//.................
}
這個loadCertificates方法需要特別說一下,因為一開始我是看完源碼之後自己寫實現的,看這個方法的時候每注意注釋,就把讀文件流什麼也沒干的步驟略過了,直接通過JarEntry.getCertificates獲取證書.結果換了好幾個簽過名的文件都獲取不到證書,重新看了下源碼才發現注釋中的必須使用JarEntry讀文件流才能接收到證書信息......不作死就不會死.拿到證書之後就跟之前2)中的步驟一樣了,直接get公鑰,然後截取字符串將RSA public key截出來,最後跟2)中的結果比對就可以做合法性效驗了.
private static Certificate[] loadCertificates(JarFile jarFile, JarEntry je,
byte[] readBuffer) throws IOException {
// We must read the stream for the JarEntry to retrieve
// its certificates.
InputStream is = new BufferedInputStream(jarFile.getInputStream(je));
while (is.read(readBuffer, 0, readBuffer.length) != -1) {
// not using
}
is.close();
return je != null ? je.getCertificates() : null;
}
服務Service的基本用法
作為 Android四大組件之一, 服務也少不了有很多非常重要的知識點,那自然要從最基本的用法開始學習了。定義一個服務:public class MyService ex
仿制慕課網app實現斗魚,全民k歌視頻引導頁(ViewVideoViewPaper)炫酷效果
在幾個月前,我第一次玩全民k歌,下載完app,它彈出來的引導頁吸引了我,不像以前的引導頁一樣千篇一律,而是用了視頻的方式,用一種動態的方式來實現。在今天,我突然又想起了這
Android Matrix手勢縮放自定義view 不止於Imageview
之前寫過一篇文章Android TextView 橫豎排切換(字方向不變) 是自定義了一個LinearLayout, 實現了當然還不夠, 還要對它進行操作, 平移,旋轉
Android自定義View仿QQ健康界面
最近一直在學習自定義View相關的知識,今天給大家帶來的是QQ健康界面的實現。先看效果圖: 可以設置數字顏色,字體顏色,運動步數,運動排名,運動平均步數,虛線下方的藍色指