天天看點

Android——編譯release版簽名系統

    在我的第一篇部落格裡面Android——TV真機調試apk(android:sharedUserId="android.uid.system") ,有提到AndroidManifest.xml中的android:sharedUserId="android.uid.system",代表的意思是和系統相同的uid,可以擁有修改系統時間,檔案操作等權限。

也有提到怎麼單獨給一個apk簽名,這裡補充一下android的簽名權限控制機制。

一:簽名類型

android的标準簽名key有:

testkey

media

platform

shared

以上的四種,可以在源碼的/build/target/product/security裡面看到對應的密鑰,其中shared.pk8代表私鑰,shared.x509.pem公鑰,一定是成對出現的。

其中testkey是作為android編譯的時候預設的簽名key,如果系統中的apk的android.mk中沒有設定LOCAL_CERTIFICATE的值,就預設使用testkey。

而如果設定成:

LOCAL_CERTIFICATE := platform

就代表使用platform來簽名,這樣的話這個apk就擁有了和system相同的簽名,因為系統級别的簽名也是使用的platform來簽名,此時使用android:sharedUserId="android.uid.system"才有用!

二:自定義簽名Key

在/build/target/product/security目錄下有個README,裡面有說怎麼制作這些key以及使用問題(android4.2):

The following commands were used to generate the test key pairs:

  development/tools/make_key testkey  '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/[email protected]'
  development/tools/make_key platform '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/[email protected]'
  development/tools/make_key shared   '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/[email protected]'
  development/tools/make_key media    '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/[email protected]'

The following standard test keys are currently included:

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.

These test keys are used strictly in development, and should never be assumed
to convey any sort of validity.  When $BUILD_SECURE=true, the code should not
honor these keys in any context.
           

從上面可以看出來在源碼下的/development/tools目錄下有個make_key的腳本,通過傳入兩個參數就可以生成一對簽名用的key。

其中第一個為key的名字,一般都預設成android本身有的,因為很多地方都預設使用了這些名字,我們自定義的話隻需要對第二個參數動手腳,定義如下:

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

另外在使用上面的make_key腳本生成key的過程中會提示輸入password,我的處理是不輸入,直接enter,不要密碼!後面解釋,用自定義的key替換/security下面的。

可以看到android源碼裡面的key使用的第二個參數就是上面README裡面的,是公開的,是以要release版本的系統的話,肯定要有自己的簽名key才能起到一個安全控制作用。

三:修改系統預設簽名key

在上面提到如果apk中的編譯選項LOCAL_CERTIFICATE沒有設定的話,就會使用預設的testkey作為簽名key,我們可以修改成自己想要的key,按照上面的步驟制作一個releasekey,修改android配置在/build/core/config.mk中定義變量:

DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/releasekey
           

在主makefile檔案裡面:

ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/releasekey)
BUILD_VERSION_TAGS += release-keys
           

這樣的話預設的所有簽名将會使用releasekey。

修改完之後就要編譯了,如果上面的這些key在制作的時候輸入了password就會出現如下錯誤:

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: *** 正在等待未完成的任務....
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
           

我在網上找到了合理的解釋:

其實會出現這個錯誤的最根本的原因是多線程的問題。在編譯的時候為了加速一般都會執行make -jxxx,這樣本來需要手動輸入密碼的時候,由于其它線程的運作,就會導緻影響目前的輸入終端,是以就會導緻密碼無法輸入的情況!

再編譯完成之後也可以在build.prop中檢視到變量:

ro.build.tags=release-keys
           

這樣處理了之後編譯出來的都是簽名過的了,系統才算是release版本

我發現我這樣處理之後,整個系統的算是全部按照我的要求簽名了。

四:其它

網上看到還有另外的簽名release辦法,但是應該是針對另外的版本的,借用學習一下:

make -j4 PRODUCT-product_modul-user dist
           

這個怎麼跟平時的編譯不一樣,後面多了兩個參數PRODUCT-product_modul-user 和 dist. 編譯完成之後回在源碼/out/dist/目錄内生成個product_modul-target_files開頭的zip檔案.這就是我們需要進行簽名的檔案系統.

我的product_modul 是full_gotechcn,後面加“-user”代表的是最終使用者版本,關于這個命名以及product_modul等可參考Android——編譯系統初始化設定

編譯出需要簽名的zip壓縮包之後,就是利用/security下面的準備的key進行簽名了:

./build/tools/releasetools/sign_target_files_apks -d /build/target/product/security  out/dist/full_gotechcn-target_files.zip   out/dist/signed_target_files.zip
           

簽名目标檔案 輸出成signed_target_files.zip

如果出現某些apk出錯,可以通過在full_gotechcn-target_files.zip前面加參數"-e <apkname>=" 來過濾這些apk.

然後再通過image的腳本生成imag的zip檔案,這種方式不适用與我目前的工程源碼,沒有做過多驗證!

撰寫不易,轉載請注明出處http://blog.csdn.net/jscese/article/details/24243171

繼續閱讀