apk簽名原理

經(jīng)常使用的總結(jié):

debug 簽名:
development/tools/make_key media '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=debug/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key networkstack '/C=CN/ST=BeiJing/L=ChaoYang/O=/OU=xxx/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key platform '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=debug/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key shared '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=debug/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key testkey '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=debug/CN=xxx/emailAddress=cm@xxx.com'

user簽名:
development/tools/make_key media '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=user/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key networkstack '/C=CN/ST=BeiJing/L=ChaoYang/O=user/OU=Pwe/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key platform '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=user/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key shared '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=user/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key testkey '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=user/CN=xxx/emailAddress=cm@xxx.com'

ota:
../development/tools/make_key releasekey '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=xxx/CN=xxx/emailAddress=cm@xxxx.com'

查看生成的格式文件:
keytool -printcert -file platform.x509.pem

使用signapk.jar 進(jìn)行簽名:android10:
java -Djava.library.path="out/host/linux-x86/lib64" -jar out/host/linux-x86/framework/signapk.jar build/target/product/security/platform.x509.pem build/target/product/security/platform.pk8 old.apk  new.apk

android 11:
./soong/host/linux-x86/framework/signapk.jar

如何產(chǎn)生jsk (keystore)文件, 只做了debug 模式發(fā)的
./keytool-importkeypair -k test.jks -p android -pk8 platform.pk8 -cert platform.x509.pem -alias test

如何查看test.jks 是否正確:
keytool -list -v -keystore test.jks
 
Android studio 如何使用:
signingConfigs {
    releaseConfig {
        keyAlias 'test'
        keyPassword 'android '
        storeFile file('/home/xxx/tools/keystore/test.jks')
        storePassword 'android '
    }
}



AndroidManifest.xml的manifest節(jié)點(diǎn)中添加
android:sharedUserId=”android.uid.system”,
Android.mk中增加  LOCAL_CERTIFICATE := platform 

APK中的META-INF/CERT.RSA
簽名之后如何對(duì)RSA 進(jìn)行查看,簽名的信息,在android root目錄 
openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text

本文主要講解簽名的原因,簽名怎么保證數(shù)據(jù)的正確,主要知識(shí)點(diǎn)

  • 數(shù)據(jù)摘要(數(shù)據(jù)指紋,消息摘要)
  • 簽名文件和證書
  • 簽名Apk包與沒有簽名的APK 差異在哪里
  • 如何對(duì)apk 進(jìn)行簽名

1-數(shù)據(jù)摘要

就是對(duì)一個(gè)數(shù)據(jù)源進(jìn)行一個(gè)算法之后得到一個(gè)摘要,也叫作數(shù)據(jù)指紋,不同的數(shù)據(jù)源,數(shù)據(jù)指紋肯定不一樣,就和人一樣

消息摘要算法(Message Digest Algorithm)是一種能產(chǎn)生特殊輸出格式的算法,其原理是根據(jù)一定的運(yùn)算規(guī)則對(duì)原始數(shù)據(jù)進(jìn)行某種形式的信息提取,被提取出的信息就被稱作原始數(shù)據(jù)的消息摘要。
著名的摘要算法有RSA公司的MD5算法和SHA-1算法及其大量的變體。

  • 無論輸入的消息有多長(zhǎng),計(jì)算出來的消息摘要的長(zhǎng)度總是固定的。
  • 原始數(shù)據(jù)不同,消息摘要不相同
  • 具有不可逆性

2-簽名文件和證書

消息的發(fā)送者來說,先要生成一對(duì)公私鑰對(duì),將公鑰給消息的接收者

  • 提取原始消息提取消息摘要;
  • 私鑰加密消息摘要;
    上面就是所原始信息的數(shù)字簽名?!?code>數(shù)字簽名=私鑰對(duì)[原始數(shù)據(jù)摘要]】

消息的接受者來說,收到了:原始的消息內(nèi)容+附加數(shù)字簽名.
接收者收到內(nèi)容:原始的消息內(nèi)容+私鑰對(duì)[原始數(shù)據(jù)摘要]

驗(yàn)證正確需要數(shù)據(jù)摘要算法+公鑰,公鑰假設(shè)是正確的。
如何驗(yàn)證:數(shù)據(jù)摘要算法對(duì)內(nèi)容提取摘要 對(duì)比公鑰解密簽名

圖示驗(yàn)證過程:

3-如何保證公鑰是正確的

數(shù)字證書,一般包含以下一些內(nèi)容:

  • 證書的發(fā)布機(jī)構(gòu)(Issuer)
  • 證書的有效期(Validity)
  • 消息發(fā)送方的公鑰
  • 證書所有者(Subject)
  • 數(shù)字簽名所使用的算法
  • 數(shù)字簽名 --》 數(shù)字證書也使用到了數(shù)字簽名,只不過簽名的內(nèi)容是證書
    公鑰簽發(fā)流程
    上面核心內(nèi)容就是申請(qǐng)者 提出申請(qǐng)公鑰, 公信力機(jī)構(gòu) 使用自己的私鑰對(duì)申請(qǐng)者的公鑰數(shù)字簽名, 公信力機(jī)構(gòu)的公鑰是大家都知道的,因此成功后,申請(qǐng)者的client 端就可以通過公信力機(jī)構(gòu) 獲取, 以驗(yàn)證公鑰的正確性。
    上面的內(nèi)容是我在理解HTTPS ,一直想不通的地方,現(xiàn)在終于想通了簽發(fā)機(jī)構(gòu)是如何發(fā)送公鑰的。
    其實(shí)app 的數(shù)字簽名與上面的CA 機(jī)構(gòu)的簽名還是有點(diǎn)區(qū)別的。

APP 是如何保證簽名流程的:
apk簽名其實(shí)是對(duì)所有源文件單獨(dú)計(jì)算摘要, 然后用私鑰加密摘要信息再得到一個(gè)加密串, 我們稱之為
APK的簽名. 你對(duì)源文件的修改都會(huì)導(dǎo)致簽名的變化. 這個(gè)是為了驗(yàn)證apk沒有被篡改.

app的升級(jí)和重新安裝, 檢測(cè)的并不是這個(gè)apk簽名, 而是你的包名+私鑰的摘要信息, 簽名的keystore文件沒有變, 私鑰的摘要信息也就不會(huì)變了.

google APP store, 當(dāng)開發(fā)者第一步開發(fā)的時(shí)候,就需要有自己的簽名,私鑰的摘要信息上傳到goole APP store, 如果升級(jí)的時(shí)候, 私鑰的摘要不一致肯定不能升級(jí)app 的上傳,這里應(yīng)該做了校驗(yàn)的。

4-簽名Apk包與沒有簽名的APK 差異在哪里

源碼位置:com/android/signapk/sign.java
Android簽名apk之后,會(huì)有一個(gè)META-INF文件夾,這里有三個(gè)文件:

  • MANIFEST.MF
  • CERT.RSA
  • CERT.SF

MANIFEST.MF是:
逐一遍歷里面的所有條目,如果是目錄就跳過,如果是一個(gè)文件,就用SHA1(或者SHA256)消息摘要算法提取出該文件的摘要然后進(jìn)行BASE64編碼后,作為“SHA1-Digest”屬性的值寫入到MANIFEST.MF文件中的一個(gè)塊中。該塊有一個(gè)“Name”屬性,其值就是該文件在apk包中的路徑。

CERT.SF:
逐條計(jì)算MANIFEST.MF文件中每一個(gè)塊的SHA1,并經(jīng)過BASE64編碼后,記錄在CERT.SF中的同名塊中,屬性的名字是“SHA1-Digest

CERT.RSA:
把之前生成的 CERT.SF文件, 用私鑰計(jì)算出簽名, 然后將簽名以及包含公鑰信息的數(shù)字證書一同寫入 CERT.RSA 中保存,還有私鑰的摘要信息

5-如何對(duì)apk 進(jìn)行簽名

5.1生成簽名文件

development/tools/make_key testkey  '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'

development/tools/make_key platform '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'

如何查看生成的platform.X509.pem:
build/target/product/security/platform.x509.pem
keytool -printcert -file platform.x509.pem
或者
openssl x509 -inform PEM -subject_hash_old -in platform.x509.pem -text

單獨(dú)給APP簽名方法:
java -Djava.library.path="out/host/linux-x86/lib64" -jar out/host/linux-x86/framework/signapk.jar build/target/product/security/platform.x509.pem build/target/product/security/platform.pk8 old.apk new.apk

APP簽名之后,如何查看CERT.RSA 信息
openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text

6-Android OTA releasekey 替換

6.1生成key
系統(tǒng)默認(rèn)的key如下,首先需要產(chǎn)生以下4種我們項(xiàng)目自己的OTA簽名key文件,每一種類型的key都是成對(duì)生成的,.509.pem后綴名的是公鑰,.pk8后綴名的是私鑰。
testkey -- a generic key for packages that do not otherwise specify a key.
platform -- a test key for packages that are part of the core platform.
shared -- a test key for things that are shared in the home/contacts process.
media -- a test key for packages that are part of the media/download system.

將XXX替換為自己公司信息。
生成文件如下:
media.pk8 media.x509.pem platform.pk8 platform.x509.pem
releasekey.pk8 releasekey.x509.pem shared.pk8 shared.x509.pem

將生成的key 文件放到項(xiàng)目相關(guān)的目錄下,針對(duì)Amlogic項(xiàng)目放到device/amlogic/p341/sign_keys。這樣我們公司的key就生成了。

6.2.更改編譯規(guī)則,使編譯過程中使用我們新生成的key對(duì)OTA進(jìn)行簽名
首先在build/core/Makefile里搜索testkey, 查看testkey是怎么用到編譯系統(tǒng)的,看到如下編譯選項(xiàng):

 ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/testkey)
 BUILD_KEYS := test-keys
 else
 BUILD_KEYS := dev-keys
 endif

繼續(xù)查看DEFAULT_SYSTEM_DEV_CERTIFICATE,可以看到在build/core/config.mk文件里有如下:

 # The default key if not set as LOCAL_CERTIFICATE
 ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE
   DEFAULT_SYSTEM_DEV_CERTIFICATE := $(PRODUCT_DEFAULT_DEV_CERTIFICATE)
 else
   DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/testkey
 endif

因此要想使用releasekey,只需要指定PRODUCT_DEFAULT_DEV_CERTIFICATE的值即可,因此在device/amlogic/p341/p341.mk中指定項(xiàng)目特定變量
PRODUCT_DEFAULT_DEV_CERTIFICATE := device/amlogic/p341/sign_keys/releasekey
同時(shí)在根據(jù)規(guī)則,在build/core/Makefile改動(dòng)如下:

 ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),device/amlogic/p341/sign_keys/releasekey)
 BUILD_KEYS := release-keys
 endif

6.3. Androoid.mk 使用platform 簽名
對(duì)于apk的簽名,系統(tǒng)會(huì)根據(jù)apk里指定的key進(jìn)行簽名。如果系統(tǒng)中的apk的android.mk中沒有設(shè)置LOCAL_CERTIFICATE的值,就默認(rèn)使用testkey。

 ifeq ($(LOCAL_CERTIFICATE),)
     LOCAL_CERTIFICATE := $(DEFAULT_SYSTEM_DEV_CERTIFICATE)
 endif
 private_key := $(LOCAL_CERTIFICATE).pk8
 certificate := $(LOCAL_CERTIFICATE).x509.pem

而如果設(shè)置成:
LOCAL_CERTIFICATE := platform
就代表使用platform來簽名,這樣的話這個(gè)apk就擁有了和system相同的簽名
如何產(chǎn)生jks文件,提供給android studio 開發(fā)使用,進(jìn)行系統(tǒng)簽名
jks文件:
第一種方式
https://github.com/chear/keytool-importkeypair
./keytool-importkeypair -k test.jks -p android -pk8 platform.pk8 -cert platform.x509.pem -alias test
最終會(huì)生成 test.jks
-k test.jks: test表示最終生成的jks的名字,可以自定義
android : 輸入當(dāng)前jks的密碼,可以自定義。
alias test: test表示別名,可以自定義,建議和上面的jks一致。

第二種方式: 該方式作為記錄,實(shí)際與第一種方式是想通的,可以看keytool-importkeypair 腳本

1、編譯android源碼。
2、cd build/target/product/security/ 
3、執(zhí)行
openssl pkcs8 -inform DER -nocrypt -in platform.pk8 -out platform.pem
生成platform.pem文件

4、
openssl pkcs12 -export -in platform.x509.pem -out platform.p12 -inkey platform.pem -password pass:123456 -name test
生成platform.p12文件,其中 "test" 為alias名(app添加簽名要用到),"123456" 為密碼。

5、執(zhí)行 
keytool -importkeystore -deststorepass test -destkeystore platform.jks -srckeystore platform.p12 -srcstoretype PKCS12 -srcstorepass test
 
生成platform.jks (app打簽名最終用到的文件),
-deststorepass "123456" 設(shè)置的是這個(gè)簽名的密碼,
-src*     的其他參數(shù)都是從前面兩個(gè)指令中生成的。
 
6、生成platform.jks
keytool -importkeystore -srckeystore platform.jks -destkeystore platform.jks -deststoretype pkcs12

說明:platform.jks 實(shí)際是含有了公鑰與私鑰, 這個(gè)是不能release給第三方的,只能給自己公司研發(fā)使用

思考:

  • 一個(gè)數(shù)據(jù)內(nèi)容使用一個(gè)簽名就可以,一個(gè)app 使用一個(gè)簽名就可以,如果重復(fù)簽名會(huì)怎么樣?
    重復(fù)使用signapk 簽名會(huì)覆蓋,上次的簽名失效,【沒有使用studio 多次簽名試過,看到有別名的可以有多個(gè)】


  • 普通簽名與系統(tǒng)簽名的區(qū)別?
    簽名是保證數(shù)據(jù)不被改寫
    系統(tǒng)簽名就是要獲取一些系統(tǒng)權(quán)限,修改時(shí)間權(quán)限等等
    普通簽名僅僅保證數(shù)據(jù)正確,單存的app 開發(fā),上傳到APP store ,不需要獲取修改系統(tǒng)的權(quán)限。

  • app升級(jí)過程中,如何保證升級(jí)APP 數(shù)據(jù)是正確的?
    數(shù)字簽名 與公鑰聯(lián)合,配合私鑰的數(shù)據(jù)摘要,android 升級(jí)過程進(jìn)行了對(duì)比,如果在第一次安裝設(shè)備時(shí)候就修改了數(shù)字簽名,那么再次安裝正確的app 不會(huì)成功。 因此老老實(shí)實(shí)從Apple store 下載,這樣保證app 正確,沒有打廣告等

  • https協(xié)議中的公鑰,私鑰處理方式,ssl 中公鑰如何傳遞給使用者?
    通過CA 公信力結(jié)構(gòu),公鑰分發(fā)給使用者,ssl協(xié)議在協(xié)商過程使用非對(duì)稱加密技術(shù), 最后協(xié)商出對(duì)稱秘鑰進(jìn)行通信,對(duì)稱秘要沒有在網(wǎng)絡(luò)上傳遞, 是雙方通過算法計(jì)算出來的。

7 設(shè)計(jì)原則與測(cè)試結(jié)果

7.1設(shè)計(jì)原則
簽名文件規(guī)格:(device.mk設(shè)計(jì)參考之前的)
1)Userdebug 與user 區(qū)別
userdebug 系統(tǒng)platform.jks 有可能release 給別人,因此user版本設(shè)計(jì)成不一樣的。
user 系統(tǒng)platform.jks 僅僅relase公司的app 開發(fā)人員
2)user 與ota ,只是ota 多了releaseky,其他文件都一樣

7.2測(cè)試華為手機(jī)user version【開發(fā)者模式】:

  • debug app 可以正常安裝, 在AndroidManifest.xml 添加了 android:sharedUserId="android.uid.system"

  • release apk(沒有簽名), 不能安裝,【 在AndroidManifest.xml 添加了 android:sharedUserId="android.uid.system"

  • release apk(使用platform 簽名[android10 google原生platformq簽名]), 這種方式可以正常安裝

  • release apk(使用platform 簽名[自己制作android10platformq簽名]), 這種方式可以正常安裝
    上面兩種都可以安裝,在運(yùn)行的時(shí)候?qū)ο到y(tǒng)權(quán)限的多種有所不同。

  • release apk(使用platform 簽名[自己制作android10platformq簽名]), 這種方式可以正常安裝,安裝之后再次對(duì)APK 簽名(使用原生簽名文件), 發(fā)現(xiàn)CERT.RSA 簽名文件失效, 不能再次安裝,提示簽名不匹配

Performing Streamed Install
adb: failed to install C:\Users\Desktop\old.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package com.example.demo signatures do not match previously installed version; ignoring!]

REF:
http://www.itdecent.cn/p/76e5f5e64b85
https://developer.android.google.cn/studio/publish/app-signing
ota relase key 參考

下載文件地址:
git clone https://github.com/getfatday/keytool-importkeypair.git

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載請(qǐng)注明出處:http://www.itdecent.cn/p/286d2b372334github:http...
    rushjs閱讀 40,737評(píng)論 3 62
  • 一、Apk打包流程 既點(diǎn)擊Andorid Studio的Build按鈕后發(fā)生了什么?Android 的包文件 AP...
    momxmo閱讀 1,589評(píng)論 0 2
  • 一、前言 Android 簽名。 在說道Android簽名之前,我們需要了解的幾個(gè)知識(shí)點(diǎn) 1、數(shù)據(jù)摘要(數(shù)據(jù)指紋)...
    福later閱讀 21,715評(píng)論 0 13
  • apk簽名過程及多渠道 公司業(yè)務(wù)渠道較多共有70多個(gè)渠道,打包時(shí)間較長(zhǎng),所以抽時(shí)間研究一下美團(tuán)的多渠道打包。本文介...
    嘻嘻瘋子閱讀 1,826評(píng)論 0 1
  • 對(duì)于 Android 開發(fā)者而言, APK 簽名的重要性不言而喻。Android 7.0 后 APK 簽名已經(jīng)從基...
    Cavabiao閱讀 10,094評(píng)論 7 30

友情鏈接更多精彩內(nèi)容