轉(zhuǎn)載請注明出處:http://www.reibang.com/p/286d2b372334
github:https://github.com/rushgit/zhongwenjun.github.com
csdn:https://blog.csdn.net/zwjemperor
前言
眾所周知后添,Android系統(tǒng)在安裝Apk的過程中,會對Apk進行簽名校驗,校驗通過后才能安裝成功。那你知道簽名校驗的機制是什么?具體校驗的是什么內(nèi)容嗎窘奏?申請第三方SDK(如微信支付)時填入的SAH1值是什么?目前眾多的快速批量打包方案又是如何繞過簽名檢驗的?
我將通過一系列的文章來解開這些疑惑:
這篇文章先來介紹Apk簽名相關(guān)的基本知識壮不。
- 簽名是什么?如何進行簽名皱碘?
- keystore和證書格式
- jarsigner和apksigner的區(qū)別
1. 簽名是什么询一?
要知道簽名是什么,先來看為什么需要簽名 癌椿。大家都知道健蕊,在消息通信時,必須至少解決兩個問題:一是確保消息來源的真實性踢俄,二是確保消息不會被第三方篡改缩功。在安裝Apk時,同樣需要確保Apk來源的真實性都办,以及Apk沒有被第三方篡改嫡锌。如何解決這兩個問題呢?方法就是開發(fā)者對Apk進行簽名:在Apk中寫入一個“指紋”琳钉。指紋寫入以后势木,Apk中有任何修改,都會導(dǎo)致這個指紋無效歌懒,Android系統(tǒng)在安裝Apk進行簽名校驗時就會不通過啦桌,從而保證了安全性。
要了解如何實現(xiàn)簽名及皂,需要了解兩個基本概念:數(shù)字摘要和數(shù)字證書甫男。
1.1 數(shù)字摘要
數(shù)字摘要是將任意長度的消息變成固定長度的短消息,它類似于一個自變量是消息的函數(shù)验烧,也就是Hash函數(shù)板驳。數(shù)字摘要就是采用單向Hash函數(shù)將需要加密的明文“摘要”成一串固定長度的密文,這一串密文又稱為數(shù)字指紋碍拆,它有固定的長度若治,而且不同的明文摘要成密文效扫,其結(jié)果總是不同的,而同樣的明文其摘要必定一致直砂。
簡單來說菌仁,就是對一個任意長度的數(shù)據(jù),通過一個Hash算法計算后静暂,都可以得到一個固定長度的二進制數(shù)據(jù)济丘,這個數(shù)據(jù)就稱為“摘要”。摘要具有下面的幾個特征:
-
唯一性
在不考慮碰撞的情況下洽蛀,不同的數(shù)據(jù)的計算出的摘要是不同的摹迷。
-
固定長度
不同的Hash算法計算的長度是不一樣的,但對同一個算法來說是一樣的郊供。比較常用的Hash算法有MD5和SHA1峡碉,MD5的長度是128拉,SHA1的長度是160位驮审。
-
不可逆性
即從正向計算的摘要不可能逆向推導(dǎo)出原始數(shù)據(jù)鲫寄。
1.2 簽名和校驗的大體過程
前面已經(jīng)說到,可以通過簽名來確保數(shù)據(jù)來源的可靠性和數(shù)據(jù)的不可篡改性疯淫。簽名就是在摘要的基礎(chǔ)上再進行一次加密地来,對摘要加密后的數(shù)據(jù)就可以當(dāng)作數(shù)字簽名,在安裝Apk需要對簽名進行驗證熙掺,驗證通過才能繼續(xù)安裝未斑。
這里有兩個過程:簽名過程 和 校驗過程。
先來說簽名過程:
-
計算摘要
通過Hash算法提取出原始數(shù)據(jù)的摘要币绩;
-
計算簽名
再通過基于密鑰(私鑰)的非對稱加密算法對提取出的摘要進行加密蜡秽,加密后的數(shù)據(jù)就是簽名信息;
-
寫入簽名
將簽名信息寫入原始數(shù)據(jù)的簽名區(qū)塊內(nèi)缆镣。
再來看校驗過程:
-
計算摘要
接收方接收到數(shù)據(jù)后芽突,首先用同樣的Hash算法從接收到的數(shù)據(jù)中提取出摘要;
-
解密簽名
使用發(fā)送方的公鑰對數(shù)字簽名進行解密费就,解密出原始摘要诉瓦;
-
比較摘要
如果解密后的數(shù)據(jù)和提取的摘要一致,則校驗通過力细;如果數(shù)據(jù)被第三方篡改過,解密后的數(shù)據(jù)和摘要不一致固额,校驗不通過眠蚂。
1.3 數(shù)字證書
這里有一個前提:接收方必須要知道發(fā)送方的公鑰和所使用的算法。如果數(shù)字簽名和公鑰一起被篡改斗躏,接收方無法得知逝慧,還是會校驗通過。如何保證公鑰的可靠性呢?答案是數(shù)字證書笛臣,數(shù)字證書是身份認(rèn)證機構(gòu)(Certificate Authority)頒發(fā)的云稚,包含了以下信息:
- 證書頒發(fā)機構(gòu)
- 證書頒發(fā)機構(gòu)簽名
- 證書綁定的服務(wù)器域名
- 證書版本、有效期
- 簽名使用的加密算法(非對稱算法沈堡,如RSA)
- 公鑰 等
接收方收到消息后静陈,先向CA驗證證書的合法性(根據(jù)證書的簽名、綁定的域名等信息诞丽。CA機構(gòu)是權(quán)威的鲸拥,可以保證這個過程的可靠性。)再進行簽名校驗僧免。
關(guān)于通過數(shù)字證書進行簽名校驗的詳細(xì)過程刑赶,可以參考我之前寫的一篇關(guān)于HTTPS通信機制的介紹:詳談HTTPS通信機制,HTTPS是如何進行安全通信的?
需要注意的是懂衩,Apk的證書通常的自簽名的撞叨,也就是由開發(fā)者自己制作,沒有向CA機構(gòu)申請浊洞。Android在安裝Apk時并沒有校驗證書本身的合法性谒所,只是從證書中提取公鑰和加密算法,這也正是對第三方Apk重新簽名后沛申,還能夠繼續(xù)在沒有安裝這個Apk的系統(tǒng)中繼續(xù)安裝的原因劣领。
1.4 簽名和校驗過程
完整的簽名和校驗過程如下:(圖片來源:維基百科)
2. keystore和證書格式
我們在對Apk簽名時并沒有直接指定私鑰、公鑰和數(shù)字證書铁材,而是使用keystore文件,這些信息都包含在了keystore文件中著觉。根據(jù)編碼不同村生,keystore文件分為很多種,Android使用的是Java標(biāo)準(zhǔn)keystore格式JKS(Java Key Storage)饼丘,所以通過Android Studio導(dǎo)出的keystore文件是以.jks結(jié)尾的趁桃。
keystore使用的證書標(biāo)準(zhǔn)是X.509,X.509標(biāo)準(zhǔn)也有多種編碼格式肄鸽,常用的有兩種:pem(Privacy Enhanced Mail)和der(Distinguished Encoding Rules)卫病。jks使用的是der格式,Android也支持直接使用pem格式的證書進行簽名典徘,我們下面會介紹蟀苛。
兩種證書編碼格式的區(qū)別:
-
DER(Distinguished Encoding Rules)
二進制格式,所有類型的證書和私鑰都可以存儲為der格式逮诲。
-
PEM(Privacy Enhanced Mail)
base64編碼帜平,內(nèi)容以-----BEGIN xxx----- 開頭幽告,以-----END xxx----- 結(jié)尾,比如:
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAlmXFRXEZomRKhNRp2XRoXH+2hm17RfrfecQlT49fktoDLkF6r99uiNnuUdPi6UQuXOnzEbe1nZkfuqfB10aBLrDqBUSZ+3
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIICvTCCAaWgAwIBAgIEcWTElDANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRyPQDLnVKeEIh81OwD3KIrQOUwsxyptOVVea1D8CzIAnGs
-----END CERTIFICATE-----
X.509證書格式:
3. jarsigner和apksigner的區(qū)別
Android提供了兩種對Apk的簽名方式裆甩,一種是基于JAR的簽名方式冗锁,另一種是基于Apk的簽名方式,它們的主要區(qū)別在于使用的簽名文件不一樣:jarsigner使用keystore文件進行簽名嗤栓;apksigner除了支持使用keystore文件進行簽名外冻河,還支持直接指定pem證書文件和私鑰進行簽名。
android {
signingConfigs {
config {
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
}
}
...
}
不知道大家有沒有注意一個問題抛腕,我們通過keytool或者AS生成一個keystore的時候(簽署您的應(yīng)用)芋绸,除了要輸入keystore的密碼外,還要輸入一個alias和key的密碼担敌。在簽名時摔敛,除了要指定keystore文件和密碼外,也要指定alias和key的密碼全封,這是為什么呢马昙?
原因是keystore是一個密鑰庫,也就是說它可以存儲多對密鑰和證書刹悴,keystore的密碼是用于保護keystore本身的行楞,一對密鑰和證書是通過alias來區(qū)分的。從這里可以看出jarsigner是支持使用多個證書對Apk進行簽名的土匀。apksigner也同樣支持子房,關(guān)于apksigner的使用介紹可以參考官方文檔apksigner。
3.1 簽名相關(guān)命令
● jarsigner簽名
jarsigner -keystore keystore_file -signedjar signed.apk unsigned.apk alias_name -storepass pwd
● apksigner簽名
java -jar signapk.jar cert.x509.pem private.pk8 unsigned.apk signed.apk
● 查看keystore文件
keytool -list -v -keystore keystore_file -storepass pwd
● 查看apk證書
keytool -printcert -jarfile apk
● 查看DER格式證書(META-INFO/CERT.RSA)
openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text
● 查看PEM格式證書
openssl x509 -in cert.x509.pem -text -noout
● apksigner檢查apk是否簽名就轧,以及查看證書SHA1值
apksigner verify -v --print-certs
ok证杭,簽名的基本概念和校驗過程就介紹到這里,關(guān)于JAR簽名和V2簽名機制的詳細(xì)介紹妒御,參考下面兩篇文章: