作者 / Oscar Rodriguez, Developer Relations Engineer
我們近期發(fā)布了 Play Integrity API,希望幫助開發(fā)者們保護(hù)自己的應(yīng)用和游戲,使其免受可能存在風(fēng)險(xiǎn)的欺詐性互動(dòng) (例如欺騙和未經(jīng)授權(quán)的訪問) 的危害,讓您能夠采取適當(dāng)措施來防范攻擊并減少濫用行為。

除了與應(yīng)用完整性、設(shè)備完整性和許可信息相關(guān)的有用信號(hào)外,Play Integrity API 還提供了一個(gè)簡(jiǎn)單卻非常實(shí)用的功能,即 “nonce”。如果使用得當(dāng),開發(fā)者可以進(jìn)一步加強(qiáng) Play Integrity API 的現(xiàn)有保護(hù)措施,并降低特定類型攻擊的風(fēng)險(xiǎn),例如中間人 (PITM) 篡改攻擊和重放攻擊。
在這篇文章中,我們將深入介紹什么是 nonce、它的工作原理,以及如何使用 nonce 字段來進(jìn)一步保護(hù)您的應(yīng)用和游戲。

什么是 nonce?

在密碼學(xué)和安全工程學(xué)中,nonce (number once) 是一個(gè)在安全通信中僅能被使用一次的數(shù)字。nonce 用途廣泛,如身份驗(yàn)證、數(shù)據(jù)加密和哈希處理等。

在 Play Integrity API 中,nonce 是您在調(diào)用 API 完整性檢查前設(shè)置的不透明 Base64 編碼二進(jìn)制 blob,并通過被簽名的響應(yīng)中原樣返回。根據(jù)創(chuàng)建和驗(yàn)證 nonce 的方式,您可以使用它來進(jìn)一步加強(qiáng) Play Integrity API 的現(xiàn)有保護(hù)措施,并緩解特定類型的攻擊,例如中間人 (PITM) 篡改攻擊和重放攻擊。

除了在被簽名的響應(yīng)中按原樣返回 nonce,Play Integrity API 不會(huì)對(duì) nonce 實(shí)際數(shù)據(jù)進(jìn)行任何處理,因此您可以設(shè)置任意值,只要它是一個(gè)有效的 Base64 值即可。也就是說,為了對(duì)響應(yīng)進(jìn)行數(shù)字簽名,nonce 值將被發(fā)送到 Google 服務(wù)器,因此請(qǐng)勿將 nonce 設(shè)置為任何類型的個(gè)人身份信息 (PII),例如用戶姓名、電話或電子郵件地址。

設(shè)置 nonce

將您的應(yīng)用設(shè)置為使用 Play Integrity API?之后,您可以使用?setNonce()?方法,或其適當(dāng)?shù)淖凅w設(shè)置 nonce,這些變體適用于 API 的?Kotlin、Java、Unity 和 Native 版本。

Kotlin:?

val nonce: String = ...

// 創(chuàng)建 manager 的實(shí)例
val integrityManager =
IntegrityManagerFactory.create(applicationContext)

// 通過 nonce 獲取完整性令牌
val integrityTokenResponse: Task<IntegrityTokenResponse> =
integrityManager.requestIntegrityToken(
IntegrityTokenRequest.builder()
.setNonce(nonce) // 設(shè)置 nonce
.build())

Java:?

String nonce = ...

// 創(chuàng)建 manager 的實(shí)例
IntegrityManager integrityManager =
IntegrityManagerFactory.create(getApplicationContext());

// 通過 nonce 獲取完整性令牌
Task<IntegrityTokenResponse> integrityTokenResponse =
integrityManager
.requestIntegrityToken(
IntegrityTokenRequest.builder()
.setNonce(nonce) // 設(shè)置 nonce
.build());

Unity:?

string nonce = ...

// 創(chuàng)建 manager 的實(shí)例
var integrityManager = new IntegrityManager();

// 通過 nonce 獲取完整性令牌
var tokenRequest = new IntegrityTokenRequest(nonce);
var requestIntegrityTokenOperation =
integrityManager.RequestIntegrityToken(tokenRequest);

Native:?

// 創(chuàng)建 IntegrityTokenRequest 對(duì)象
const char* nonce = ...
IntegrityTokenRequest* request;
IntegrityTokenRequest_create(&request);
IntegrityTokenRequest_setNonce(request, nonce); // 設(shè)置 nonce
IntegrityTokenResponse* response;
IntegrityErrorCode error_code =
IntegrityManager_requestIntegrityToken(request, &response);

驗(yàn)證 nonce

Play Integrity API 的響應(yīng)以?JSON 網(wǎng)絡(luò)令牌 (JWT)?的形式返回,其負(fù)載為純文本 JSON,格式如下:?

您可以在?requestDetails?結(jié)構(gòu)中查看 nonce,其格式如下:?

requestDetails: {
requestPackageName: "...",
nonce: "...",
timestampMillis: ...
}

nonce?字段的值應(yīng)與您之前調(diào)用 API 傳過去的值完全匹配。此外,由于 nonce 值位于 Play Integrity API 的加密簽名響應(yīng)中,收到響應(yīng)之后是無法改變它的。通過這些屬性,您就可以使用 nonce 進(jìn)一步保護(hù)您的應(yīng)用。

保護(hù)重要操作

試想這個(gè)場(chǎng)景,一名攻擊者正在試圖惡意將玩家得分虛報(bào)給游戲服務(wù)端。這種情況下,設(shè)備和應(yīng)用都是完整的,但攻擊者仍可以通過代理服務(wù)器或者虛擬專用網(wǎng)絡(luò)查看并修改與游戲服務(wù)器之間的通信數(shù)據(jù)流,從而達(dá)到虛報(bào)分?jǐn)?shù)的目的。
在這種情況下,僅調(diào)用 Play Integrity API 不足以保護(hù)應(yīng)用:?設(shè)備沒有被破解、應(yīng)用也是合法的,因此該操作可以通過 Play Integrity API 的所有檢查。
但您可以使用 Play Integrity API 的 nonce 來保護(hù)這種報(bào)告游戲分?jǐn)?shù)的特定高價(jià)值操作,即在 nonce 中編碼操作的值。實(shí)現(xiàn)方法如下:?

  1. 用戶發(fā)起重要操作;
  2. 應(yīng)用準(zhǔn)備好要保護(hù)的消息,例如 JSON 格式的消息;
  3. 應(yīng)用計(jì)算要保護(hù)的消息的加密哈希值。例如,使用 SHA-256 或 SHA-3-256 哈希算法;
  4. 應(yīng)用調(diào)用 Play Integrity API,并調(diào)用 setNonce() 以將 nonce 字段設(shè)置為在上一步計(jì)算的加密哈希值;
  5. 應(yīng)用將要保護(hù)的消息以及 Play Integrity API 的簽名結(jié)果發(fā)送給服務(wù)器;
  6. 應(yīng)用服務(wù)器驗(yàn)證其收到的消息的加密哈希值是否與簽名結(jié)果中的 nonce 字段值匹配,并拒絕任何不匹配的結(jié)果。

下面的序列圖說明了相關(guān)步驟:?

只要受保護(hù)的原始消息與簽名結(jié)果一起發(fā)送,且服務(wù)器和客戶端都使用完全相同的機(jī)制來計(jì)算 nonce,通過這樣的方式來保證消息不會(huì)被篡改。
請(qǐng)注意,在上述場(chǎng)景下,安全模型的有效性僅限攻擊行為發(fā)生在網(wǎng)絡(luò)中 (而不是發(fā)生在設(shè)備或應(yīng)用),因此驗(yàn)證 Play Integrity API 提供的設(shè)備和應(yīng)用完整性信號(hào)也尤為重要。

防范重放攻擊


我們?cè)僭囅肓硗庖环N場(chǎng)景,一個(gè)應(yīng)用或游戲使用了 Play Integrity API 來保護(hù)自己的 C/S 架構(gòu),但攻擊者試圖通過用已破解的設(shè)備與服務(wù)端交互,并且不讓服務(wù)器端監(jiān)測(cè)到。
若要 “達(dá)成” 這種攻擊目標(biāo),攻擊者會(huì)首先在合法的設(shè)備上讓應(yīng)用與 Play Integrity API 進(jìn)行交互,并獲得已經(jīng)簽名的響應(yīng)內(nèi)容,然后再在破解設(shè)備上運(yùn)行應(yīng)用并攔截 Play Integrity API 的調(diào)用,使用此前記錄的、已獲得簽名的響應(yīng)內(nèi)容進(jìn)行響應(yīng),這樣一來就不會(huì)執(zhí)行完整性檢查了。
由于已簽名的響應(yīng)并未以任何方式被更改,所以數(shù)字簽名看似正常,應(yīng)用服務(wù)器就會(huì)誤以為它正在與合法設(shè)備進(jìn)行通信。我們將此稱為重放攻擊
抵御此類攻擊的第一道防線是驗(yàn)證簽名響應(yīng)中的?timestampMillis?字段。這個(gè)字段包含創(chuàng)建響應(yīng)時(shí)的時(shí)間戳,即使在數(shù)字簽名通過驗(yàn)證的情況下,也能用于服務(wù)器端檢測(cè)是否為可疑的舊響應(yīng)。

也就是說,應(yīng)用服務(wù)器也可以利用 Play Integrity API 中的 nonce,為每個(gè)響應(yīng)分配一個(gè)唯一值,并驗(yàn)證該響應(yīng)是否與之前設(shè)置的唯一值匹配。實(shí)現(xiàn)方法如下: 

  1. 服務(wù)器以攻擊者無法預(yù)測(cè)的方式創(chuàng)建全局唯一值。例如,128 位或位數(shù)更多的加密安全隨機(jī)數(shù);
  2. 應(yīng)用調(diào)用 Play Integrity API,并將 nonce 字段設(shè)置為應(yīng)用服務(wù)器接收的唯一值;
  3. 應(yīng)用將 Play Integrity API 的簽名結(jié)果發(fā)送到服務(wù)器;
  4. 服務(wù)器驗(yàn)證簽名結(jié)果中的 nonce 字段是否與之前生成的唯一值匹配,并拒絕所有不匹配的結(jié)果。

下面的序列圖說明了相關(guān)步驟:?

實(shí)現(xiàn)上述流程后,每次服務(wù)器要求應(yīng)用調(diào)用 Play Integrity API 時(shí),它都會(huì)使用不同的全局唯一值,因此只要攻擊者無法預(yù)測(cè)該值,nonce 與預(yù)期值不匹配,就無法重用之前的響應(yīng)。

結(jié)合兩種保護(hù)措施


雖然上述兩種機(jī)制的工作方式不同,但如果應(yīng)用同時(shí)需要兩種保護(hù),則可以將這兩種機(jī)制組合在一個(gè) Play Integrity API 調(diào)用中,例如,將兩種保護(hù)措施的結(jié)果附加到一個(gè)更大的 Base64 nonce 中。結(jié)合兩種保護(hù)措施的實(shí)現(xiàn)方法如下:?

  1. 用戶發(fā)起重要操作;
  2. 應(yīng)用要求服務(wù)器提供一個(gè)標(biāo)識(shí)請(qǐng)求的唯一值;
  3. 應(yīng)用服務(wù)器生成全局唯一值,防止攻擊者做出預(yù)測(cè)。例如,您可以使用加密安全的隨機(jī)數(shù)生成器創(chuàng)建此類值。我們建議創(chuàng)建不小于 128 位的值;
  4. 應(yīng)用服務(wù)器向應(yīng)用發(fā)送全局唯一值;
  5. 應(yīng)用準(zhǔn)備好要保護(hù)的消息,例如 JSON 格式的消息;
  6. 應(yīng)用計(jì)算要保護(hù)的消息的加密哈希值。例如,使用 SHA-256 或 SHA-3-256 哈希算法;
  7. 應(yīng)用通過附加從應(yīng)用服務(wù)器收到的唯一值以及要保護(hù)的消息的哈希值來創(chuàng)建一個(gè)字符串;
  8. 應(yīng)用調(diào)用 Play Integrity API,并調(diào)用 setNonce() 以將 nonce 字段設(shè)置為在上一步中創(chuàng)建的字符串;
  9. 應(yīng)用將要保護(hù)的消息以及 Play Integrity API 的簽名結(jié)果發(fā)送給服務(wù)器;
  10. 應(yīng)用服務(wù)器拆分 nonce 字段的值,然后驗(yàn)證消息的加密哈希值以及之前生成的唯一值是否與預(yù)期值相匹配,并拒絕任何不匹配的結(jié)果。

下面的序列圖說明了相關(guān)步驟:?

如果您的應(yīng)用會(huì)處理敏感數(shù)據(jù),或容易被濫用,我們建議您考慮借助 Play Integrity API,采取相關(guān)措施緩解威脅。

本文章轉(zhuǎn)載微信公眾號(hào)@Android 開發(fā)者

上一篇:

一文帶你了解大模型——智能體(Agent)

下一篇:

HTTP API 設(shè)計(jì)指南
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊(cè)

多API并行試用

數(shù)據(jù)驅(qū)動(dòng)選型,提升決策效率

查看全部API→
??

熱門場(chǎng)景實(shí)測(cè),選對(duì)API

#AI文本生成大模型API

對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)

#AI深度推理大模型API

對(duì)比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)