TrustedTime API — 提供可靠時間來源的全新解決方案
近期,Android Developers 團隊發表了一篇文章,介紹一項全新的 API:TrustedTime API。這個 API 的核心目標在於為應用程式提供一個安全、可靠的時間來源,避免因設備本地時鐘被篡改而產生的安全風險。以下整理了文章中的重點內容與技術細節,讓我們一起了解這項創新功能。
TrustedTime 怎麼運作?
新的 API 利用 Google 的安全基礎設施,為您的應用程式提供一個可信賴的時間來源。TrustedTime 定期將其時鐘與 Google 的伺服器同步,而這些伺服器具備極高精準度的時間來源,因此您不需要每次查詢當前網路時間時都發送伺服器請求。此外,我們還整合了一個獨特的模型來計算裝置時鐘的漂移,這將告知您在網路同步之間何時時間可能不準確。
為什麼準確的時間來源很重要?
許多應用程式依賴設備的時鐘來提供各種功能。然而,使用者可能會有意或無意地更改設備的時間設定,從而影響應用程式獲取的時間。這可能導致以下問題:
- 數據不一致:如果應用程式依賴按時間順序排列的事件,使用者修改設備時間可能會導致數據損壞。TrustedTime 可提供可信賴的時間來源,以降低這種風險。
- 安全漏洞:基於時間的安全機制(如一次性密碼或限時存取控制)需要未被篡改的時間來源才能有效運作。
- 不可靠的排程:依賴準確時間的應用程式(如行事曆或提醒應用)可能因設備時鐘(如 Unix 時間戳記)不準確而發生故障。
- 時間不精確:設備內部時鐘可能會因溫度、休眠模式、電池電量等因素而產生時間漂移。這對於需要高精度的應用程式而言可能會造成問題。TrustedTime API 會提供時間戳記的誤差估算,確保應用程式的時間敏感操作能夠正確執行。
- 設備間時間不一致:多設備場景(如遊戲或協作應用)中,設備之間的時間不一致可能會造成問題。TrustedTime API 可確保所有設備的時間保持一致,提升使用者體驗。
- 不必要的電量與數據消耗:相比於每次應用程式需要當前時間時都向 NTP 伺服器發送請求,TrustedTime 更加高效。它會定期與時間伺服器同步,並以同步後的時間作為參考點,透過設備內部時鐘計算當前時間。這種方法可降低網路使用量並提升應用程式效能,特別是對於需要頻繁檢查時間的應用程式而言。
TrustedTime 的應用場景
TrustedTime API 可提升應用程式的可靠性與安全性,適用於多種情境,例如:
- 金融應用:確保交易時間戳即使在設備離線時仍然準確,防止詐欺與爭議。
- 遊戲:防止使用者透過修改設備時間來操控遊戲時鐘,確保公平競技。
- 限時優惠:確保促銷與優惠活動在正確時間到期,而不受使用者設備設定影響。
- 電子商務:精確追蹤訂單處理與配送時間。
- 數位內容授權:強制執行基於時間的數位內容限制,例如租賃或訂閱服務。
- 物聯網 (IoT) 設備:確保多個設備之間的時鐘同步,以保持數據記錄與控制的一致性。
- 生產力應用:準確記錄雲端文件的變更時間,以確保文件歷史記錄的可靠性。
開始使用 TrustedTime API
TrustedTime API 建立在 Google Play 服務之上,對於大多數 Android 開發者來說,整合過程十分順暢。
最簡單的整合方式是在應用程式生命週期的早期初始化 TrustedTimeClient,例如在 Application 類別的 onCreate() 方法中初始化。以下範例使用 Hilt 進行依賴注入,使時間客戶端可在整個應用程式中供各個元件使用。
[選擇性] 設定依賴注入
// TrustedTimeClientAccessor.kt import com.google.android.gms.tasks.Task import com.google.android.gms.time.TrustedTimeClient interface TrustedTimeClientAccessor { fun createClient(): Task<TrustedTimeClient> } // TrustedTimeModule.kt @Module @InstallIn(SingletonComponent::class) class TrustedTimeModule { @Provides fun provideTrustedTimeClientAccessor( @ApplicationContext context: Context ): TrustedTimeClientAccessor { return object : TrustedTimeClientAccessor { override fun createClient(): Task<TrustedTimeClient> { return TrustedTime.createClient(context) } } } }
// TrustedTimeDemoApplication.kt @HiltAndroidApp class TrustedTimeDemoApplication : Application() { @Inject lateinit var trustedTimeClientAccessor: TrustedTimeClientAccessor var trustedTimeClient: TrustedTimeClient? = null private set override fun onCreate() { super.onCreate() trustedTimeClientAccessor.createClient().addOnCompleteListener { task -> if (task.isSuccessful) { // Stash the client trustedTimeClient = task.result } else { // Handle error, maybe retry later val exception = task.exception } } // To use Kotlin Coroutine, you can use the await() method, // see https://developers.google.com/android/guides/tasks#kotlin_coroutine for more info. } } NOTE: If you don't use dependency injection in your app. You can simply call `TrustedTime.createClient(context)` instead of using a TrustedTimeClientAccessor.
TrustedTimeClient
// Retrieve the TrustedTimeClient from your application class val myApp = applicationContext as TrustedTimeDemoApplication // In this example, System.currentTimeMillis() is used as a fallback if the // client is null (i.e. client creation task failed) or when there is no time // signal available. You may not want to do this if using the system clock is // not suitable for your use case. val currentTimeMillis = myApp.trustedTimeClient?.computeCurrentUnixEpochMillis() ?: System.currentTimeMillis() // trustedTimeClient.computeCurrentInstant() can be used if Instant is // preferred to long for Unix epoch times and you are able to use the APIs.
@AndroidEntryPoint class MainActivity : AppCompatActivity() { @Inject lateinit var trustedTimeAccessor: TrustedTimeAccessor private var trustedTimeClient: TrustedTimeClient? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ... trustedTimeAccessor.createClient().addOnCompleteListener { task -> if (task.isSuccessful) { // Stash the client trustedTimeClient = task.result } else { // Handle error, maybe retry later or use another time source. val exception = task.exception } } } private fun getCurrentTimeInMillis() : Long? { return trustedTimeClient?.computeCurrentUnixEpochMillis() } }
TrustedTime API 的可用性與限制
TrustedTime API 適用於所有運行 Google Play 服務 的 Android 5(Lollipop)及以上版本的設備。若要存取此 API,請新增以下依賴項:
或更新版本。
使用此 API 無需額外的權限,但 TrustedTime 需要在設備啟動後連接網路才能提供時間戳記。如果設備自開機以來從未連接到網際網路,則 TrustedTime API 無法返回時間戳記。
請注意,設備的內部時鐘可能會因 溫度、休眠模式(Doze Mode)、電池電量等因素 而產生時間漂移。TrustedTime 無法防止 這種漂移,但其 API 會為每個時間戳提供誤差估算值,可用來判斷時間的準確性是否符合應用程式的需求。此外,雖然 TrustedTime 能 降低使用者修改設備時間 影響應用程式的可能性,但它 無法完全防止時間篡改,仍可能有進階技術能影響設備時間。

0 留言