Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of Session Transcript and OID4VPHandover for Openid4Vp #41

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ file.

```groovy
dependencies {
implementation "eu.europa.ec.eudi:eudi-lib-android-wallet-core:0.5.4-SNAPSHOT"
implementation "eu.europa.ec.eudi:eudi-lib-android-wallet-core:0.5.6-SNAPSHOT"
implementation "androidx.biometric:biometric-ktx:1.2.0-alpha05"
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,3 @@ androidJvm
| context | the application context |
| config | the configuration for OpenID4VCI |
| documentManager | the document manager to use for issuing documents |
| executor | the executor to use for callbacks. If null, the main executor will be used. |
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ androidJvm
| context | the application context |
| config | the configuration for OpenID4VCI |
| documentManager | the document manager to use for issuing documents |
| executor | the executor to use for callbacks. If null, the main executor will be used. |

## Constructors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
# OpenId4VpRequest

[androidJvm]\
constructor(presentationDefinition: PresentationDefinition)
constructor(presentationDefinition: PresentationDefinition, sessionTranscript: SessionTranscriptBytes)
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
# OpenId4VpRequest

[androidJvm]\
class [OpenId4VpRequest](index.md)(val presentationDefinition: PresentationDefinition) : Request
class [OpenId4VpRequest](index.md)(val presentationDefinition: PresentationDefinition, val sessionTranscript: SessionTranscriptBytes) : Request

## Constructors

| | |
|---|---|
| [OpenId4VpRequest](-open-id4-vp-request.md) | [androidJvm]<br>constructor(presentationDefinition: PresentationDefinition) |
| [OpenId4VpRequest](-open-id4-vp-request.md) | [androidJvm]<br>constructor(presentationDefinition: PresentationDefinition, sessionTranscript: SessionTranscriptBytes) |

## Properties

| Name | Summary |
|---|---|
| [presentationDefinition](presentation-definition.md) | [androidJvm]<br>val [presentationDefinition](presentation-definition.md): PresentationDefinition |
| [sessionTranscript](session-transcript.md) | [androidJvm]<br>val [sessionTranscript](session-transcript.md): SessionTranscriptBytes |
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//[wallet-core](../../../index.md)/[eu.europa.ec.eudi.wallet.transfer.openid4vp](../index.md)/[OpenId4VpRequest](index.md)/[sessionTranscript](session-transcript.md)

# sessionTranscript

[androidJvm]\
val [sessionTranscript](session-transcript.md): SessionTranscriptBytes
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
| [OpenId4VpCBORResponseGeneratorImpl](-open-id4-vp-c-b-o-r-response-generator-impl/index.md) | [androidJvm]<br>class [OpenId4VpCBORResponseGeneratorImpl](-open-id4-vp-c-b-o-r-response-generator-impl/index.md)(documentsResolver: DocumentsResolver, storageEngine: StorageEngine, secureArea: AndroidKeystoreSecureArea) : ResponseGenerator&lt;[OpenId4VpRequest](-open-id4-vp-request/index.md)&gt; <br>OpenId4VpCBORResponseGeneratorImpl class is used for parsing a request (Presentation Definition) and generating the DeviceResponse |
| [OpenId4VpConfig](-open-id4-vp-config/index.md) | [androidJvm]<br>class [OpenId4VpConfig](-open-id4-vp-config/index.md)<br>Configuration for the OpenId4Vp transfer. |
| [OpenId4vpManager](-open-id4vp-manager/index.md) | [androidJvm]<br>class [OpenId4vpManager](-open-id4vp-manager/index.md)(context: [Context](https://developer.android.com/reference/kotlin/android/content/Context.html), openId4VpConfig: [OpenId4VpConfig](-open-id4-vp-config/index.md), val responseGenerator: [OpenId4VpCBORResponseGeneratorImpl](-open-id4-vp-c-b-o-r-response-generator-impl/index.md)) : TransferEvent.Listenable |
| [OpenId4VpRequest](-open-id4-vp-request/index.md) | [androidJvm]<br>class [OpenId4VpRequest](-open-id4-vp-request/index.md)(val presentationDefinition: PresentationDefinition) : Request |
| [OpenId4VpRequest](-open-id4-vp-request/index.md) | [androidJvm]<br>class [OpenId4VpRequest](-open-id4-vp-request/index.md)(val presentationDefinition: PresentationDefinition, val sessionTranscript: SessionTranscriptBytes) : Request |
| [PreregisteredVerifier](-preregistered-verifier/index.md) | [androidJvm]<br>data class [PreregisteredVerifier](-preregistered-verifier/index.md)(var clientId: [ClientId](index.md#-875823108%2FClasslikes%2F1615067946), var verifierApi: [VerifierApi](index.md#-1538977700%2FClasslikes%2F1615067946)) |
| [VerifierApi](index.md#-1538977700%2FClasslikes%2F1615067946) | [androidJvm]<br>typealias [VerifierApi](index.md#-1538977700%2FClasslikes%2F1615067946) = [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) |
3 changes: 2 additions & 1 deletion docs/wallet-core/package-list
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@ $dokka.location:eu.europa.ec.eudi.wallet.transfer.openid4vp/OpenId4VpConfig/encr
$dokka.location:eu.europa.ec.eudi.wallet.transfer.openid4vp/OpenId4VpConfig/encryptionMethods/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.transfer.openid4vp/-open-id4-vp-config/encryption-methods.md
$dokka.location:eu.europa.ec.eudi.wallet.transfer.openid4vp/OpenId4VpConfig/scheme/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.transfer.openid4vp/-open-id4-vp-config/scheme.md
$dokka.location:eu.europa.ec.eudi.wallet.transfer.openid4vp/OpenId4VpRequest///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.transfer.openid4vp/-open-id4-vp-request/index.md
$dokka.location:eu.europa.ec.eudi.wallet.transfer.openid4vp/OpenId4VpRequest/OpenId4VpRequest/#eu.europa.ec.eudi.prex.PresentationDefinition/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.transfer.openid4vp/-open-id4-vp-request/-open-id4-vp-request.md
$dokka.location:eu.europa.ec.eudi.wallet.transfer.openid4vp/OpenId4VpRequest/OpenId4VpRequest/#eu.europa.ec.eudi.prex.PresentationDefinition#kotlin.ByteArray/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.transfer.openid4vp/-open-id4-vp-request/-open-id4-vp-request.md
$dokka.location:eu.europa.ec.eudi.wallet.transfer.openid4vp/OpenId4VpRequest/presentationDefinition/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.transfer.openid4vp/-open-id4-vp-request/presentation-definition.md
$dokka.location:eu.europa.ec.eudi.wallet.transfer.openid4vp/OpenId4VpRequest/sessionTranscript/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.transfer.openid4vp/-open-id4-vp-request/session-transcript.md
$dokka.location:eu.europa.ec.eudi.wallet.transfer.openid4vp/OpenId4vpManager///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.transfer.openid4vp/-open-id4vp-manager/index.md
$dokka.location:eu.europa.ec.eudi.wallet.transfer.openid4vp/OpenId4vpManager/OpenId4vpManager/#android.content.Context#eu.europa.ec.eudi.wallet.transfer.openid4vp.OpenId4VpConfig#eu.europa.ec.eudi.wallet.transfer.openid4vp.OpenId4VpCBORResponseGeneratorImpl/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.transfer.openid4vp/-open-id4vp-manager/-open-id4vp-manager.md
$dokka.location:eu.europa.ec.eudi.wallet.transfer.openid4vp/OpenId4vpManager/addTransferEventListener/#eu.europa.ec.eudi.iso18013.transfer.TransferEvent.Listener/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.transfer.openid4vp/-open-id4vp-manager/add-transfer-event-listener.md
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ systemProp.sonar.host.url=https://sonarcloud.io
systemProp.sonar.gradle.skipCompile=true
systemProp.sonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/testDebugUnitTestCoverage/testDebugUnitTestCoverage.xml,build/reports/jacoco/testReleaseUnitTestCoverage/testReleaseUnitTestCoverage.xml
systemProp.sonar.projectName=eudi-lib-android-wallet-core
VERSION_NAME=0.5.5-SNAPSHOT
VERSION_NAME=0.5.6-SNAPSHOT

SONATYPE_HOST=S01
SONATYPE_AUTOMATIC_RELEASE=false
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ espresso-core = "3.5.1"
eudi-document-manager = "0.2.3-SNAPSHOT"
eudi-iso18013-data-transfer = "0.2.0-SNAPSHOT"
eudi-lib-jvm-openid4vci-kt = "0.2.0"
eudi-lib-jvm-siop-openid4vp-kt = "0.3.3"
eudi-lib-jvm-siop-openid4vp-kt = "0.3.4"
gradle-plugin = "7.4.0"
identity-credential = "20231002"
identity-credential-android = "20231002"
Expand Down
2 changes: 1 addition & 1 deletion licenses.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

# EUDI Wallet Core library for Android
## Dependency License Report
_2024-04-04 16:00:54 EEST_
_2024-05-17 16:56:38 EEST_
## Apache License, Version 2.0

**1** **Group:** `androidx.appcompat` **Name:** `appcompat` **Version:** `1.6.1`
Expand Down
4 changes: 3 additions & 1 deletion wallet-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ dependencies {
implementation libs.nimbus.oauth2.oidc.sdk

// Siop-Openid4VP library
implementation libs.eudi.lib.jvm.siop.openid4vp.kt
implementation (libs.eudi.lib.jvm.siop.openid4vp.kt) {
exclude group: "org.bouncycastle"
}

// Google library
implementation (libs.identity.credential) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright (c) 2023-2024 European Commission
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package eu.europa.ec.eudi.wallet.internal

import com.upokecenter.cbor.CBORObject
import eu.europa.ec.eudi.iso18013.transfer.response.SessionTranscriptBytes
import java.security.MessageDigest
import java.security.SecureRandom
import java.util.Base64

/**
* Utility class to generate the session transcript for the OpenID4VP protocol.
*
* SessionTranscript = [
* DeviceEngagementBytes,
* EReaderKeyBytes,
* Handover
* ]
*
* DeviceEngagementBytes = null,
* EReaderKeyBytes = null
*
* Handover = OID4VPHandover
* OID4VPHandover = [
* clientIdHash
* responseUriHash
* nonce
* ]
*
* clientIdHash = bstr
* responseUriHash = bstr
*
* where clientIdHash is the SHA-256 hash of clientIdToHash and responseUriHash is the SHA-256 hash of the responseUriToHash.
*
*
* clientIdToHash = [clientId, mdocGeneratedNonce]
* responseUriToHash = [responseUri, mdocGeneratedNonce]
*
*
* mdocGeneratedNonce = tstr
* clientId = tstr
* responseUri = tstr
* nonce = tstr
*
*/

internal object Openid4VpUtils {

@JvmStatic
internal fun generateSessionTranscript(
clientId: String,
responseUri: String,
nonce: String,
mdocGeneratedNonce: String
): SessionTranscriptBytes {

val openID4VPHandover =
generateOpenId4VpHandover(clientId, responseUri, nonce, mdocGeneratedNonce)

val sessionTranscriptBytes =
CBORObject.NewArray().apply {
Add(CBORObject.Null)
Add(CBORObject.Null)
Add(openID4VPHandover)
}.EncodeToBytes()

return sessionTranscriptBytes
}

@JvmStatic
internal fun generateOpenId4VpHandover(
clientId: String,
responseUri: String,
nonce: String,
mdocGeneratedNonce: String
): CBORObject {
val clientIdToHash = CBORObject.NewArray().apply {
Add(clientId)
Add(mdocGeneratedNonce)
}.EncodeToBytes()

val responseUriToHash = CBORObject.NewArray().apply {
Add(responseUri)
Add(mdocGeneratedNonce)
}.EncodeToBytes()

val clientIdHash = MessageDigest.getInstance("SHA-256").digest(clientIdToHash)
val responseUriHash = MessageDigest.getInstance("SHA-256").digest(responseUriToHash)

val openID4VPHandover = CBORObject.NewArray().apply {
Add(clientIdHash)
Add(responseUriHash)
Add(nonce)
}
return openID4VPHandover
}

@JvmStatic
internal fun generateMdocGeneratedNonce(): String {
val secureRandom = SecureRandom()
val bytes = ByteArray(16)
secureRandom.nextBytes(bytes)
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import eu.europa.ec.eudi.iso18013.transfer.RequestedDocumentData
import eu.europa.ec.eudi.iso18013.transfer.ResponseResult
import eu.europa.ec.eudi.iso18013.transfer.readerauth.ReaderTrustStore
import eu.europa.ec.eudi.iso18013.transfer.response.ResponseGenerator
import eu.europa.ec.eudi.iso18013.transfer.response.SessionTranscriptBytes
import eu.europa.ec.eudi.wallet.internal.Openid4VpX509CertificateTrust

private const val TAG = "OpenId4VpCBORResponseGe"
Expand All @@ -61,6 +62,7 @@ class OpenId4VpCBORResponseGeneratorImpl(private val documentsResolver: Document

private var readerTrustStore: ReaderTrustStore? = null
private val openid4VpX509CertificateTrust = Openid4VpX509CertificateTrust(readerTrustStore)
private var sessionTranscript: SessionTranscriptBytes? = null

/**
* Set a trust store so that reader authentication can be performed.
Expand Down Expand Up @@ -100,6 +102,7 @@ class OpenId4VpCBORResponseGeneratorImpl(private val documentsResolver: Document
* @return [RequestedDocumentData]
*/
override fun parseRequest(request: OpenId4VpRequest): RequestedDocumentData {
sessionTranscript = request.sessionTranscript
return createRequestedDocumentData(
request.presentationDefinition.inputDescriptors
.mapNotNull { inputDescriptor ->
Expand Down Expand Up @@ -154,12 +157,13 @@ class OpenId4VpCBORResponseGeneratorImpl(private val documentsResolver: Document
return ResponseResult.Failure(Exception("Device Response is not allowed to have more than to age_over_NN elements"))
}
val addResult =
addDocumentToResponse(deviceResponse, responseDocument, byteArrayOf(0))
addDocumentToResponse(deviceResponse, responseDocument, sessionTranscript!!)
if (addResult is AddDocumentToResponse.UserAuthRequired)
return ResponseResult.UserAuthRequired(
addResult.keyUnlockData.getCryptoObjectForSigning(SecureArea.ALGORITHM_ES256)
)
}
sessionTranscript = null
return ResponseResult.Success(OpenId4VpCBORResponse(deviceResponse.generate()))
} catch (e: Exception) {
return ResponseResult.Failure(e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package eu.europa.ec.eudi.wallet.transfer.openid4vp

import eu.europa.ec.eudi.iso18013.transfer.response.Request
import eu.europa.ec.eudi.iso18013.transfer.response.SessionTranscriptBytes
import eu.europa.ec.eudi.prex.PresentationDefinition

class OpenId4VpRequest(val presentationDefinition: PresentationDefinition): Request
class OpenId4VpRequest(val presentationDefinition: PresentationDefinition, val sessionTranscript: SessionTranscriptBytes): Request
Loading
Loading