Skip to content

Commit 0c47e20

Browse files
committed
wip to test issuance
1 parent ae1a807 commit 0c47e20

File tree

4 files changed

+121
-87
lines changed

4 files changed

+121
-87
lines changed

wallet-core/src/main/java/eu/europa/ec/eudi/wallet/EudiWallet.kt

Lines changed: 68 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ import eu.europa.ec.eudi.wallet.document.sample.SampleDocumentManager
3535
import eu.europa.ec.eudi.wallet.internal.getCertificate
3636
import eu.europa.ec.eudi.wallet.internal.mainExecutor
3737
import eu.europa.ec.eudi.wallet.issue.openid4vci.*
38+
import eu.europa.ec.eudi.wallet.keystore.KeyGenerator
39+
import eu.europa.ec.eudi.wallet.keystore.KeyGeneratorImpl
3840
import eu.europa.ec.eudi.wallet.transfer.openid4vp.OpenId4VpCBORResponse
39-
import eu.europa.ec.eudi.wallet.transfer.openid4vp.responseGenerator.OpenId4VpResponseGeneratorDelegator
4041
import eu.europa.ec.eudi.wallet.transfer.openid4vp.OpenId4vpManager
42+
import eu.europa.ec.eudi.wallet.transfer.openid4vp.responseGenerator.OpenId4VpResponseGeneratorDelegator
4143
import eu.europa.ec.eudi.wallet.util.DefaultNfcEngagementService
42-
import eu.europa.ec.eudi.wallet.keystore.KeyGenerator
43-
import eu.europa.ec.eudi.wallet.keystore.KeyGeneratorImpl
4444
import java.security.cert.X509Certificate
4545
import java.util.concurrent.Executor
4646

@@ -229,7 +229,10 @@ object EudiWallet : KeyGenerator by KeyGeneratorImpl {
229229
* @return [StoreDocumentResult]
230230
* @throws IllegalStateException if [EudiWallet] is not firstly initialized via the [init] method
231231
*/
232-
fun storeIssuedDocument(unsignedDocument: UnsignedDocument, data: ByteArray): StoreDocumentResult =
232+
fun storeIssuedDocument(
233+
unsignedDocument: UnsignedDocument,
234+
data: ByteArray
235+
): StoreDocumentResult =
233236
documentManager.storeIssuedDocument(unsignedDocument, data)
234237

235238
private var openId4VciManager: OpenId4VciManager? = null
@@ -285,7 +288,15 @@ object EudiWallet : KeyGenerator by KeyGeneratorImpl {
285288
config(config)
286289
logger = this@EudiWallet.logger
287290
ktorHttpClientFactory = _config.ktorHttpClientFactory
288-
}.also { it.issueDocumentByDocType(docType, txCode, executor, authorizationHandler, onEvent) }
291+
}.also {
292+
it.issueDocumentByDocType(
293+
docType,
294+
txCode,
295+
executor,
296+
authorizationHandler,
297+
onEvent
298+
)
299+
}
289300
} ?: run {
290301
(executor ?: context.mainExecutor()).execute {
291302
onEvent(IssueEvent.failure(IllegalStateException("OpenId4Vci config is not set in configuration")))
@@ -321,7 +332,15 @@ object EudiWallet : KeyGenerator by KeyGeneratorImpl {
321332
config(config)
322333
logger = this@EudiWallet.logger
323334
ktorHttpClientFactory = _config.ktorHttpClientFactory
324-
}.also { it.issueDocumentByOffer(offer, txCode, executor, authorizationHandler, onEvent) }
335+
}.also {
336+
it.issueDocumentByOffer(
337+
offer,
338+
txCode,
339+
executor,
340+
authorizationHandler,
341+
onEvent
342+
)
343+
}
325344
} ?: run {
326345
(executor ?: context.mainExecutor()).execute {
327346
onEvent(IssueEvent.failure(IllegalStateException("OpenId4Vci config is not set in configuration")))
@@ -356,7 +375,15 @@ object EudiWallet : KeyGenerator by KeyGeneratorImpl {
356375
config(config)
357376
logger = this@EudiWallet.logger
358377
ktorHttpClientFactory = _config.ktorHttpClientFactory
359-
}.also { it.issueDocumentByOfferUri(offerUri, txCode, executor, authorizationHandler, onEvent) }
378+
}.also {
379+
it.issueDocumentByOfferUri(
380+
offerUri,
381+
txCode,
382+
executor,
383+
authorizationHandler,
384+
onEvent
385+
)
386+
}
360387
} ?: run {
361388
(executor ?: context.mainExecutor()).execute {
362389
onEvent(IssueEvent.failure(IllegalStateException("OpenId4Vci config is not set in configuration")))
@@ -388,7 +415,12 @@ object EudiWallet : KeyGenerator by KeyGeneratorImpl {
388415
ktorHttpClientFactory = _config.ktorHttpClientFactory
389416
}.also {
390417
when (val document = documentManager.getDocumentById(documentId)) {
391-
is DeferredDocument -> it.issueDeferredDocument(document, executor, onResult)
418+
is DeferredDocument -> it.issueDeferredDocument(
419+
document,
420+
executor,
421+
onResult
422+
)
423+
392424
else -> (executor ?: context.mainExecutor()).execute {
393425
onResult(
394426
DeferredIssueResult.DocumentFailed(
@@ -479,8 +511,16 @@ object EudiWallet : KeyGenerator by KeyGeneratorImpl {
479511
* @return [EudiWallet]
480512
*/
481513
fun setTrustedReaderCertificates(trustedReaderCertificates: List<X509Certificate>) = apply {
482-
deviceResponseGenerator.setReaderTrustStore(ReaderTrustStore.getDefault(trustedReaderCertificates))
483-
openId4VpCBORResponseGenerator.setReaderTrustStore(ReaderTrustStore.getDefault(trustedReaderCertificates))
514+
deviceResponseGenerator.setReaderTrustStore(
515+
ReaderTrustStore.getDefault(
516+
trustedReaderCertificates
517+
)
518+
)
519+
openId4VpCBORResponseGenerator.setReaderTrustStore(
520+
ReaderTrustStore.getDefault(
521+
trustedReaderCertificates
522+
)
523+
)
484524
}
485525

486526
/**
@@ -635,9 +675,10 @@ object EudiWallet : KeyGenerator by KeyGeneratorImpl {
635675
// create response
636676
val responseResult = when (transferMode) {
637677
TransferMode.OPENID4VP ->
638-
openId4vpManager?.responseGenerator?.createResponse(disclosedDocuments) ?: ResponseResult.Failure(
639-
Throwable("Openid4vpManager has not been initialized properly")
640-
)
678+
openId4vpManager?.responseGenerator?.createResponse(disclosedDocuments)
679+
?: ResponseResult.Failure(
680+
Throwable("Openid4vpManager has not been initialized properly")
681+
)
641682

642683
TransferMode.ISO_18013_5, TransferMode.REST_API ->
643684
transferManager.responseGenerator.createResponse(disclosedDocuments)
@@ -701,14 +742,22 @@ object EudiWallet : KeyGenerator by KeyGeneratorImpl {
701742
private val transferManagerDocumentsResolver: DocumentsResolver
702743
get() = DocumentsResolver { req ->
703744

704-
//When()
705-
//get sdJwt docs
706-
//SdJwt filter
745+
DocumentManagerSdJwt
746+
.getAllDocuments()
747+
.filter { doc -> doc.vct == req.docType }
748+
.map { doc ->
749+
RequestDocument(
750+
documentId = doc.id,
751+
docType = doc.vct,
752+
docName = doc.docName,
753+
userAuthentication = doc.requiresUserAuth,
754+
docRequest = req
755+
)
756+
}.takeIf { it.isNotEmpty() }?.let { return@DocumentsResolver it }
707757

708-
//Mdoc filter
709-
documentManager.getDocuments(Document.State.ISSUED)
758+
return@DocumentsResolver documentManager.getDocuments(Document.State.ISSUED)
710759
.filterIsInstance<IssuedDocument>()
711-
.filter { doc -> doc.docType == req.docType }
760+
// .filter { doc -> doc.docType == req.docType }
712761
.map { doc ->
713762
RequestDocument(
714763
documentId = doc.id,

wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/ProcessResponse.kt

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,28 @@
1616

1717
package eu.europa.ec.eudi.wallet.issue.openid4vci
1818

19-
import com.android.identity.util.CborUtil
2019
import com.nimbusds.jose.crypto.ECDSAVerifier
21-
import com.nimbusds.jose.crypto.RSASSAVerifier
2220
import com.nimbusds.jose.jwk.ECKey
23-
import com.nimbusds.jose.jwk.RSAKey
2421
import eu.europa.ec.eudi.openid4vci.IssuedCredential
2522
import eu.europa.ec.eudi.openid4vci.SubmissionOutcome
26-
import eu.europa.ec.eudi.sdjwt.SdJwtFactory
27-
import eu.europa.ec.eudi.sdjwt.SdJwtIssuer
2823
import eu.europa.ec.eudi.sdjwt.SdJwtVerifier
2924
import eu.europa.ec.eudi.sdjwt.asJwtVerifier
30-
import eu.europa.ec.eudi.sdjwt.nimbus
3125
import eu.europa.ec.eudi.wallet.document.DocumentId
3226
import eu.europa.ec.eudi.wallet.document.DocumentManager
3327
import eu.europa.ec.eudi.wallet.document.StoreDocumentResult
3428
import eu.europa.ec.eudi.wallet.document.UnsignedDocument
3529
import eu.europa.ec.eudi.wallet.issue.openid4vci.IssueEvent.Companion.documentFailed
3630
import eu.europa.ec.eudi.wallet.logging.Logger
37-
import eu.europa.ec.eudi.wallet.util.CBOR
31+
import eu.europa.ec.eudi.wallet.logging.d
32+
import eu.europa.ec.eudi.wallet.transfer.openid4vp.OpenId4vpManager.Companion.TAG
3833
import kotlinx.coroutines.CancellableContinuation
3934
import kotlinx.coroutines.CoroutineScope
4035
import kotlinx.coroutines.Dispatchers
4136
import kotlinx.coroutines.launch
4237
import kotlinx.coroutines.runBlocking
4338
import kotlinx.coroutines.suspendCancellableCoroutine
4439
import kotlinx.serialization.json.Json
40+
import org.bouncycastle.util.encoders.Hex
4541
import org.json.JSONObject
4642
import java.io.ByteArrayInputStream
4743
import java.io.Closeable
@@ -65,10 +61,6 @@ internal class ProcessResponse(
6561
}
6662

6763
suspend fun process(response: SubmitRequest.Response) {
68-
//Get UUID from mDoc
69-
70-
//Give UUID into sdJwt process() call
71-
7264
response.forEach { (unsignedDocument, result) ->
7365
process(unsignedDocument, result)
7466
}
@@ -104,32 +96,38 @@ internal class ProcessResponse(
10496
when (outcome) {
10597
is SubmissionOutcome.Success -> when (val credential = outcome.credentials[0]) {
10698
is IssuedCredential.Issued -> try {
107-
// sdjwt
108-
109-
val headerString = credential.credential.split(".").first()
110-
val headerJson = JSONObject(String(Base64.getUrlDecoder().decode(headerString)))
111-
val keyString = headerJson.getJSONArray("x5c").getString(0).replace("\n", "")
112-
113-
val pemKey = "-----BEGIN CERTIFICATE-----\n" +
114-
"${keyString}\n" +
115-
"-----END CERTIFICATE-----"
116-
117-
val certificateFactory: CertificateFactory = CertificateFactory.getInstance("X.509")
118-
val certificate =
119-
certificateFactory.generateCertificate(ByteArrayInputStream(pemKey.toByteArray())) as X509Certificate
120-
121-
val ecKey = ECKey.parse(certificate)
122-
val jwtSignatureVerifier = ECDSAVerifier(ecKey).asJwtVerifier()
123-
124-
CoroutineScope(Dispatchers.IO).launch {
125-
val verifiedIssuanceSdJwt = SdJwtVerifier.verifyIssuance(
126-
jwtSignatureVerifier,
127-
credential.credential
128-
).getOrThrow()
129-
130-
//store
131-
132-
// logger?.d(TAG, "CBOR bytes: ${Hex.toHexString(cborBytes)}")
99+
if (isSdJwt(credential.credential)) {
100+
val headerString = credential.credential.split(".").first()
101+
val headerJson =
102+
JSONObject(String(Base64.getUrlDecoder().decode(headerString)))
103+
val keyString =
104+
headerJson.getJSONArray("x5c").getString(0).replace("\n", "")
105+
106+
val pemKey = "-----BEGIN CERTIFICATE-----\n" +
107+
"${keyString}\n" +
108+
"-----END CERTIFICATE-----"
109+
110+
val certificateFactory: CertificateFactory =
111+
CertificateFactory.getInstance("X.509")
112+
val certificate =
113+
certificateFactory.generateCertificate(ByteArrayInputStream(pemKey.toByteArray())) as X509Certificate
114+
115+
val ecKey = ECKey.parse(certificate)
116+
val jwtSignatureVerifier = ECDSAVerifier(ecKey).asJwtVerifier()
117+
118+
CoroutineScope(Dispatchers.IO).launch {
119+
SdJwtVerifier.verifyIssuance(
120+
jwtSignatureVerifier,
121+
credential.credential
122+
).getOrThrow()
123+
124+
DocumentManagerSdJwt.storeDocument(unsignedDocument.id, credential.credential)
125+
}
126+
127+
} else {
128+
val cborBytes = Base64.getUrlDecoder().decode(credential.credential)
129+
130+
logger?.d(TAG, "CBOR bytes: ${Hex.toHexString(cborBytes)}")
133131
documentManager.storeIssuedDocument(
134132
unsignedDocument,
135133
credential.credential.toByteArray()
@@ -168,7 +166,13 @@ internal class ProcessResponse(
168166
}
169167

170168
private fun isSdJwt(credential: String): Boolean {
171-
return credential.contains("~")
169+
return try {
170+
val headerString = credential.split(".").first()
171+
val headerJson = JSONObject(String(Base64.getUrlDecoder().decode(headerString)))
172+
true
173+
} catch (e: Exception) {
174+
false
175+
}
172176
}
173177

174178
private fun UserAuthRequiredException.toIssueEvent(

wallet-core/src/main/java/eu/europa/ec/eudi/wallet/transfer/openid4vp/responseGenerator/OpenId4VpResponseGeneratorDelegator.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,7 @@ class OpenId4VpResponseGeneratorDelegator(
8888
}
8989

9090
val openId4VpSdJwtResponseGeneratorImpl = OpenId4VpSdJwtResponseGeneratorImpl(
91-
documentsResolver,
92-
storageEngine,
93-
androidSecureArea,
94-
logger
91+
documentsResolver
9592
).apply {
9693
readerTrustStore?.let { setReaderTrustStore(it) }
9794
}

0 commit comments

Comments
 (0)