依附元件驗證

Gradle 依附元件遭到入侵會造成安全性風險。惡意行為人可能會在依附元件解析期間,透過攔截式攻擊,將經過修改的依附元件插入建構程序。

如果建構依附元件 (程式庫) 遭到入侵,可能會影響應用程式在裝置上執行的方式。如果外掛程式依附元件遭到入侵,可能會改變建構作業的方式,甚至在建構機器上執行外部指令。

為減輕這種情況,您可以在建構中啟用依附元件驗證

程式庫總和檢查碼和簽章

程式庫作者可以提供兩個中繼資料,協助您驗證下載的依附元件是否正確無誤。您可以定義名為 gradle/verification-metadata.xml 的檔案,指定您核准的值。可包含:

  • 總和檢查碼:成果的雜湊,可用於驗證成果在傳輸期間未遭到損毀。如果檢查碼是從可信來源擷取,就會告知您該構件並未變更,進而減少中間人攻擊。

    缺點是,由於總和檢查碼是根據構件計算,因此會隨著每個版本而變更,因此您每次升級時都必須更新 gradle/verification-metadata.xml

  • 簽名:允許依附元件使用者為特定構件指定公開金鑰,以便驗證這個構件是由該公開金鑰的已驗證擁有者 (也就是程式庫作者) 建構及簽署。這會增加程式庫作者的工作量,但只要私密金鑰本身未遭到入侵,簽名就會告知您程式庫是合法的。

    如果程式庫作者使用相同的金鑰為每個構件版本簽署,您升級時就不需要更新 gradle/verification-metadata.xml

啟用依附元件驗證功能

Gradle 依附元件驗證會在建構期間比較總和檢查碼和簽章。

建立包含下列內容的 gradle/verification-metadata.xml 檔案:

<?xml version="1.0" encoding="UTF-8"?>
<verification-metadata
    xmlns="https://schema.gradle.org/dependency-verification"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://schema.gradle.org/dependency-verification https://schema.gradle.org/dependency-verification/dependency-verification-1.3.xsd">
    <configuration>
        <!-- verify .pom and .module files -->
        <verify-metadata>true</verify-metadata>
        <!-- verify .asc PGP files that come with the artifacts -->
        <verify-signatures>true</verify-signatures>
        <!-- use human readable keyring format -->
        <keyring-format>armored</keyring-format>
        <!-- read keys in a local file, fewer requests to network -->
        <key-servers enabled="false">
            <key-server uri="https://keyserver.ubuntu.com"/>
            <key-server uri="https://keys.openpgp.org"/>
        </key-servers>
    </configuration>
    <components>
    </components>
</verification-metadata>

這只是起點,很快就會更新。

執行 ./gradlew assembleDebug,看看這會如何變更建構作業。您會看到類似以下的訊息

* What went wrong:
Error resolving plugin [id: 'com.android.application', version: '8.7.3', apply: false]
> Dependency verification failed for configuration 'detachedConfiguration1'
  One artifact failed verification: com.android.application.gradle.plugin-8.7.3.pom ...
  This can indicate that a dependency has been compromised ...
  
  Open this report for more details: .../dependency-verification-report.html

Gradle 會告知您,您正在匯入未明確核准的依附元件版本。

啟動總和檢查碼和簽章資料

您可以啟動初始信任金鑰和元件的設定。這個程序會收集專案使用的所有程式庫目前的簽章和總和檢查碼。

執行以下命令,產生初始中繼資料

./gradlew --write-verification-metadata pgp,sha256 --export-keys help

這個指令會指示 Gradle 為此專案中使用的所有依附元件建立 PGP 金鑰和備用總和檢查碼清單。您會看到 verification-metadata.xml 有變更,其中包含多個項目,例如:

<trusted-key id="8461EFA0E74ABAE010DE66994EB27DB2A3B88B8B">
    <trusting group="androidx.activity"/>
</trusted-key>

這會告訴 Gradle,如果 Gradle 看到 Maven 群組 androidx.activity 的依附元件,就會確保隨附的 .asc 檔案 (儲存在存放區中的簽名) 與該鍵相符。

引導程序也會產生 gradle/verification-keyring.keys,其中包含版本使用的公開 PGP 金鑰。將這兩個檔案都提交至版本追蹤系統。日後若有任何變更會修改 verification-metadata.xmlverification-keyring.keys,請務必仔細審查。

從信任的金鑰中移除版本

在程式庫的不同版本之間,簽署金鑰幾乎不會變更。gradle/verification-metadata.xml 檔案中產生的資料包含版本詳細資料,因此您必須為每個新的依附元件版本重新新增關鍵資訊。

如要避免這種情況,並指定金鑰套用至程式庫的所有版本,請移除版本規格。

在 Android Studio 編輯器中,使用規則運算式依序選取「Edit」>「Find」>「Replace...」,取代信任金鑰的所有版本規格。

  • 來源:<trusted-key(.*) version=\".*\"/>
  • 收款人:<trusted-key$1/>

Android Studio 同步處理

到目前為止,您的指令列建構作業都正常運作,但如果您嘗試在 Android Studio 中進行同步處理,就會看到類似以下的錯誤訊息:

A build operation failed.
    Dependency verification failed for configuration ':app:detachedConfiguration3'
One artifact failed verification: gradle-8.10.2-src.zip (gradle:gradle:8.10.2) from repository Gradle distributions
If the artifacts are trustworthy, you will need to update the gradle/verification-metadata.xml file. For more on how to do this, please refer to https://docs.gradle.org/8.10.2/userguide/dependency_verification.html#sec:troubleshooting-verification in the Gradle documentation.

Android Studio 想要下載 Gradle 來源 (以及其他來源和文件)。修正這個問題最簡單的方法,就是信任所有來源和 Javadoc。在 gradle/verification-metadata.xml 中新增 <trusted-artifacts>

<verification-metadata ...>
   <configuration>
      <trusted-artifacts>
         <trust file=".*-javadoc[.]jar" regex="true"/>
         <trust file=".*-sources[.]jar" regex="true"/>
         <trust group="gradle" name="gradle"/>
      </trusted-artifacts>
      ...
  </configuration>
</verification-metadata>

您的建構作業現在可透過指令列和 Android Studio 正常運作。