android 系統簽名【轉】

來源:互聯網
上載者:User

標籤:安全   cti   系統預設   問題   otherwise   cer   類型   許可權控制   rod   

本文轉載自:http://blog.csdn.net/csh86277516/article/details/73549824

Android——編譯release版簽名系統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):

 

  1. The following commands were used to generate the test key pairs:  
  2.   
  3.   development/tools/make_key testkey  ‘/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=[email protected]‘  
  4.   development/tools/make_key platform ‘/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=[email protected]‘  
  5.   development/tools/make_key shared   ‘/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=[email protected]‘  
  6.   development/tools/make_key media    ‘/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=[email protected]‘  
  7.   
  8. The following standard test keys are currently included:  
  9.   
  10. testkey -- a generic key for packages that do not otherwise specify a key.  
  11. platform -- a test key for packages that are part of the core platform.  
  12. shared -- a test key for things that are shared in the home/contacts process.  
  13. media -- a test key for packages that are part of the media/download system.  
  14.   
  15. These test keys are used strictly in development, and should never be assumed  
  16. to convey any sort of validity.  When $BUILD_SECURE=true, the code should not  
  17. 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中定義變數:

 

 

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


在主makefile檔案裡面:

 

 

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

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

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

  

  1. Enter password for build/target/product/security/releasekey.pk8 (password will not be hidden): java.lang.NullPointerException  
  2.     at com.android.signapk.SignApk.decryptPrivateKey(SignApk.java:142)  
  3.     at com.android.signapk.SignApk.readPrivateKey(SignApk.java:166)  
  4.     at com.android.signapk.SignApk.main(SignApk.java:531)  
  5. 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  
  6. make: *** 正在等待未完成的任務....  
  7. Enter password for build/target/product/security/releasekey.pk8 (password will not be hidden): java.lang.NullPointerException  
  8.     at com.android.signapk.SignApk.decryptPrivateKey(SignApk.java:142)  
  9.     at com.android.signapk.SignApk.readPrivateKey(SignApk.java:166)  
  10.     at com.android.signapk.SignApk.main(SignApk.java:531)  
  11. make: *** [out/target/product/gotechcn/obj/APPS/Calculator_intermediates/package.apk] 錯誤 1  
  12. Warning: AndroidManifest.xml already defines minSdkVersion (in http://schemas.android.com/apk/res/android); using existing value in manifest.  
  13. Warning: AndroidManifest.xml already defines targetSdkVersion (in http://schemas.android.com/apk/res/android); using existing value in manifest.  
  14.  ‘out/target/common/obj/APPS/Calendar_intermediates/classes.dex‘ as ‘classes.dex‘...  
  15. Enter password for build/target/product/security/releasekey.pk8 (password will not be hidden): java.lang.NullPointerException  
  16.     at com.android.signapk.SignApk.decryptPrivateKey(SignApk.java:142)  
  17.     at com.android.signapk.SignApk.readPrivateKey(SignApk.java:166)  
  18.     at com.android.signapk.SignApk.main(SignApk.java:531)  
  19. make: *** [out/target/product/gotechcn/obj/APPS/Calendar_intermediates/package.apk] 錯誤 1  
  20. ^Cmake: *** [out/target/product/gotechcn/obj/APPS/BasicDreams_intermediates/package.apk] 錯誤 130  

 

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

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

再編譯完成之後也可以在build.prop中查看到變數:

 

  1. ro.build.tags=release-keys  


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

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

 

四:其它

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

 

  1. 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等可參考http://blog.csdn.net/jscese/article/details/23931159

 

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

  

  1. ./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檔案,這種方式不適用與我目前的工程源碼,沒有做過多驗證!

 

 

 

 

Android簽名機制可劃分為兩部分:(1)ROM簽名機制;(2)第三方APK簽名機制。

Android APK實際上是一個jar包,而jar包又是一個zip包。APK包的簽名實際上使用的是jar包的簽名機制:在zip中添加一個META的子目錄,其中存放簽名資訊;而簽名方法是為zip包中的每個檔案計算其HASH值,得到簽名檔案(*.sf),然後對簽名檔案(.sf)進行簽名並把簽名儲存在簽名塊檔案(*.dsa)中。

ROM簽名機制

在編譯Android源碼產生ROM的過程中,會使用build/target/product/security目錄中的4個key(media, platform, shared, testkey)來對apk進行簽名。其中,*.pk8是二進位形式(DER)的私密金鑰,*.x509.pem是對應的X509密鑰憑證(BASE64編碼)。build/target/product/security目錄中的這幾個預設key是沒有密碼保護的,只能用於debug版本的ROM。

要產生Release版本的ROM,可先產生TargetFiles,再使用帶密碼的key對TargetFiles重新簽名,最後由重簽名的TargetFiles來產生最終的ROM。

可以使用Android源碼樹中內建的工具“development/tools/make_key”來產生帶密碼的RSA公私密金鑰對(實際上是通過openssl來產生的):
$ development/tools/make_key media ‘/C=CN/ST=Sichuan/L=Chengdu/O=MyOrg/OU=MyDepartment/CN=MyName’
上面的命令將產生一個二進位形式(DER)的私密金鑰檔案“media.pk8”和一個對應的X509密鑰憑證檔案“media.x509.pem”。其中,/C表示“Country Code”,/ST表示“State or Province”,/L表示“City or Locality”,/O表示“Organization”,/OU表示“Organizational Unit”,/CN表示“Name”。前面的命令產生的RSA公開金鑰的e值為3,可以修改development/tools/make_key指令碼來使用F4 (0×10001)作為e值(openssl genrsa的-3參數改為-f4)。

也可以使用JDK中的keytool來產生公私密金鑰對,第三方APK簽名一般都是通過keytool來產生公私密金鑰對的。

可以使用openssl x509命令來查看密鑰憑證的詳細資料:
$ openssl x509 -in media.x509.pem -text -noout
or,
$ openssl x509 -in media.x509.pem -inform PEM -text -noout

還可以使用JDK中的keytool來查看密鑰憑證內容,但其輸出內容沒有openssl x509全面:
$ keytool -printcert -v -file media.x509.pem

有了key之後,可以使用工具“build/tools/releasetools/sign_target_files”來對TargetFiles重新簽名:
$ build/tools/releasetools/sign_target_files_apks -d new_keys_dir -o target_files.zip target_files_resigned.zip
其中,new_keys_dir目錄中需要有四個key(media, platform, shared, releasekey)。注意:這裡的releasekey將代替預設的testkey(請參考build/tools/releasetools/sign_target_files指令碼實現),也就是說,如果某個apk的Android.mk檔案中的LOCAL_CERTIFICATE為testkey,那麼在產生TargetFiles時是使用的build/target/product/security/testkey來簽名的,這裡重新簽名時將使用new_keys_dir/releasekey來簽名。

build/tools/releasetools/sign_target_files_apks是通過host/Linux-x86/framework/signapk.jar來完成簽名的。也可以直接使用host/linux-x86/framework/signapk.jar來對某個apk進行簽名:
$ Java -jar signapk [-w] publickey.x509[.pem] privatekey.pk8 input.jar output.jar
其中,”-w”表示還對整個apk包(zip包)進行簽名,並把簽名放在zip包的comment中。

第三方APK簽名機制

對於第三方應用開發人員而言,對APK簽名相對要簡單得多。第三方應用開發一般採用JDK中的keytool和jarsigner來完成簽名密鑰的管理和APK的簽名。

使用keytool來產生儲存有公私密金鑰對的keystore:
$ keytool -genkey -v -keystore my-release-key.keystore -alias mykey -keyalg RSA -keysize 2048 -validity 10000

查看產生的密鑰資訊:
$ keytool -list -keystore my-release-key.keystore -alias mykey -v
or,
$ keytool -list -keystore my-release-key.keystore -alias mykey -rfc
(註:擷取Base64格式的密鑰憑證,RFC 1421)

匯出密鑰憑證:
$ keytool -export -keystore mystore -alias mykey -file my.der
(註:二進位格式密鑰憑證,DER)
$ keytool -export -keystore mystore -alias mykey -file my.pem -rfc
(註:Base64格式密鑰憑證,PEM)

對APK進行簽名:
$ jarsigner -verbose -keystore my-release-key.keystore my_application.apk mykey

驗證簽名:
$ jarsigner -verify -verbose -certs my_application.apk

在進行Android二次開發時,有時需要把build/target/product/security下面的公私密金鑰對轉換為keystore的形式,可以參考這篇文章:把Android源碼中的密碼對轉換為keystore的方法。

android 系統簽名【轉】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.