android系统release签名
轉(zhuǎn)自:http://blog.csdn.net/yangkai6121/article/details/38682321
為什么需要給Android系統(tǒng)簽個名才能進行CTS認證呢?原來我們通過make -j4編譯出來的system.img使用的是test key,這種類型的key只適用于開發(fā)階段,而且這種秘鑰是公開的,誰都可以使用。當發(fā)布一款android產(chǎn)品,就需要另外給整個系統(tǒng)簽個名,防止被別 人盜用。這種系統(tǒng)就是release版本的Android系統(tǒng)。
?
一、 首先介紹關(guān)于簽名的作用
??1、 APK簽名的作用:
?? ?a) 發(fā)送者的身份認證,由于開發(fā)商可能通過使用相同的Package Name來混淆替換已經(jīng)安裝的程序,以此保證簽名不同的包不被替換。
?? ?b) 保證信息傳輸?shù)耐暾?#xff0c;簽名對于包中的每個文件進行處理,以此確保包中內(nèi)容不被替換,防止交易中的抵賴發(fā)生,Market對軟件的要求。
??2、 Recovery簽名作用:
? ?? ?Recovery進行簽名的主要作用是用來驗證數(shù)據(jù)的完整性。
??3、要對Android系統(tǒng)進行簽名,需要生成四種類型的key文件。
?? ?a)releasekey (或testkey)
?? ?b)media
?? ?c)shared
?? ?d)platform
以上的四種,可以在源碼的/build/target/product/security里面看到對應(yīng)的密鑰,其中shared.pk8代表私鑰,shared.x509.pem公鑰,一定是成對出現(xiàn)的。其中testkey是作為android編譯的時候默認的簽名key,如果系統(tǒng)中的apk的android.mk中沒有設(shè)置LOCAL_CERTIFICATE的值,就默認使用testkey。而如果設(shè)置成:LOCAL_CERTIFICATE := platform 就代表使用platform來簽名,這樣的話這個apk就擁有了和system相同的簽名,因為系統(tǒng)級別的簽名也是使用的platform來簽名,此時使用android:sharedUserId="android.uid.system"才有用!
二、 生成加密key文件
??? 我們就拿releasekey為例簡單介紹下生成過程。Android使用SHA1-RSA算法進行簽名。可通過eclipse插件進行,可以通過keytool和jarsigner 用命令行執(zhí)行。也可以在源碼下進行簽名。
?????1、以源碼下簽名方法來介紹生成密鑰對方法:
直接執(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è)置你的密碼(一般直接回車,要不每次簽名apk,你還得手動輸入簽名密碼,后面講其他原因)
creating platform.pk8 with password [mypassword]
Generating RSA private key, 2048 bit long modulus
...............+++
........................................................+++
e is 3 (0x3)
key的名字很好理解,就是前面提到的4中類型的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種類型的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是公鑰,生成時兩者是成對出現(xiàn)的.
另外,如果出現(xiàn) openssl : relocation error :openssl : symbol ...嘗試用 sudo 執(zhí)行命令, 問題解決了!
生成的密鑰需要放到build/target/product/security/目錄下面,因為之前系統(tǒng)里面寫的test-keys的密鑰就放在此處。我們是仿照系統(tǒng)的方法的方法放在此處,后面寫系統(tǒng)簽名剛好用到所以放到該文件夾最合適。
? 2、 make_key介紹
a)生成公鑰
openssl genrsa -3 -out testkey.pem 2048
其中-3是算法的參數(shù),2048是密鑰長度,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,表示不加密,所以簽名時不用輸入密碼
三、 如何簽名
?
? 1、 對APK簽名命令:
signapk publickey.x509[.pem] privatekey.pk8 input.apk output.apk
如上面就可以寫為:java -jar signapk.jar releasekey.x509.pem releasekey.pk8 input.apk output.apk
簽名后,輸出文件的meta_inf目錄下生長如下文件:
MANIFEST.MF:對非文件夾非簽名文件的文件,逐個生成SHA1的數(shù)字簽名信息
CERT.SF:對Manifest文件,使用SHA1-RSA算法,用私鑰進行簽名。
CERT.RSA:CERT.RSA文件中保存了公鑰、所采用的加密算法等信息。
下圖是eclipse中簽名的過程。
?
? 2、 對recovery 簽名命令:
signapk –w publickey.x509[.pem] privatekey.pk8 input.zip output.zip
- w參數(shù)表示對整個文件進行簽名,目前看只是在制作recovery升級包時使用。
對升級包的簽名可參考:http://blog.163.com/yi_yixinyiyi/blog/static/136286889201132533759563/
另外一種對系統(tǒng)的簽名可以直接在源碼加入編譯的簽名的路徑不需要在去手動簽名,其修改方法如下:
主要參考了:http://www.cnblogs.com/leaven/p/3860583.html 講的很詳細,也很有用。
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 目的就是配置當前的名方式為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īng)的該行以寫成OTA_PUBLIC_KEYS := $(DEFAULT_SYSTEM_DEV_CERTIFICATE).x509.pem可以直接被自動替換
(3),其實在安裝apk的package.mk中也有密鑰的使用,不過他和海斯一樣直接用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在制作的時候輸入了password就會出現(xiàn)如下錯誤:
??? 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] 錯誤 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] 錯誤 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] 錯誤 1 ?
?? ??? ?^Cmake: *** [out/target/product/gotechcn/obj/APPS/BasicDreams_intermediates/package.apk] 錯誤 130 ?
其實會出現(xiàn)這個錯誤的最根本的原因是多線程的問題。在編譯的時候為了加速一般都會執(zhí)行make -jxxx,這樣本來需要手動輸入密碼的時候,由于其它線程的運行,就會導致影響當前的輸入終端,所以就會導致密碼無法輸入的情況!再編譯完成之后也可以在build.prop中查看到變量:ro.build.tags=release-keys? 這樣處理了之后編譯出來的都是簽名過的了,系統(tǒng)才算是release版本。我發(fā)現(xiàn)我這樣處理之后,整個系統(tǒng)的算是全部按照我的要求簽名了。
四、 簽名的相關(guān)文件
? 1、 apk包中簽名相關(guān)的文件在meta_INF目錄下
CERT.SF:生成每個文件相對的密鑰
MANIFEST.MF:數(shù)字簽名信息
xxx.SF:這是JAR文件的簽名文件,占位符xxx標識了簽名者
xxx.DSA:對輸出文件的簽名和公鑰
??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/*
五、? 怎樣驗證簽名
? 1、 APK驗證:
安裝apk時,通過CERT.RSA查找公鑰和算法,并對CERT.SF進行解密和簽名驗證,確認MANIFEST.MF,最終對每個文件簽名校驗。
升級時,android也會進行簽名驗證。如果遇到以下情況,都不能完成升級:
a)兩個應(yīng)用,名字相同,簽名不同
b)升級時前一版本簽名,后一版本沒簽名。
c)升級時前一版本為DEBUG簽名,后一個為自定義簽名。
d)升級時前一版本為Android源碼中的簽名,后一個為DEBUG簽名或自定義簽名。
e)安裝未簽名的程序。
f)安裝升級已過有效期的程序。
? 一般在apk安裝時提示出錯:INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES
a)兩個應(yīng)用,名字相同,簽名不同
b)升級時前一版本簽名,后一版本沒簽名
c)升級時前一版本為DEBUG簽名,后一個為自定義簽名
d)升級時前一版本為Android源碼中的簽
以上可以看到,隨便更換密鑰對后簽名生成的apk也是可以安裝在任何平臺的。因為公鑰是放在apk里的。
? 2、 RECOVERY:
Recovery公鑰是固定在代碼里面。并沒有采用CERT.RSA里面公鑰。目前幾乎所有的手機平臺都是用testkey。固定公鑰目的可能是為了確保其它平臺的升級包不能被升級。比如我們統(tǒng)一更換了一個密鑰對,那么recovery里面固定的公鑰更改后,用testkey做成的升級包是無法升級成功的。
同時recovery只是對整個升級壓縮文件進行簽名校驗(前面說過recovery簽名使用的是-w)。
Recovery 代碼里面使用的公鑰是按照rsapublickey 數(shù)據(jù)結(jié)構(gòu)存儲。這個數(shù)據(jù)是通過dumppublickey工具從制作出來的x509證書文件中獲得。Dumppublickey代碼在網(wǎng)上可以查找到。
轉(zhuǎn)載于:https://www.cnblogs.com/dirt2/p/6233057.html
總結(jié)
以上是生活随笔為你收集整理的android系统release签名的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用Python玩转词云
- 下一篇: winpcap 发送数据包