讀古今文學網 > Android程序設計:第2版 > 應用簽名 >

應用簽名

應用簽名(或代碼簽名)使得Android設備、Android市場及其他發佈方式能夠清楚應用屬於哪個簽名所有人,並可以確保代碼在簽名後沒有被修改。

公鑰加密和加密簽名

公鑰加密的數學原理是,大的素數相乘很容易,但是求大素數的因子很困難。計算大素數乘積可能只需要微秒級的時間,而求大素數的因子可能需要數百萬年,需要天文數字般大的計算能力。

求乘積和求因子之間的天壤之別意味著由兩個大素數生成的乘積所得到的鑰匙可以作為公鑰。對加密的消息進行解密就是求兩個大素數因子,這兩個因子就是私鑰。這意味著由公鑰加密的文件是安全的,只有持有私鑰才能夠破解。

在Android應用中所要生成的簽名取決於公鑰加密的相關屬性。

對文件簽名的步驟如下:

1.根據文件計算唯一散列值。這也稱為消息摘要(message digest)。

2.根據簽名者的私鑰對消息摘要進行「加密」。這樣就得到了簽名。

好了!現在有了數值簽名——對文件通過散列函數求值,並且和簽名者的私鑰相關。

驗證一個簽名文件的步驟如下:

1.根據文件計算唯一散列值。

2.使用公鑰對簽名進行「解密」,其結果值和散列值應該相同。

你可能注意到一個有趣的現象,文件(在我們這裡即應用)源於私鑰所有者,該私鑰和在校驗中使用的公鑰對應。除非文件沒有發生改變,否則對簽名進行解密所求得的散列值會不同於從文件中計算出的散列值。

驗證簽名也確保了簽名沒有拷貝錯誤。簽名是和其創建文件唯一相關的。

注意:你可能已經注意到我們在談到對消息摘要或散列加密時,對「加密」和「解密」兩個詞加了引號。這是因為它和你通常在公鑰和私鑰系統中所使用的加密和解密不同——通過公鑰對消息進行加密,從而只有私鑰持有者才能夠讀懂該消息。

這裡,「加密」表示的是「計算一個數值」。通過私鑰對散列或消息摘要進行「加密」並不是把消息隱藏起來。使用加密和解密這兩個詞的原因是當你使用公鑰進行解密時,你得到通用的散列或消息摘要。

任何持有公鑰和發佈算法的人都可以對消息「解密「——這正是驗證的意義:看到你獲得和發佈人提供的同樣的散列簽名,也證實了發佈人確實持有和公鑰對應的私鑰,並能證實文件和發佈人一致。

因為可以通過公鑰來計算驗證,你的Android系統,以及任何其他相關方,可以驗證應用是使用某個特定鍵(key)計算的簽名,而且在生成該簽名後就沒有被修改過。

更普遍的是,任何電子文檔(任意數據)都可以對其加密簽名,而加密後的簽名即「數字簽名」可以用於對文件進行簽署,就相當於法律意義上的手寫簽名。

簽名是如何做到保護軟件用戶、發佈商和安全通信的

作為計算機軟件用戶,你可能一直在思考:「如果能夠知道我使用的軟件來自哪裡,並且在我的設備上沒有被修改,那將是一件很好的事情。」帶簽名的應用就可以達到這個目的。該信心來自於這個簽名,原理類似於你可能用過的圖形簽名。當你瀏覽Web時,你已經依賴於圖形簽名來確認你正在瀏覽的電子網站是真實的,而不是冒名騙錢之後就開溜的流氓網站。在電子商務中,客戶使用第三方證書頒發機構提供的公鑰來驗證服務器的證書籤名。瀏覽器內置了一些證書頒發機構提供的這類密鑰。

證書頒發機構的作用是鞏固各方的信任關係:信任瀏覽器供應商只使用信譽良好的證書頒發機構的密鑰,電子商務服務提供商從瀏覽器供應商信任的頒發機構獲取證書。證書頒發機構有責任核實信息的真實性,如Amazon.com確實是真正的Amazon.com。現在,當你的瀏覽器向Amazon.com發起安全會話時,你清楚兩件事:加密之後進行傳輸的數據是安全的,只有電子商務服務商能對數據進行解密。你可以相信正在訪問的服務器,因為它所使用的證書是由證書頒發機構發佈的,並且證書頒發機構已經採取各種措施確保自己是向已知的另一方發佈證書。

Android軟件的自簽名證書

對於Android軟件簽名,其簽名證書不需要來自證書頒發機構。Android簽名可以由軟件發佈商創建——在這個例子中,軟件發佈商就是你。和電子商務中的交易不同,Android軟件不需要確保和瀏覽器的每一次連接都是真實可信的,例如連接到真正的Amazon.com,Android軟件可能會使用未知出處的連接,使用軟件也不需要嚴格瞭解簽署方的身份。

對於考慮使用由證書頒發機構所發佈的簽名的企業,Google文檔明確指出應用沒有必要使用證書頒發機構提供的簽名,而自我認證是Android應用的非正式標準。

除了初步驗證應用開發者的身份,Android軟件在升級應用時也會使用Android數字簽名,從而確保升級時能夠訪問歷史版本所創建的文件,而應用升級也並非惡意使用應用,沒有試圖竊取用戶數據。

只要確定軟件升級和初次獲取軟件來自相同的發佈商,就可以充分相信正在使用的軟件是安全的,而且軟件的分發商即Android市場,是知道該軟件的發佈商的。

除了確保更新來源於原始發佈商之外,Android應用是沙盒式的,需要獲得許可才能訪問可能損壞你的數據或造成在移動設備上收費的功能,詳細說明請參考下面這條鏈接:http://developer.android.com/guide/topics/security/security.html。

應用簽名

加密簽名背後的概念是微妙和複雜的。但是其複雜性是由SDK工具管理的。當你在設備或模擬器上編譯和運行Android代碼時,運行的是帶簽名的代碼。

證書調試

如果你對本書給出的例子都做過實際練習,創建Android項目並在模擬器或設備上運行它。你可能已經注意到,雖然所有的Android代碼都必須簽署簽名,但你不需要創建證書,並且你的應用仍然可以安裝在Android手機上。有這種便利性是因為使用了自動創建的調試證書。我們一起來看看調試證書。

首先查看home目錄下的android目錄。在該目錄下,應該可以找到一個名為debug.keystore的文件。使用keytool命令,可以查看該文件中的內容:


keytool -list -keystore debug.keystore
  

當需要密碼時,輸入android。則可以看到如下的輸出:


Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
androiddebugkey, May 13, 2010, PrivateKeyEntry,
Certificate fingerprint (MD5): 95:04:04:F4:51:0B:98:46:14:74:58:15:D3:CA:73:CE
  

keystore類型和提供商表明keystore是Java keystore,兼容Java加密架構和使得Android得以使用代碼簽名和其他加密工具的Java類。關於Java加密架構的更多信息可以訪問下面這條鏈接:http://download.oracle.com/javase/6/docs/technotes/tools/solaris/keytool.html。

keytool命令是JDK的一部分,在P30「keytool」一節做了簡要描述,要查看更詳細的說明可以訪問鏈接http://developer.android.com/guide/publishing/app-signing.html#cert。查閱keytool詳細的文檔說明可以訪問下面這條鏈接:http://download.oracle.com/javase/6/docs/technotes/tools/solaris/keytool.html。

keytool的list選項最後一行輸出是證書指紋。證書指紋是根據密鑰生成的唯一編號。在P124「應用簽名」一節中,可以看到該編號的一種使用方式,通過該編號獲取API密鑰。

該證書在很短的時間間隔內就會過期失效,因此不能用於Android軟件分發,而只能用於測試。不要誤認為可以使用調試證書來對軟件進行簽名就意味著你在分發軟件時可以不需要對軟件進行簽名!

創建自簽名的證書

準備對代碼進行簽名以便發佈了嗎?首先,使用keytool工具創建私鑰:


keytool -genkey -v -keystore my-release-key.keystore -alias alias_name 
  -keyalg RSA -keysize 2048 -validity 50000
  

注意:字符「」表示換行符,在Unix和Mac OS X系統上可以使用該字符來表示多行命令。但是,在Windows系統上,必須在一行上輸出整條命令,不能使用「」來表示。

對於my-release-key和alias_name,可以選擇一個名字進行替換。參數-keysize和-validity應該保留,正如前面的代碼所示。

如下面代碼所示,keytool命令會要求輸入keystore的密碼。在訪問keystore時,需要記住該密碼及關於你個人、組織結構和地理位置的一系列問題。keytool工具生成一個私鑰作為證書籤名,其有效期大約是150年,保存在文件my-release_key.keystore中:


example-user@default-hostname:~$ keytool -genkey -v 
  -keystore example-release-key.keystore -alias example_alias_name 
  -keyalg RSA -keysize 2048 -validity 50000
Enter keystore password:
Re-enter new password:
What is your first and last name?
  [Unknown]: Example Examplenik
What is the name of your organizational unit?
  [Unknown]: Example
What is the name of your organization?
  [Unknown]: Example
What is the name of your City or Locality?
  [Unknown]: Example
What is the name of your State or Province?
  [Unknown]: Massachusetts
What is the two-letter country code for this unit?
  [Unknown]: US
Is CN=Example Examplenik, OU=Example, O=Example, L=Example, ST=Massachusetts,
   C=US correct?
  [no]: yes
Generating 2,048 bit RSA key pair and self-signed certificate (SHA1withRSA) with a
      validity of 50,000 days for: CN=Example Examplenik, OU=Example, O=Example,
      L=Example, ST=Massachusetts, C=US
Enter key password for <example_alias_name>
      (RETURN if same as keystore password):
Re-enter new password:
[Storing example-release-key.keystore]
 

現在,有了keystore的有效密鑰。

千萬別丟失密鑰

雖然加密的數字簽名在很多方面要比手寫的簽名更可靠和安全,但是它也有不足:無法對文件進行數字簽名。

如果你丟掉了簽名的證書,你就失去了在Android設備和Android市場上的「身份證」。這意味著即使你編譯和發佈的代碼和之前完全相同,你也無法使用這些新編譯的應用來更新之前的應用,因為Android設備和Android市場都無法識別出你是之前的發佈商。

要在多個地理位置的多種類型的媒體上保存多份簽名證書副本,包括紙質文件。要保證這些備份文件的安全性。如果你的簽名證書被其他人使用,他們可以替換你的客戶的Android設備的程序。

關於確保簽名證書安全性的詳細建議可以通過Android Developer站點查閱:http://developer.android.com/guide/publishing/app-signing.html#secure-key。

注意:相反,你的加密簽名是僅屬於你的簽名,因為它歸你所有。在你想要發佈Android應用並繼續作為該應用的發佈商時,你可以隨意生成、使用和丟棄簽名。不要害怕嘗試和學習!

使用自簽名的證書對應用進行簽名

現在開始對應用簽名。在Eclipse中,選擇要發佈的應用的項目,並選擇File→Export命令。你可能會問,「為什麼要選擇export命令?」畢竟,如果你想讓別人嘗試你的應用,你可以給其一份bin下的.apk文件副本。它看起來很隨意:export對話框中提供了一系列功能,這是一個放置與deploying有一些差別的處理過程的合適地方。

在這個例子中,我們使用的是TestActivity項目,但是實際上可以使用任意一個項目——你自己創建的項目,或者本書示例中給出的任意項目。

Eclipse會提供一個選項列表,這些選項以文件形式組織。選擇Android文件夾,然後選擇Export Android Application選項(如圖4-1所示),最後單擊Next按鈕。

首先,需要查看應用在配置上是否存在任何錯誤,有些錯誤信息會妨礙應用的發佈,例如在manifest文件中把debuggable屬性設置成了true。如果應用已經準備就緒,那麼在如圖4-2所示的對話框中不會顯示任何錯誤。

應用的簽署發佈包含多個步驟,後續對話框主要集中於簽名。所請求的信息跟你為創建在P128「創建自簽名的證書」一節中所描述的發佈密鑰輸入的信息一致。

下一步,選擇keystore,如圖4-3所示。keystore是個文件夾,保存著你的密鑰。

圖4-1:導出Android應用

圖4-2:Android應用,它在簽名和發佈上沒有任何問題

圖4-3:選擇keystore

輸入keystore名稱和密碼之後,單擊Next按鈕進行下一步操作:選擇密鑰的別名,輸入該別名的密碼,如圖4-4所示。

圖4-4:選擇密鑰別名

如果你實際練習過了P128「創建自簽名的證書」一節中所描述的各個步驟,那麼在你的keystore文件中,只會有一個密鑰及一個別名。輸入密鑰,單擊Next按鈕。下一步是指定目標.apk文件,檢查確定你的應用是否包含一些錯誤。如果一切準備順利,將會看到圖4-5所示的結果。

圖4-5:選擇目標路徑及最後的檢查

單擊Finish按鈕,在指定的路徑下面就可以看到所指定的.apk文件已經生成好了。