1. 程式人生 > >Unity接入SDK_簽名_Keystore相關

Unity接入SDK_簽名_Keystore相關

在Unity打包安卓平臺APK包時,需要使用到KeyStore對其APK進行簽名。Android系統在安裝Apk的過程中,會對Apk進行簽名校驗,校驗通過後才能安裝成功。比如申請第三方SDK(微信登陸,支付)時會檢驗及使用。

1. 簽名是什麼?

簽名是什麼,先來看為什麼需要簽名 。大家都知道,在訊息通訊時,必須至少解決兩個問題:一是確保訊息來源的真實性,二是確保訊息不會被第三方篡改。在安裝Apk時,同樣需要確保Apk來源的真實性,以及Apk沒有被第三方篡改。如何解決這兩個問題呢?方法就是開發者對Apk進行簽名:在Apk中寫入一個“指紋”。指紋寫入以後,Apk中有任何修改,都會導致這個指紋無效,Android系統在安裝Apk進行簽名校驗時就會不通過,從而保證了安全性。

要了解如何實現簽名,需要了解兩個基本概念:數字摘要和數字證書。

簡單來說,就是對一個任意長度的資料,通過一個Hash演算法計算後,都可以得到一個固定長度的二進位制資料,這個資料就稱為“摘要”。摘要具有下面的幾個特徵:

1.1 數字摘要

  1. 唯一性:在不考慮碰撞的情況下,不同的資料的計算出的摘要是不同的。

  2. 固定長度:不同的Hash演算法計算的長度是不一樣的,但對同一個演算法來說是一樣的。比較常用的Hash演算法有MD5和SHA1,MD5的長度是128拉,SHA1的長度是160位。

  3. 不可逆性:即從正向計算的摘要不可能逆向推匯出原始資料。

 1.2 簽名和校驗的大體過程

前面已經說到,可以通過簽名來確保資料來源的可靠性和資料的不可篡改性。簽名就是在摘要的基礎上再進行一次加密,對摘要加密後的資料就可以當作數字簽名,在安裝Apk需要對簽名進行驗證,驗證通過才能繼續安裝

先來說簽名過程:

  1. 計算摘要:通過Hash演算法提取出原始資料的摘要;

  2. 計算簽名:再通過基於金鑰(私鑰)的非對稱加密演算法對提取出的摘要進行加密,加密後的資料就是簽名信息;

  3. 寫入簽名:將簽名信息寫入原始資料的簽名區塊內。

再來看校驗過程:

1.3 數字證書 

  1. 計算摘要:接收方接收到資料後,首先用同樣的Hash演算法從接收到的資料中提取出摘要;

  2. 解密簽名:

    使用傳送方的公鑰對數字簽名進行解密,解密出原始摘要;

  3. 比較摘要 :如果解密後的資料和提取的摘要一致,則校驗通過;如果資料被第三方篡改過,解密後的資料和摘要不一致,校驗不通過

這裡有一個前提:接收方必須要知道傳送方的公鑰和所使用的演算法。如果數字簽名和公鑰一起被篡改,接收方無法得知,還是會校驗通過。如何保證公鑰的可靠性呢?答案是數字證書,數字證書是身份認證機構(Certificate Authority)頒發的,包含了以下資訊:

證書頒發機構 證書頒發機構簽名 證書繫結的伺服器域名 證書版本、有效期 簽名使用的加密演算法(非對稱演算法,如RSA)

接收方收到訊息後,先向CA驗證證書的合法性(根據證書的簽名、繫結的域名等資訊。CA機構是權威的,可以保證這個過程的可靠性。)再進行簽名校驗。

需要注意的是,Apk的證書通常的自簽名的,也就是由開發者自己製作,沒有向CA機構申請。Android在安裝Apk時並沒有校驗證書本身的合法性,只是從證書中提取公鑰和加密演算法,這也正是對第三方Apk重新簽名後,還能夠繼續在沒有安裝這個Apk的系統中繼續安裝的原因

1.4 簽名和校驗過程

2. keystore和證書格式

我們在對Apk簽名時並沒有直接指定私鑰、公鑰和數字證書,而是使用keystore檔案,這些資訊都包含在了keystore檔案中。根據編碼不同,keystore檔案分為很多種,Android使用的是Java標準keystore格式JKS(Java Key Storage),所以通過Android Studio匯出的keystore檔案是以.jks結尾的。

keystore使用的證書標準是X.509,X.509標準也有多種編碼格式,常用的有兩種:pem(Privacy Enhanced Mail)和der(Distinguished Encoding Rules)。jks使用的是der格式,Android也支援直接使用pem格式的證書進行簽名,我們下面會介紹。

兩種證書編碼格式的區別:

DER(Distinguished Encoding Rules)

二進位制格式,所有型別的證書和私鑰都可以儲存為der格式。

PEM(Privacy Enhanced Mail)

base64編碼,內容以-----BEGIN xxx----- 開頭,以-----END xxx----- 結尾,比如:

3. jarsigner和apksigner的區別

Android提供了兩種對Apk的簽名方式,一種是基於JAR的簽名方式,另一種是基於Apk的簽名方式,它們的主要區別在於使用的簽名檔案不一樣:jarsigner使用keystore檔案進行簽名;apksigner除了支援使用keystore檔案進行簽名外,還支援直接指定pem證書檔案和私鑰進行簽名。

android {
    signingConfigs {
        config {
            storeFile file(keystoreProperties['storeFile'])
            storePassword keystoreProperties['storePassword']
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword'] 
        }
    }
    ...
  }

不知道大家有沒有注意一個問題,我們通過keytool或者AS生成一個keystore的時候(簽署您的應用),除了要輸入keystore的密碼外,還要輸入一個alias和key的密碼。在簽名時,除了要指定keystore檔案和密碼外,也要指定alias和key的密碼,這是為什麼呢?

原因是keystore是一個金鑰庫,也就是說它可以儲存多對金鑰和證書,keystore的密碼是用於保護keystore本身的,一對金鑰和證書是通過alias來區分的。從這裡可以看出jarsigner是支援使用多個證書對Apk進行簽名的。apksigner也同樣支援,關於apksigner的使用介紹可以參考官方文件apksigner

3.1 簽名相關命令

● jarsigner簽名
jarsigner -keystore keystore_file -signedjar signed.apk unsigned.apk alias_name -storepass pwd

● apksigner簽名
java -jar signapk.jar cert.x509.pem private.pk8 unsigned.apk signed.apk

● 檢視keystore檔案
keytool -list  -v -keystore keystore_file -storepass pwd

● 檢視apk證書
keytool -printcert -jarfile apk

● 檢視DER格式證書(META-INFO/CERT.RSA)
openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text

● 檢視PEM格式證書
openssl x509 -in cert.x509.pem -text -noout

● apksigner檢查apk是否簽名,以及檢視證書SHA1值
apksigner verify -v --print-certs

keytool -list  -v -keystore xxxx.keystore -storepass 密碼,簽名的資訊就有了

在手機上檢視對應APK的簽名:

下載個Gen_Signature_Android,安裝在手機上,輸出對應的包名就可以檢視簽名的MD5,不過要知道APK包名。