@@ -20,13 +20,16 @@ import com.credman.cmwallet.CmWalletApplication.Companion.computeClientId
2020import com.credman.cmwallet.data.model.Credential
2121import com.credman.cmwallet.data.model.CredentialDisplayData
2222import com.credman.cmwallet.data.model.CredentialItem
23+ import com.credman.cmwallet.data.model.CredentialKeyHardware
2324import com.credman.cmwallet.data.model.CredentialKeySoftware
2425import com.credman.cmwallet.data.room.CredentialDatabaseItem
2526import com.credman.cmwallet.decodeBase64UrlNoPadding
2627import com.credman.cmwallet.getcred.createOpenID4VPResponse
2728import com.credman.cmwallet.mdoc.MDoc
29+ import com.credman.cmwallet.openid4vci.HardwareKey
2830import com.credman.cmwallet.openid4vci.OpenId4VCI
2931import com.credman.cmwallet.openid4vci.OpenId4VCI.Companion.WALLET_CLIENT_ID
32+ import com.credman.cmwallet.openid4vci.SoftwareKey
3033import com.credman.cmwallet.openid4vci.data.AuthorizationDetailResponseOpenIdCredential
3134import com.credman.cmwallet.openid4vci.data.CredentialConfigurationMDoc
3235import com.credman.cmwallet.openid4vci.data.CredentialConfigurationSdJwtVc
@@ -116,23 +119,19 @@ class CreateCredentialViewModel : ViewModel() {
116119 if (tokenResponse.authorizationDetails == null ) {
117120 val scopes = (tokenResponse.scopes ? : tokenRequestScope)?.split(" " )
118121 scopes?.forEach { scope ->
119- val deviceKeys: MutableList <KeyPair > = mutableListOf ()
120- val kpg = KeyPairGenerator .getInstance(" EC" )
121- kpg.initialize(ECGenParameterSpec (" secp256r1" ))
122- for (i in 0 .. < (openId4VCI.credentialOffer.issuerMetadata.batchCredentialIssuance?.batchSize ? : 1 )) {
123- deviceKeys.add(kpg.genKeyPair())
124- }
122+ val keyPairsAndProofs = openId4VCI.createKeyProofs(scope)
125123 val credentialResponse = openId4VCI.requestCredentialFromEndpoint(
126124 accessToken = tokenResponse.accessToken,
127125 credentialRequest = CredentialRequest (
128126 credentialConfigurationId = scope,
129- proofs = openId4VCI.createProofJwt(deviceKeys)
127+ proofs = keyPairsAndProofs.first
130128 )
131129 )
132130 Log .i(TAG , " credentialResponse $credentialResponse " )
133131 val config = openId4VCI.credentialOffer.issuerMetadata.credentialConfigurationsSupported[scope]!!
134132 val display = credentialResponse.display?.firstOrNull()
135133 val configDisplay = config.credentialMetadata?.display?.firstOrNull()
134+ val deviceKeys = keyPairsAndProofs.second
136135 val newCredentialItem = CredentialItem (
137136 id = Uuid .random().toHexString(),
138137 config = config,
@@ -147,7 +146,7 @@ class CreateCredentialViewModel : ViewModel() {
147146 val mdoc = MDoc (it.credential.decodeBase64UrlNoPadding())
148147 val deviceKey = mdoc.deviceKey
149148 deviceKeys.firstOrNull {
150- val public = it.public as ECPublicKey
149+ val public = it.publicKey as ECPublicKey
151150 val x = String (public.w.affineX.toFixedByteArray(32 ))
152151 val y = String (public.w.affineY.toFixedByteArray(32 ))
153152 x == deviceKey.first && y == deviceKey.second
@@ -157,7 +156,7 @@ class CreateCredentialViewModel : ViewModel() {
157156 val issuerJwtString = it.credential.split(' ~' )[0 ]
158157 val cnfKey = IssuerJwt (issuerJwtString).payload.getJSONObject(" cnf" ).getJSONObject(" jwk" )
159158 deviceKeys.firstOrNull {
160- val public = it.public as ECPublicKey
159+ val public = it.publicKey as ECPublicKey
161160 val x = public.w.affineX.toFixedByteArray(32 ).toBase64UrlNoPadding()
162161 val y = public.w.affineY.toFixedByteArray(32 ).toBase64UrlNoPadding()
163162 x == cnfKey.getString(" x" ) && y == cnfKey.getString(" y" )
@@ -166,10 +165,18 @@ class CreateCredentialViewModel : ViewModel() {
166165 else -> throw UnsupportedOperationException (" Unknown configuration $config " )
167166 }
168167 Credential (
169- key = CredentialKeySoftware (
170- publicKey = Base64 .encodeToString(deviceKeyPair!! .public.encoded, Base64 .URL_SAFE or Base64 .NO_PADDING or Base64 .NO_WRAP ),
171- privateKey = Base64 .encodeToString(deviceKeyPair.private.encoded, Base64 .URL_SAFE or Base64 .NO_PADDING or Base64 .NO_WRAP ),
172- ),
168+ key = deviceKeyPair!! .let { deviceKey ->
169+ when (deviceKey) {
170+ is SoftwareKey -> CredentialKeySoftware (
171+ publicKey = Base64 .encodeToString(deviceKey.publicKey.encoded, Base64 .URL_SAFE or Base64 .NO_PADDING or Base64 .NO_WRAP ),
172+ privateKey = Base64 .encodeToString(deviceKey.privateKey.encoded, Base64 .URL_SAFE or Base64 .NO_PADDING or Base64 .NO_WRAP ),
173+ )
174+ is HardwareKey -> CredentialKeyHardware (
175+ publicKey = Base64 .encodeToString(deviceKey.publicKey.encoded, Base64 .URL_SAFE or Base64 .NO_PADDING or Base64 .NO_WRAP ),
176+ keyAlias = deviceKey.keyAlias
177+ )
178+ }
179+ },
173180 credential = it.credential
174181 )
175182 }
@@ -181,23 +188,19 @@ class CreateCredentialViewModel : ViewModel() {
181188 when (authDetail) {
182189 is AuthorizationDetailResponseOpenIdCredential -> {
183190 authDetail.credentialIdentifiers.forEach { credentialId ->
184- val deviceKeys: MutableList <KeyPair > = mutableListOf ()
185- val kpg = KeyPairGenerator .getInstance(" EC" )
186- kpg.initialize(ECGenParameterSpec (" secp256r1" ))
187- for (i in 0 .. < (openId4VCI.credentialOffer.issuerMetadata.batchCredentialIssuance?.batchSize ? : 1 )) {
188- deviceKeys.add(kpg.genKeyPair())
189- }
191+ val keyPairsAndProofs = openId4VCI.createKeyProofs(authDetail.credentialConfigurationId)
190192 val credentialResponse = openId4VCI.requestCredentialFromEndpoint(
191193 accessToken = tokenResponse.accessToken,
192194 credentialRequest = CredentialRequest (
193195 credentialIdentifier = credentialId,
194- proofs = openId4VCI.createProofJwt(deviceKeys)
196+ proofs = keyPairsAndProofs.first
195197 ),
196198 )
197199 Log .i(TAG , " credentialResponse $credentialResponse " )
198200 val config = openId4VCI.credentialOffer.issuerMetadata.credentialConfigurationsSupported[authDetail.credentialConfigurationId]!!
199201 val display = credentialResponse.display?.firstOrNull()
200202 val displayFromOffer = config.credentialMetadata?.display?.firstOrNull()
203+ val deviceKeys = keyPairsAndProofs.second
201204 val newCredentialItem = CredentialItem (
202205 id = Uuid .random().toHexString(),
203206 config = config,
@@ -212,7 +215,7 @@ class CreateCredentialViewModel : ViewModel() {
212215 val mdoc = MDoc (it.credential.decodeBase64UrlNoPadding())
213216 val deviceKey = mdoc.deviceKey
214217 deviceKeys.firstOrNull {
215- val public = it.public as ECPublicKey
218+ val public = it.publicKey as ECPublicKey
216219 val x = String (public.w.affineX.toFixedByteArray(32 ))
217220 val y = String (public.w.affineY.toFixedByteArray(32 ))
218221 x == deviceKey.first && y == deviceKey.second
@@ -222,7 +225,7 @@ class CreateCredentialViewModel : ViewModel() {
222225 val issuerJwtString = it.credential.split(' ~' )[0 ]
223226 val cnfKey = IssuerJwt (issuerJwtString).payload.getJSONObject(" cnf" ).getJSONObject(" jwk" )
224227 deviceKeys.firstOrNull {
225- val public = it.public as ECPublicKey
228+ val public = it.publicKey as ECPublicKey
226229 val x = public.w.affineX.toFixedByteArray(32 ).toBase64UrlNoPadding()
227230 val y = public.w.affineY.toFixedByteArray(32 ).toBase64UrlNoPadding()
228231 x == cnfKey.getString(" x" ) && y == cnfKey.getString(" y" )
@@ -232,10 +235,18 @@ class CreateCredentialViewModel : ViewModel() {
232235 }
233236
234237 Credential (
235- key = CredentialKeySoftware (
236- publicKey = Base64 .encodeToString(deviceKeyPair!! .public.encoded, Base64 .URL_SAFE or Base64 .NO_PADDING or Base64 .NO_WRAP ),
237- privateKey = Base64 .encodeToString(deviceKeyPair.private.encoded, Base64 .URL_SAFE or Base64 .NO_PADDING or Base64 .NO_WRAP ),
238- ),
238+ key = deviceKeyPair!! .let { deviceKey ->
239+ when (deviceKey) {
240+ is SoftwareKey -> CredentialKeySoftware (
241+ publicKey = Base64 .encodeToString(deviceKey.publicKey.encoded, Base64 .URL_SAFE or Base64 .NO_PADDING or Base64 .NO_WRAP ),
242+ privateKey = Base64 .encodeToString(deviceKey.privateKey.encoded, Base64 .URL_SAFE or Base64 .NO_PADDING or Base64 .NO_WRAP ),
243+ )
244+ is HardwareKey -> CredentialKeyHardware (
245+ publicKey = Base64 .encodeToString(deviceKey.publicKey.encoded, Base64 .URL_SAFE or Base64 .NO_PADDING or Base64 .NO_WRAP ),
246+ keyAlias = deviceKey.keyAlias
247+ )
248+ }
249+ },
239250 credential = it.credential
240251 )
241252 }
0 commit comments