Android 發佈 TrustedTime API — 提供可靠時間來源的全新解決方案

Android 發佈 TrustedTime API — 提供可靠時間來源的全新解決方案

 

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.


在Activity內使用:
@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,請新增以下依賴項:


implementation 'com.google.android.gms:play-services-time:16.0.1'

或更新版本。

使用此 API 無需額外的權限,但 TrustedTime 需要在設備啟動後連接網路才能提供時間戳記。如果設備自開機以來從未連接到網際網路,則 TrustedTime API 無法返回時間戳記

請注意,設備的內部時鐘可能會因 溫度、休眠模式(Doze Mode)、電池電量等因素 而產生時間漂移。TrustedTime 無法防止 這種漂移,但其 API 會為每個時間戳提供誤差估算值,可用來判斷時間的準確性是否符合應用程式的需求。此外,雖然 TrustedTime 能 降低使用者修改設備時間 影響應用程式的可能性,但它 無法完全防止時間篡改,仍可能有進階技術能影響設備時間。






張貼留言

0 留言