---
# System prepended metadata

title: '第 4 篇:Google Play Integrity 深入解析'
tags: [AppCheck系列]

---

# 第 4 篇:Google Play Integrity 深入解析

## 前言:Android 平台的完整性驗證

在上一篇,我們了解了 reCAPTCHA 如何提供通用的人機識別。但是,reCAPTCHA 無法回答一個關鍵問題:**這個請求真的來自未被篡改的正版應用程式嗎?**

Google Play Integrity 專門解決這個問題,提供 **Android 平台專屬的應用程式與裝置完整性驗證**。

## Play Integrity 的核心價值

### 為什麼需要 Play Integrity?

```
reCAPTCHA 無法防範的攻擊:
├── 反編譯應用程式
├── 修改 APK 程式碼
├── 在模擬器上執行
├── 在 Root 裝置上繞過檢查
└── 使用破解工具修改應用行為

Play Integrity 可以偵測:
├── ✅ 應用程式是否來自 Play Store
├── ✅ 應用程式是否被篡改
├── ✅ 執行環境是否為真實 Android 裝置
├── ✅ 裝置是否通過 Google 認證
└── ✅ 裝置上是否有惡意軟體
```

### 與 reCAPTCHA 的差異

| 特徵 | reCAPTCHA | Play Integrity |
|------|-----------|----------------|
| 驗證對象 | 使用者行為 | 應用程式 + 裝置 |
| 防護重點 | 機器人、腳本 | 破解、模擬器 |
| 平台支援 | 跨平台 | 僅 Android |
| 驗證深度 | 行為分析 | 硬體 + 軟體完整性 |
| 依賴 | Google 服務 | Google Play Services |

## Play Integrity 核心概念

### 五大驗證維度

Play Integrity 從五個維度全面驗證請求的可信度:

#### 1. Request Details (請求詳情)

```
驗證內容:
├── Request Package Name
│   └── 確認請求來自正確的應用程式包名
├── Nonce
│   └── 防止重放攻擊的一次性隨機值
└── Timestamp
    └── 請求產生的時間戳記

目的:
├── 防止跨應用程式攻擊
├── 確保請求的新鮮度
└── 防止重放攻擊
```

**重要概念:**
- **Nonce (Number used once，一次性隨機數)**:伺服器產生的隨機值,確保每個 token 唯一
- 伺服器必須追蹤並核銷使用過的 nonce

#### 2. App Integrity (應用程式完整性)

```
應用程式完整性判定:
├── PLAY_RECOGNIZED
│   ├── 應用程式來自 Google Play
│   ├── 簽章與 Play Store 版本一致
│   └── 未被篡改或修改
│
├── UNRECOGNIZED_VERSION
│   ├── 應用程式包名正確
│   ├── 但版本不在 Play Store 中
│   └── 可能是測試版或舊版本
│
└── UNEVALUATED
    └── 無法評估(網路問題等)
```

**典型場景:**
- `PLAY_RECOGNIZED`:正常使用者從 Play Store 安裝
- `UNRECOGNIZED_VERSION`:開發者測試版、企業內部版
- 被拒絕:破解版、反編譯後重新打包的版本

#### 3. Device Integrity (裝置完整性)

這是 Play Integrity 最強大的部分,提供多層次的裝置完整性評估:

```
裝置完整性等級:
├── MEETS_DEVICE_INTEGRITY (最高等級)
│   ├── Google 認證的 Android 裝置
│   ├── 通過 Android 相容性測試
│   ├── 未被 Root
│   └── 系統完整性良好
│
├── MEETS_BASIC_INTEGRITY (基本等級)
│   ├── 可能不是 Google 認證裝置
│   ├── 或是 Google 認證但被修改
│   └── 基本的 Android 系統相容性
│
├── MEETS_STRONG_INTEGRITY (硬體支援等級)
│   ├── 具有硬體安全模組(HSM)
│   ├── 支援 Hardware-backed Keystore
│   └── 提供最高等級的安全保證
│
└── MEETS_VIRTUAL_INTEGRITY (虛擬環境)
    └── Google 官方模擬器(用於開發測試)
```

**重要概念:**

**MEETS_DEVICE_INTEGRITY:**
- 代表標準的 Android 生態系統
- 大部分正常使用者的裝置
- 最常見的完整性等級

**MEETS_BASIC_INTEGRITY:**
- 可能的情況:
  - 中國品牌手機(沒有 Google 認證)
  - Root 過的裝置
  - 自定義 ROM
  - 修改過的系統

**MEETS_STRONG_INTEGRITY:**
- 高階裝置才有
- 使用硬體安全晶片
- 提供 hardware-backed attestation

#### 4. Account Details (帳號詳情)

```
帳號授權狀態:
├── LICENSED
│   ├── 應用程式已透過 Play Store 取得
│   └── 對免費 App:表示已下載安裝
│   └── 對付費 App:表示已購買
│
├── UNLICENSED
│   └── 應用程式未透過 Play Store 合法取得
│
└── UNEVALUATED
    └── 無法評估授權狀態
```

**使用場景:**
- 防止盜版
- 驗證付費應用程式的授權
- 檢測側載(Sideloading)安裝

#### 5. Environment Details (環境詳情)

Environment Details 評估裝置的執行環境安全性,包含兩個主要欄位:

**可能的判定值:**

```
environmentDetails {
  playProtectVerdict: string    // Play Protect 狀態
  appAccessRiskVerdict: string  // 應用程式存取風險
}
```

**A. Play Protect Verdict (Play Protect 狀態)**

```
Play Protect 常見判定值（示意）:
├── PLAY_PROTECT_VERDICT_UNSPECIFIED
│   └── 未指定或無法判定
├── NO_ISSUES
│   └── Play Protect 已啟用且未發現問題
├── NO_DATA
│   └── 無法取得 Play Protect 資訊
├── MEDIUM_RISK
│   └── Play Protect 偵測到中度風險
└── HIGH_RISK
    └── Play Protect 偵測到高度風險

註：實際判定值以 Google 官方 SDK 回應為準，可能隨版本變動
```

**Play Protect 功能:**
- Google 內建的惡意軟體掃描服務
- 持續監控已安裝的應用程式
- 偵測潛在有害應用程式 (PHA)

**B. App Access Risk Verdict (應用程式存取風險)**

App Access Risk 會回傳 `appsDetected` 陣列,包含偵測到的應用程式類型。

**判定值分類:**

根據應用程式來源,判定值會有不同前綴:
- `KNOWN_*`: Google Play 或系統預載應用程式
- `UNKNOWN_*`: 其他來源安裝的應用程式

```
可能的判定值:
├── KNOWN_INSTALLED / UNKNOWN_INSTALLED
│   └── 偵測到已安裝的應用程式
├── KNOWN_CAPTURING / UNKNOWN_CAPTURING
│   └── 有執行中應用程式可查看螢幕畫面
├── KNOWN_CONTROLLING / UNKNOWN_CONTROLLING
│   └── 有執行中應用程式可控制裝置或攔截輸入/輸出
├── KNOWN_OVERLAYS / UNKNOWN_OVERLAYS
│   └── 有執行中應用程式可顯示疊加畫面
└── {} (空白)
    └── 未符合評估條件 (如裝置可信度不足)
```

**判定結果範例:**

| appsDetected | 意義 |
|-------------|------|
| `["KNOWN_INSTALLED"]` | 只有 Play 或系統應用,無風險 |
| `["KNOWN_INSTALLED", "UNKNOWN_CAPTURING"]` | 有其他應用正在擷取螢幕或輸入 |
| `["KNOWN_CONTROLLING", "UNKNOWN_INSTALLED"]` | 有 Play 應用正在控制裝置,且有其他來源應用 |
| `{}` | 無法評估 (裝置可信度不足等) |

**重要注意事項:**
- 經過 Google Play 無障礙功能審查的應用會被排除
- 工作資料夾中的應用一律標記為 `UNKNOWN_*`
- 空白結果可能原因:裝置可信度不足、Android 版本過舊、Play Store 版本過舊等

**使用建議:**
- 根據業務需求決定對不同風險等級的處理方式
- `CAPTURING` 和 `CONTROLLING` 應特別注意,可能影響敏感操作
- 可結合其他判定維度綜合評估

## Play Integrity 工作流程

### 基本流程

```mermaid
sequenceDiagram
    participant A as Android App
    participant P as Play Integrity API
    participant S as Your Server
    participant Auth as Google Auth API
    participant G as Google Verdict API

    A->>S: 請求 nonce
    S->>A: 返回 nonce
    A->>P: requestIntegrityToken(nonce)
    P->>G: 收集裝置資訊
    G->>G: 評估完整性
    G->>P: 返回加密 token
    P->>A: IntegrityToken
    A->>S: 提交 token

    Note over S,Auth: 第一步:取得授權 Token
    S->>Auth: 請求 OAuth 2.0 Access Token
    Auth->>S: 返回 Access Token

    Note over S,G: 第二步:解密並取得判定
    S->>G: 解密 token (帶 Access Token)
    G->>S: 返回 verdict (判定結果)

    S->>S: 根據判定做決策
    S->>A: 返回結果
```

**關鍵步驟說明:**

1. **Nonce 生成:**
   - 伺服器產生隨機 nonce
   - 綁定到特定請求
   - 防止 token 被重複使用

2. **Token 請求:**
   - App 呼叫 Play Integrity API
   - 傳入 nonce
   - API 收集裝置和應用資訊

3. **Token 加密:**
   - Google 評估完整性
   - 生成加密的 token
   - Token 包含所有判定結果

4. **後端兩步驟 API 驗證:**

   **步驟 1 - 取得授權 Token:**
   - 使用 Service Account 憑證
   - 呼叫 Google OAuth 2.0 API
   - 取得短期有效的 Access Token
   - Endpoint: `https://oauth2.googleapis.com/token`

   **步驟 2 - 解密並取得判定:**
   - 使用步驟 1 的 Access Token
   - 呼叫 Play Integrity API
   - 傳入加密的 Integrity Token
   - Endpoint: `https://playintegrity.googleapis.com/v1/{package}/decodeIntegrityToken`
   - 獲得五大維度的判定結果

   **為什麼需要兩步驟?**
   - 安全性考量:Access Token 短期有效(通常 1 小時)
   - 權限隔離:Service Account 可精細控制權限
   - 防止濫用:每個 API 呼叫都需要有效授權

### Token 的特性

```
Integrity Token 特性:
├── 加密保護
│   └── 只有 Google 和您的伺服器能解密
├── 單次使用
│   └── Nonce 機制防止重放
├── 有時間限制
│   └── 通常幾分鐘內有效
└── 包含完整資訊
    └── 五大維度的判定結果
```

## 實作決策邏輯

### 如何解讀判定結果?

不同的業務場景需要不同的信任等級:

```
場景一:一般功能訪問
可接受的判定:
├── App Integrity: PLAY_RECOGNIZED
├── Device Integrity: MEETS_DEVICE_INTEGRITY 或 MEETS_BASIC_INTEGRITY
└── 決策: 允許

場景二:敏感操作(如支付)
嚴格要求:
├── App Integrity: 必須 PLAY_RECOGNIZED
├── Device Integrity: 必須 MEETS_DEVICE_INTEGRITY 或 MEETS_STRONG_INTEGRITY
├── Account Details: LICENSED
└── 決策: 拒絕任何不符合的情況

場景三:開發測試環境
寬鬆設定:
├── App Integrity: UNRECOGNIZED_VERSION (允許)
├── Device Integrity: MEETS_VIRTUAL_INTEGRITY (允許模擬器)
└── 決策: 用於開發階段
```

### 分層處理策略

```
根據完整性等級分層處理:

高信任等級:
├── PLAY_RECOGNIZED + MEETS_DEVICE_INTEGRITY
└── 動作: 完全訪問

中信任等級:
├── PLAY_RECOGNIZED + MEETS_BASIC_INTEGRITY
└── 動作: 允許但監控,限制敏感功能

低信任等級:
├── UNRECOGNIZED_VERSION
└── 動作: 限制功能,要求額外驗證

拒絕:
├── 無任何有效的 integrity 判定
└── 動作: 拒絕請求
```

## 常見挑戰與考量

### 1. Root 裝置處理

```
Root 裝置的判定:
├── 通常無法通過 MEETS_DEVICE_INTEGRITY
├── 可能通過 MEETS_BASIC_INTEGRITY
└── 完全無法通過 MEETS_STRONG_INTEGRITY

處理策略:
├── 嚴格應用: 拒絕所有 Root 裝置
├── 彈性應用: 允許但限制功能
└── 考量: 部分合法使用者可能使用 Root 裝置
```

**建議:**
- 金融、支付類應用:嚴格拒絕
- 一般應用:可以允許但監控
- 遊戲應用:視反作弊需求決定

### 2. 中國市場考量

```
中國市場挑戰:
├── 許多裝置沒有 Google Play Services
├── 無法使用 Play Integrity
└── 需要替代方案

替代策略:
├── 使用中國本地的完整性驗證方案
├── 或降級使用其他驗證機制
└── reCAPTCHA + 自定義檢測
```

### 3. 開發與測試環境

```
開發環境處理:
├── Debug 版本通常是 UNRECOGNIZED_VERSION
├── 模擬器返回 MEETS_VIRTUAL_INTEGRITY
└── 需要設定不同的驗證邏輯

建議做法:
├── 環境判斷
│   ├── Production: 嚴格驗證
│   ├── Staging: 中等驗證
│   └── Development: 寬鬆驗證
└── 使用 Build Variant 區分
```

## 與其他機制的配合

### 三層防護中的角色

```
第一層: reCAPTCHA
├── 防護: 機器人、腳本攻擊
└── 所有請求都要通過

第二層: Play Integrity (Android)
├── 防護: 破解應用、模擬器、惡意環境
├── 高風險操作必須通過
└── 提供裝置和應用完整性保證

第三層: 業務邏輯驗證
└── 應用程式特定的驗證規則
```

### 組合使用範例

```
使用者登入流程:
1. reCAPTCHA 檢查 (人機識別)
   ├── 分數 < 0.5: 拒絕
   └── 分數 >= 0.5: 繼續

2. Play Integrity 檢查 (完整性)
   ├── App != PLAY_RECOGNIZED: 拒絕
   ├── Device != MEETS_DEVICE_INTEGRITY: 額外驗證
   └── 通過: 允許登入

3. 業務邏輯檢查
   ├── 帳號狀態
   ├── 登入歷史
   └── 異常模式偵測
```

## 總結

### Play Integrity 的核心價值

**優勢:**  

✅ 強大的應用程式完整性驗證  
✅ 多層次的裝置完整性評估  
✅ 硬體級安全支援(STRONG_INTEGRITY)  
✅ 整合 Google Play 生態系  
✅ 偵測 Root、破解、模擬器  
✅ Play Protect 惡意軟體防護

**適用場景:**
- Android 應用程式防護
- 防止破解和逆向工程
- 遊戲反作弊
- 金融應用安全
- 付費內容保護

**局限性:**  

❌ 僅限 Android 平台  
❌ 需要 Google Play Services  
❌ 中國市場無法使用  
❌ Root 裝置可能被拒絕(影響部分合法使用者)  
❌ 需要較複雜的判定邏輯

### 關鍵概念回顧

1. **五大驗證維度**:全面評估請求可信度
2. **多層次完整性等級**:DEVICE/BASIC/STRONG/VIRTUAL
3. **Nonce 機制**:防止 token 重放攻擊
4. **分層處理**:根據不同信任等級採取不同策略
5. **環境感知**:開發、測試、生產環境不同處理

### 與 Apple App Attest 的對應

Play Integrity 和 Apple App Attest 解決相同的問題,但實作方式不同:

| 特徵 | Play Integrity | App Attest |
|------|----------------|------------|
| 平台 | Android | iOS |
| 核心 | Play Services | Secure Enclave |
| 完整性等級 | 多層次(4種) | 二元(通過/失敗) |
| 硬體支援 | STRONG_INTEGRITY | 強制硬體綁定 |
| 實作複雜度 | 中 | 高 |

---

在下一篇文章中,我們將深入探討 **Apple App Attest**,了解 iOS 平台如何利用硬體安全模組提供最高等級的完整性保證。

## 參考資源

- [Play Integrity API 官方文件](https://developer.android.com/google/play/integrity)
- [Integrity Verdict 解讀指南](https://developer.android.com/google/play/integrity/verdict)
- [Play Integrity 最佳實務](https://developer.android.com/google/play/integrity/overview#best-practices)
- [Classic API 遷移指南](https://developer.android.com/google/play/integrity/migrate)
