android系统release签名
轉(zhuǎn)自:http://blog.csdn.net/yangkai6121/article/details/38682321
為什么需要給Android系統(tǒng)簽個(gè)名才能進(jìn)行CTS認(rèn)證呢?原來(lái)我們通過(guò)make -j4編譯出來(lái)的system.img使用的是test key,這種類(lèi)型的key只適用于開(kāi)發(fā)階段,而且這種秘鑰是公開(kāi)的,誰(shuí)都可以使用。當(dāng)發(fā)布一款android產(chǎn)品,就需要另外給整個(gè)系統(tǒng)簽個(gè)名,防止被別 人盜用。這種系統(tǒng)就是release版本的Android系統(tǒng)。
?
一、 首先介紹關(guān)于簽名的作用
??1、 APK簽名的作用:
?? ?a) 發(fā)送者的身份認(rèn)證,由于開(kāi)發(fā)商可能通過(guò)使用相同的Package Name來(lái)混淆替換已經(jīng)安裝的程序,以此保證簽名不同的包不被替換。
?? ?b) 保證信息傳輸?shù)耐暾?#xff0c;簽名對(duì)于包中的每個(gè)文件進(jìn)行處理,以此確保包中內(nèi)容不被替換,防止交易中的抵賴(lài)發(fā)生,Market對(duì)軟件的要求。
??2、 Recovery簽名作用:
? ?? ?Recovery進(jìn)行簽名的主要作用是用來(lái)驗(yàn)證數(shù)據(jù)的完整性。
??3、要對(duì)Android系統(tǒng)進(jìn)行簽名,需要生成四種類(lèi)型的key文件。
?? ?a)releasekey (或testkey)
?? ?b)media
?? ?c)shared
?? ?d)platform
以上的四種,可以在源碼的/build/target/product/security里面看到對(duì)應(yīng)的密鑰,其中shared.pk8代表私鑰,shared.x509.pem公鑰,一定是成對(duì)出現(xiàn)的。其中testkey是作為android編譯的時(shí)候默認(rèn)的簽名key,如果系統(tǒng)中的apk的android.mk中沒(méi)有設(shè)置LOCAL_CERTIFICATE的值,就默認(rèn)使用testkey。而如果設(shè)置成:LOCAL_CERTIFICATE := platform 就代表使用platform來(lái)簽名,這樣的話這個(gè)apk就擁有了和system相同的簽名,因?yàn)橄到y(tǒng)級(jí)別的簽名也是使用的platform來(lái)簽名,此時(shí)使用android:sharedUserId="android.uid.system"才有用!
二、 生成加密key文件
??? 我們就拿releasekey為例簡(jiǎn)單介紹下生成過(guò)程。Android使用SHA1-RSA算法進(jìn)行簽名。可通過(guò)eclipse插件進(jìn)行,可以通過(guò)keytool和jarsigner 用命令行執(zhí)行。也可以在源碼下進(jìn)行簽名。
?????1、以源碼下簽名方法來(lái)介紹生成密鑰對(duì)方法:
直接執(zhí)行development/tools/make_key releasekey? '/C=CN/ST=BeiJing/L=HaiDian View/O=JiuZhou/OU=PingTai/CN=lran/emailAddress=lran@jzby.com'生成releasekey.pk8和releasekey.x509.pem。其中releasekey? 是指最后的加密方式為release方式,執(zhí)行后顯示如下:
development/tools$ sh make_key releasekey '/C=CN/ST=JiangSu/L=NanJing/O=Company/OU=Department/CN=YourName/emailAddress=YourE-mailAddress'
Enter password for 'releasekey' (blank for none; password will be visible): mypassword???? <------- 設(shè)置你的密碼(一般直接回車(chē),要不每次簽名apk,你還得手動(dòng)輸入簽名密碼,后面講其他原因)
creating platform.pk8 with password [mypassword]
Generating RSA private key, 2048 bit long modulus
...............+++
........................................................+++
e is 3 (0x3)
key的名字很好理解,就是前面提到的4中類(lèi)型的key,公司信息的參數(shù)比較多,它們的含義如下:
C?? --->? Country Name (2 letter code)
ST? --->? State or Province Name (full name)
L?? --->? Locality Name (eg, city)
O?? --->? Organization Name (eg, company)
OU? --->? Organizational Unit Name (eg, section)
CN? --->? Common Name (eg, your name or your server’s hostname)
emailAddress --->? Contact email address
這樣就生成了一組releasekey,另外3種類(lèi)型的key的生成方法也基本一樣。
生成后的結(jié)果如下:
/development/tools$ ls
makedict? media.pk8?????? mkstubs?????? platform.pk8?????? releasekey.pk8?????? shared.pk8?? make_key? media.x509.pem??? platform.x509.pem? releasekey.x509.pem? shared.x509.pem
*.pk8是生成的私鑰,而*.x509.pem是公鑰,生成時(shí)兩者是成對(duì)出現(xiàn)的.
另外,如果出現(xiàn) openssl : relocation error :openssl : symbol ...嘗試用 sudo 執(zhí)行命令, 問(wèn)題解決了!
生成的密鑰需要放到build/target/product/security/目錄下面,因?yàn)橹跋到y(tǒng)里面寫(xiě)的test-keys的密鑰就放在此處。我們是仿照系統(tǒng)的方法的方法放在此處,后面寫(xiě)系統(tǒng)簽名剛好用到所以放到該文件夾最合適。
? 2、 make_key介紹
a)生成公鑰
openssl genrsa -3 -out testkey.pem 2048
其中-3是算法的參數(shù),2048是密鑰長(zhǎng)度,testkey.pem是輸出的文件
b) 轉(zhuǎn)成x509格式(含作者有效期等)
openssl req -new -x509 -key testkey.pem -out testkey.x509.pem -days 10000 -subj ‘/C=US/ST=California/L=MountainView/O=Android/OU=Android/CN=Android/emailAddress=android@android.com’
c) 生成私鑰
openssl pkcs8 -in testkey.pem -topk8 -outform DER -out testkey.pk8 -nocrypt
把的格式轉(zhuǎn)換成PKCS #8,這里指定了-nocryp,表示不加密,所以簽名時(shí)不用輸入密碼
三、 如何簽名
?
? 1、 對(duì)APK簽名命令:
signapk publickey.x509[.pem] privatekey.pk8 input.apk output.apk
如上面就可以寫(xiě)為:java -jar signapk.jar releasekey.x509.pem releasekey.pk8 input.apk output.apk
簽名后,輸出文件的meta_inf目錄下生長(zhǎng)如下文件:
MANIFEST.MF:對(duì)非文件夾非簽名文件的文件,逐個(gè)生成SHA1的數(shù)字簽名信息
CERT.SF:對(duì)Manifest文件,使用SHA1-RSA算法,用私鑰進(jìn)行簽名。
CERT.RSA:CERT.RSA文件中保存了公鑰、所采用的加密算法等信息。
下圖是eclipse中簽名的過(guò)程。
?
? 2、 對(duì)recovery 簽名命令:
signapk –w publickey.x509[.pem] privatekey.pk8 input.zip output.zip
- w參數(shù)表示對(duì)整個(gè)文件進(jìn)行簽名,目前看只是在制作recovery升級(jí)包時(shí)使用。
對(duì)升級(jí)包的簽名可參考:http://blog.163.com/yi_yixinyiyi/blog/static/136286889201132533759563/
另外一種對(duì)系統(tǒng)的簽名可以直接在源碼加入編譯的簽名的路徑不需要在去手動(dòng)簽名,其修改方法如下:
主要參考了:http://www.cnblogs.com/leaven/p/3860583.html 講的很詳細(xì),也很有用。
a)修改/build/core/config.mk中變量DEFAULT_SYSTEM_DEV_CERTIFICATE ,修改方法如下:(紅色為添加代碼)
# 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
#modify by lran jzby 指出密鑰路徑
? DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/releasekey
# ###############################################################
# Set up final options.
# ###############################################################
b) 在build/core/Makefile中添加:
?? ?(1)mx中修改方法
ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/testkey)
BUILD_KEYS := test-keys
else
BUILD_KEYS := dev-keys
endif
#modify by lran jzby 目的就是配置當(dāng)前的名方式為release方式
ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/releasekey)
BUILD_KEYS := release-keys
endif
BUILD_VERSION_TAGS += $(BUILD_KEYS)
.....
ifeq ($(BUILD_SECURE),true)
?? ?OTA_PUBLIC_KEYS := device/*/$(TARGET_DEVICE)/releasekey.x509.pem
else
?? ?OTA_PUBLIC_KEYS := $(SRC_TARGET_DIR)/product/security/testkey.x509.pem
endif
#modify by lran jzby? 指向密鑰
?? ?OTA_PUBLIC_KEYS := build/target/product/security/releasekey.x509.pem
?? ?(2)hisi中修改方法
ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/testkey)
BUILD_VERSION_TAGS += test-keys
endif
#modify by lran jzby
ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/releasekey)
BUILD_VERSION_TAGS += release-keys
else
BUILD_VERSION_TAGS += dev-keys
endif
BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS)))
海斯中第二行不需要修改,因?yàn)楹K箤?duì)應(yīng)的該行以寫(xiě)成OTA_PUBLIC_KEYS := $(DEFAULT_SYSTEM_DEV_CERTIFICATE).x509.pem可以直接被自動(dòng)替換
(3),其實(shí)在安裝apk的package.mk中也有密鑰的使用,不過(guò)他和海斯一樣直接用DEFAULT_SYSTEM_DEV_CERTIFICATE替代了,所以不用修改。
ifeq ($(LOCAL_CERTIFICATE),)
??? LOCAL_CERTIFICATE := $(DEFAULT_SYSTEM_DEV_CERTIFICATE)
endif
......
private_key := $(LOCAL_CERTIFICATE).pk8
certificate := $(LOCAL_CERTIFICATE).x509.pem
(4)修改完之后就要編譯了,如果上面的這些key在制作的時(shí)候輸入了password就會(huì)出現(xiàn)如下錯(cuò)誤:
??? Enter password for build/target/product/security/releasekey.pk8 (password will not be hidden): java.lang.NullPointerException ?
??????? at com.android.signapk.SignApk.decryptPrivateKey(SignApk.java:142) ?
??????? at com.android.signapk.SignApk.readPrivateKey(SignApk.java:166) ?
??????? at com.android.signapk.SignApk.main(SignApk.java:531) ?
? ??? ? Enter password for build/target/product/security/releasekey.pk8 (password will not be hidden): make: *** ?? ?[out/target/product/gotechcn/obj/APPS/CalendarProvider_intermediates/package.apk] 錯(cuò)誤 1 ?
? ??? ? make: *** 正在等待未完成的任務(wù).... ?
?? ??? ?Enter password for build/target/product/security/releasekey.pk8 (password will not be hidden): java.lang.NullPointerException ?
??????? at com.android.signapk.SignApk.decryptPrivateKey(SignApk.java:142) ?
??????? at com.android.signapk.SignApk.readPrivateKey(SignApk.java:166) ?
??????? at com.android.signapk.SignApk.main(SignApk.java:531) ?
? ??? ? make: *** [out/target/product/gotechcn/obj/APPS/Calculator_intermediates/package.apk] 錯(cuò)誤 1 ?
? ??? ? Warning: AndroidManifest.xml already defines minSdkVersion (in http://schemas.android.com/apk/res/android); using existing value in manifest. ?
? ??? ? Warning: AndroidManifest.xml already defines targetSdkVersion (in http://schemas.android.com/apk/res/android); using existing value in manifest. ?
?? ??? ? 'out/target/common/obj/APPS/Calendar_intermediates/classes.dex' as 'classes.dex'... ?
? ??? ? Enter password for build/target/product/security/releasekey.pk8 (password will not be hidden): java.lang.NullPointerException ?
??????? at com.android.signapk.SignApk.decryptPrivateKey(SignApk.java:142) ?
??????? at com.android.signapk.SignApk.readPrivateKey(SignApk.java:166) ?
??????? at com.android.signapk.SignApk.main(SignApk.java:531) ?
? ??? ? make: *** [out/target/product/gotechcn/obj/APPS/Calendar_intermediates/package.apk] 錯(cuò)誤 1 ?
?? ??? ?^Cmake: *** [out/target/product/gotechcn/obj/APPS/BasicDreams_intermediates/package.apk] 錯(cuò)誤 130 ?
其實(shí)會(huì)出現(xiàn)這個(gè)錯(cuò)誤的最根本的原因是多線程的問(wèn)題。在編譯的時(shí)候?yàn)榱思铀僖话愣紩?huì)執(zhí)行make -jxxx,這樣本來(lái)需要手動(dòng)輸入密碼的時(shí)候,由于其它線程的運(yùn)行,就會(huì)導(dǎo)致影響當(dāng)前的輸入終端,所以就會(huì)導(dǎo)致密碼無(wú)法輸入的情況!再編譯完成之后也可以在build.prop中查看到變量:ro.build.tags=release-keys? 這樣處理了之后編譯出來(lái)的都是簽名過(guò)的了,系統(tǒng)才算是release版本。我發(fā)現(xiàn)我這樣處理之后,整個(gè)系統(tǒng)的算是全部按照我的要求簽名了。
四、 簽名的相關(guān)文件
? 1、 apk包中簽名相關(guān)的文件在meta_INF目錄下
CERT.SF:生成每個(gè)文件相對(duì)的密鑰
MANIFEST.MF:數(shù)字簽名信息
xxx.SF:這是JAR文件的簽名文件,占位符xxx標(biāo)識(shí)了簽名者
xxx.DSA:對(duì)輸出文件的簽名和公鑰
??2、相關(guān)源碼
development/tools/jarutils/src/com.anroid.jarutils/SignedJarBuilder.java
frameworks/base/services/java/com/android/server/PackageManagerService.java
frameworks/base/core/java/android/content/pm/PackageManager.java
frameworks/base/cmds/pm/src/com/android/commands/pm/Pm.java
dalvik/libcore/security/src/main/java/java/security/Sign*
build/target/product/security/platform.*
build/tools/signapk/*
五、? 怎樣驗(yàn)證簽名
? 1、 APK驗(yàn)證:
安裝apk時(shí),通過(guò)CERT.RSA查找公鑰和算法,并對(duì)CERT.SF進(jìn)行解密和簽名驗(yàn)證,確認(rèn)MANIFEST.MF,最終對(duì)每個(gè)文件簽名校驗(yàn)。
升級(jí)時(shí),android也會(huì)進(jìn)行簽名驗(yàn)證。如果遇到以下情況,都不能完成升級(jí):
a)兩個(gè)應(yīng)用,名字相同,簽名不同
b)升級(jí)時(shí)前一版本簽名,后一版本沒(méi)簽名。
c)升級(jí)時(shí)前一版本為DEBUG簽名,后一個(gè)為自定義簽名。
d)升級(jí)時(shí)前一版本為Android源碼中的簽名,后一個(gè)為DEBUG簽名或自定義簽名。
e)安裝未簽名的程序。
f)安裝升級(jí)已過(guò)有效期的程序。
? 一般在apk安裝時(shí)提示出錯(cuò):INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES
a)兩個(gè)應(yīng)用,名字相同,簽名不同
b)升級(jí)時(shí)前一版本簽名,后一版本沒(méi)簽名
c)升級(jí)時(shí)前一版本為DEBUG簽名,后一個(gè)為自定義簽名
d)升級(jí)時(shí)前一版本為Android源碼中的簽
以上可以看到,隨便更換密鑰對(duì)后簽名生成的apk也是可以安裝在任何平臺(tái)的。因?yàn)楣€是放在apk里的。
? 2、 RECOVERY:
Recovery公鑰是固定在代碼里面。并沒(méi)有采用CERT.RSA里面公鑰。目前幾乎所有的手機(jī)平臺(tái)都是用testkey。固定公鑰目的可能是為了確保其它平臺(tái)的升級(jí)包不能被升級(jí)。比如我們統(tǒng)一更換了一個(gè)密鑰對(duì),那么recovery里面固定的公鑰更改后,用testkey做成的升級(jí)包是無(wú)法升級(jí)成功的。
同時(shí)recovery只是對(duì)整個(gè)升級(jí)壓縮文件進(jìn)行簽名校驗(yàn)(前面說(shuō)過(guò)recovery簽名使用的是-w)。
Recovery 代碼里面使用的公鑰是按照rsapublickey 數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)。這個(gè)數(shù)據(jù)是通過(guò)dumppublickey工具從制作出來(lái)的x509證書(shū)文件中獲得。Dumppublickey代碼在網(wǎng)上可以查找到。
轉(zhuǎn)載于:https://www.cnblogs.com/dirt2/p/6233057.html
總結(jié)
以上是生活随笔為你收集整理的android系统release签名的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 用Python玩转词云
- 下一篇: winpcap 发送数据包