Skip to content

Commit a36fb19

Browse files
committed
Use trusted time
1 parent 07924fa commit a36fb19

6 files changed

Lines changed: 26 additions & 5 deletions

File tree

app/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ dependencies {
7676
androidTestImplementation(libs.androidx.ui.test.junit4)
7777
debugImplementation(libs.androidx.ui.tooling)
7878
debugImplementation(libs.androidx.ui.test.manifest)
79+
implementation(libs.play.services.time)
7980
}
8081

8182
configurations.all {

app/src/main/java/com/credman/cmwallet/CmWalletApplication.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ import androidx.room.Room
1414
import com.credman.cmwallet.data.repository.CredentialRepository
1515
import com.credman.cmwallet.data.room.CredentialDatabase
1616
import com.credman.cmwallet.mdoc.MDoc
17+
import com.google.android.gms.time.TrustedTime
18+
import com.google.android.gms.time.TrustedTimeClient
1719
import kotlinx.coroutines.CoroutineScope
1820
import kotlinx.coroutines.Dispatchers
1921
import kotlinx.coroutines.SupervisorJob
2022
import kotlinx.coroutines.launch
2123
import java.io.ByteArrayOutputStream
24+
import java.time.Instant
2225
import kotlin.io.encoding.ExperimentalEncodingApi
2326

2427

@@ -29,6 +32,8 @@ class CmWalletApplication : Application() {
2932

3033
lateinit var walletIcon: Bitmap
3134

35+
var trustedTimeClient: TrustedTimeClient? = null
36+
3237
fun computeClientId(callingAppInfo: CallingAppInfo): String {
3338
val origin = callingAppInfo.getOrigin(credentialRepo.privAppsJson)
3439
return if (origin == null) {
@@ -38,15 +43,24 @@ class CmWalletApplication : Application() {
3843
}
3944
}
4045

46+
fun getCurrentTime() =
47+
trustedTimeClient?.computeCurrentInstant()?.epochSecond ?: Instant.now().epochSecond
48+
4149
const val TAG = "CmWalletApplication"
4250
}
4351

4452
private val registryManager = RegistryManager.create(this)
53+
4554
private val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
4655

4756
@OptIn(ExperimentalDigitalCredentialApi::class, ExperimentalEncodingApi::class)
4857
override fun onCreate() {
4958
super.onCreate()
59+
TrustedTime.createClient(this).addOnSuccessListener {
60+
trustedTimeClient = it
61+
}.addOnFailureListener {
62+
Log.e(TAG, "Could not get trusted time client $it")
63+
}
5064

5165
walletIcon = resources.getDrawable(R.mipmap.ic_launcher, theme).toBitmap()
5266

app/src/main/java/com/credman/cmwallet/Utils.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.credman.cmwallet
22

33
import android.util.Log
44
import com.credman.cmwallet.sdjwt.jwsSignatureToDer
5+
import com.google.android.gms.time.TrustedTimeClient
56
import kotlinx.serialization.encodeToString
67
import kotlinx.serialization.json.Json
78
import kotlinx.serialization.json.JsonElement
@@ -29,6 +30,7 @@ import java.security.spec.ECParameterSpec
2930
import java.security.spec.ECPoint
3031
import java.security.spec.ECPublicKeySpec
3132
import java.security.spec.PKCS8EncodedKeySpec
33+
import java.time.Instant
3234
import java.util.Arrays
3335
import javax.crypto.Cipher
3436
import javax.crypto.KeyAgreement

app/src/main/java/com/credman/cmwallet/openid4vci/OpenId4VCI.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import android.security.keystore.KeyProperties
55
import android.util.Base64
66
import android.util.Log
77
import com.credman.cmwallet.CmWalletApplication.Companion.TAG
8+
import com.credman.cmwallet.CmWalletApplication.Companion.getCurrentTime
89
import com.credman.cmwallet.createJWTES256
910
import com.credman.cmwallet.jweDecrypt
1011
import com.credman.cmwallet.jweSerialization
@@ -224,7 +225,7 @@ class OpenId4VCI(val credentialOfferJson: String) {
224225
val clientAttestationPayload = buildJsonObject {
225226
put("sub", WALLET_CLIENT_ID)
226227
put("wallet_name", WALLET_NAME)
227-
put("exp", Instant.now().epochSecond + 432000 /* 5 days */)
228+
put("exp", getCurrentTime() + 432000 /* 5 days */)
228229
put("cnf", buildJsonObject {
229230
put("jwk", kp.public.toJWK())
230231
})
@@ -240,7 +241,7 @@ class OpenId4VCI(val credentialOfferJson: String) {
240241
val clientAttestationPopPayload = buildJsonObject {
241242
put("aud", authServerIdentifier())
242243
put("jti", Uuid.random().toByteArray().encodeBase64())
243-
put("iat", Instant.now().epochSecond)
244+
put("iat", getCurrentTime())
244245
put("challenge", challenge)
245246
}
246247
return createJWTES256(clientAttestationPopHeader, clientAttestationPopPayload, kp.private)
@@ -256,7 +257,7 @@ class OpenId4VCI(val credentialOfferJson: String) {
256257
put("jti", Uuid.random().toByteArray().encodeBase64())
257258
put("htm", method)
258259
put("htu", endpoint)
259-
put("iat", Instant.now().epochSecond)
260+
put("iat", getCurrentTime())
260261
ath?.let { put("ath", ath) }
261262
dpopNonce?.let { put("nonce", dpopNonce) }
262263
}
@@ -405,7 +406,7 @@ class OpenId4VCI(val credentialOfferJson: String) {
405406
},
406407
payload = buildJsonObject {
407408
put("aud", credentialOffer.credentialIssuer)
408-
put("iat", Instant.now().epochSecond)
409+
put("iat", getCurrentTime())
409410
put("nonce", nonceResponse.cNonce)
410411
},
411412
privateKey = privateKey

app/src/main/java/com/credman/cmwallet/sdjwt/SdJwt.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import java.math.BigInteger
99
import java.nio.ByteBuffer
1010
import java.security.MessageDigest
1111
import android.util.Base64
12+
import com.credman.cmwallet.CmWalletApplication.Companion.getCurrentTime
1213
import com.credman.cmwallet.createJWTES256
1314
import com.credman.cmwallet.jwsDeserialization
1415
import com.credman.cmwallet.loadECPrivateKey
@@ -143,7 +144,7 @@ class SdJwt(
143144
put("alg", "ES256")
144145
}
145146
val kbPayload = buildJsonObject {
146-
put("iat", Instant.now().epochSecond)
147+
put("iat", getCurrentTime())
147148
put("aud", aud)
148149
put("nonce", nonce)
149150
put("sd_hash", digest)

gradle/libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ ktorClient = "3.0.1"
1212
lifecycleRuntimeKtx = "2.6.1"
1313
activityCompose = "1.10.0"
1414
composeBom = "2024.12.01"
15+
playServicesTime = "16.0.1"
1516
registryDigitalcredentialsMdoc = "1.0.0-SNAPSHOT"
1617
lifecycleRuntimeComposeAndroid = "2.8.7"
1718
roomRuntime = "2.6.1"
@@ -53,6 +54,7 @@ ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx
5354
lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx" }
5455
androidx-lifecycle-runtime-compose-android = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose-android", version.ref = "lifecycleRuntimeComposeAndroid" }
5556
androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "roomRuntime" }
57+
play-services-time = { module = "com.google.android.gms:play-services-time", version.ref = "playServicesTime" }
5658

5759
[plugins]
5860
android-application = { id = "com.android.application", version.ref = "agp" }

0 commit comments

Comments
 (0)