diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-algorithm-exception/-unsupported-algorithm-exception.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-algorithm-exception/-unsupported-algorithm-exception.md
new file mode 100644
index 00000000..1b7810a7
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-algorithm-exception/-unsupported-algorithm-exception.md
@@ -0,0 +1,6 @@
+//[wallet-core](../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../index.md)/[UnsupportedAlgorithmException](index.md)/[UnsupportedAlgorithmException](-unsupported-algorithm-exception.md)
+
+# UnsupportedAlgorithmException
+
+[androidJvm]\
+constructor()
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-algorithm-exception/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-algorithm-exception/index.md
new file mode 100644
index 00000000..9524be8a
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-algorithm-exception/index.md
@@ -0,0 +1,32 @@
+//[wallet-core](../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../index.md)/[UnsupportedAlgorithmException](index.md)
+
+# UnsupportedAlgorithmException
+
+[androidJvm]\
+class [UnsupportedAlgorithmException](index.md) : [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)
+
+## Constructors
+
+| | |
+|----------------------------------------------------------------------|-------------------------------|
+| [UnsupportedAlgorithmException](-unsupported-algorithm-exception.md) | [androidJvm]
constructor() |
+
+## Functions
+
+| Name | Summary |
+|----------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [addSuppressed](../-unsupported-proof-type-exception/index.md#282858770%2FFunctions%2F1615067946) | [androidJvm]
fun [addSuppressed](../-unsupported-proof-type-exception/index.md#282858770%2FFunctions%2F1615067946)(p0: [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)) |
+| [fillInStackTrace](../-unsupported-proof-type-exception/index.md#-1102069925%2FFunctions%2F1615067946) | [androidJvm]
open fun [fillInStackTrace](../-unsupported-proof-type-exception/index.md#-1102069925%2FFunctions%2F1615067946)(): [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html) |
+| [getLocalizedMessage](../-unsupported-proof-type-exception/index.md#1043865560%2FFunctions%2F1615067946) | [androidJvm]
open fun [getLocalizedMessage](../-unsupported-proof-type-exception/index.md#1043865560%2FFunctions%2F1615067946)(): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) |
+| [getStackTrace](../-unsupported-proof-type-exception/index.md#2050903719%2FFunctions%2F1615067946) | [androidJvm]
open fun [getStackTrace](../-unsupported-proof-type-exception/index.md#2050903719%2FFunctions%2F1615067946)(): [Array](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)<[StackTraceElement](https://developer.android.com/reference/kotlin/java/lang/StackTraceElement.html)> |
+| [getSuppressed](../-unsupported-proof-type-exception/index.md#672492560%2FFunctions%2F1615067946) | [androidJvm]
fun [getSuppressed](../-unsupported-proof-type-exception/index.md#672492560%2FFunctions%2F1615067946)(): [Array](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)<[Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)> |
+| [initCause](../-unsupported-proof-type-exception/index.md#-418225042%2FFunctions%2F1615067946) | [androidJvm]
open fun [initCause](../-unsupported-proof-type-exception/index.md#-418225042%2FFunctions%2F1615067946)(p0: [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)): [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html) |
+| [printStackTrace](../-unsupported-proof-type-exception/index.md#-1769529168%2FFunctions%2F1615067946) | [androidJvm]
open fun [printStackTrace](../-unsupported-proof-type-exception/index.md#-1769529168%2FFunctions%2F1615067946)()
open fun [printStackTrace](../-unsupported-proof-type-exception/index.md#1841853697%2FFunctions%2F1615067946)(p0: [PrintStream](https://developer.android.com/reference/kotlin/java/io/PrintStream.html))
open fun [printStackTrace](../-unsupported-proof-type-exception/index.md#1175535278%2FFunctions%2F1615067946)(p0: [PrintWriter](https://developer.android.com/reference/kotlin/java/io/PrintWriter.html)) |
+| [setStackTrace](../-unsupported-proof-type-exception/index.md#2135801318%2FFunctions%2F1615067946) | [androidJvm]
open fun [setStackTrace](../-unsupported-proof-type-exception/index.md#2135801318%2FFunctions%2F1615067946)(p0: [Array](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)<[StackTraceElement](https://developer.android.com/reference/kotlin/java/lang/StackTraceElement.html)>) |
+
+## Properties
+
+| Name | Summary |
+|-----------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [cause](../-unsupported-proof-type-exception/index.md#-654012527%2FProperties%2F1615067946) | [androidJvm]
open val [cause](../-unsupported-proof-type-exception/index.md#-654012527%2FProperties%2F1615067946): [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)? |
+| [message](../-unsupported-proof-type-exception/index.md#1824300659%2FProperties%2F1615067946) | [androidJvm]
open val [message](../-unsupported-proof-type-exception/index.md#1824300659%2FProperties%2F1615067946): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? |
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-proof-type-exception/-unsupported-proof-type-exception.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-proof-type-exception/-unsupported-proof-type-exception.md
new file mode 100644
index 00000000..a293315b
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-proof-type-exception/-unsupported-proof-type-exception.md
@@ -0,0 +1,6 @@
+//[wallet-core](../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../index.md)/[UnsupportedProofTypeException](index.md)/[UnsupportedProofTypeException](-unsupported-proof-type-exception.md)
+
+# UnsupportedProofTypeException
+
+[androidJvm]\
+constructor()
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-proof-type-exception/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-proof-type-exception/index.md
new file mode 100644
index 00000000..29c8bb0a
--- /dev/null
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-proof-type-exception/index.md
@@ -0,0 +1,32 @@
+//[wallet-core](../../../index.md)/[eu.europa.ec.eudi.wallet.issue.openid4vci](../index.md)/[UnsupportedProofTypeException](index.md)
+
+# UnsupportedProofTypeException
+
+[androidJvm]\
+class [UnsupportedProofTypeException](index.md) : [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)
+
+## Constructors
+
+| | |
+|-----------------------------------------------------------------------|-------------------------------|
+| [UnsupportedProofTypeException](-unsupported-proof-type-exception.md) | [androidJvm]
constructor() |
+
+## Functions
+
+| Name | Summary |
+|---------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [addSuppressed](index.md#282858770%2FFunctions%2F1615067946) | [androidJvm]
fun [addSuppressed](index.md#282858770%2FFunctions%2F1615067946)(p0: [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)) |
+| [fillInStackTrace](index.md#-1102069925%2FFunctions%2F1615067946) | [androidJvm]
open fun [fillInStackTrace](index.md#-1102069925%2FFunctions%2F1615067946)(): [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html) |
+| [getLocalizedMessage](index.md#1043865560%2FFunctions%2F1615067946) | [androidJvm]
open fun [getLocalizedMessage](index.md#1043865560%2FFunctions%2F1615067946)(): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html) |
+| [getStackTrace](index.md#2050903719%2FFunctions%2F1615067946) | [androidJvm]
open fun [getStackTrace](index.md#2050903719%2FFunctions%2F1615067946)(): [Array](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)<[StackTraceElement](https://developer.android.com/reference/kotlin/java/lang/StackTraceElement.html)> |
+| [getSuppressed](index.md#672492560%2FFunctions%2F1615067946) | [androidJvm]
fun [getSuppressed](index.md#672492560%2FFunctions%2F1615067946)(): [Array](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)<[Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)> |
+| [initCause](index.md#-418225042%2FFunctions%2F1615067946) | [androidJvm]
open fun [initCause](index.md#-418225042%2FFunctions%2F1615067946)(p0: [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)): [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html) |
+| [printStackTrace](index.md#-1769529168%2FFunctions%2F1615067946) | [androidJvm]
open fun [printStackTrace](index.md#-1769529168%2FFunctions%2F1615067946)()
open fun [printStackTrace](index.md#1841853697%2FFunctions%2F1615067946)(p0: [PrintStream](https://developer.android.com/reference/kotlin/java/io/PrintStream.html))
open fun [printStackTrace](index.md#1175535278%2FFunctions%2F1615067946)(p0: [PrintWriter](https://developer.android.com/reference/kotlin/java/io/PrintWriter.html)) |
+| [setStackTrace](index.md#2135801318%2FFunctions%2F1615067946) | [androidJvm]
open fun [setStackTrace](index.md#2135801318%2FFunctions%2F1615067946)(p0: [Array](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/index.html)<[StackTraceElement](https://developer.android.com/reference/kotlin/java/lang/StackTraceElement.html)>) |
+
+## Properties
+
+| Name | Summary |
+|----------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [cause](index.md#-654012527%2FProperties%2F1615067946) | [androidJvm]
open val [cause](index.md#-654012527%2FProperties%2F1615067946): [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html)? |
+| [message](index.md#1824300659%2FProperties%2F1615067946) | [androidJvm]
open val [message](index.md#1824300659%2FProperties%2F1615067946): [String](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html)? |
diff --git a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/index.md b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/index.md
index d3dfc06b..015adbb0 100644
--- a/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/index.md
+++ b/docs/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/index.md
@@ -4,9 +4,11 @@
## Types
-| Name | Summary |
-|---|---|
-| [IssueEvent](-issue-event/index.md) | [androidJvm]
interface [IssueEvent](-issue-event/index.md) |
-| [Offer](-offer/index.md) | [androidJvm]
interface [Offer](-offer/index.md)
An offer of credentials to be issued. |
-| [OfferResult](-offer-result/index.md) | [androidJvm]
interface [OfferResult](-offer-result/index.md)
The result of an offer operation. |
-| [OpenId4VciManager](-open-id4-vci-manager/index.md) | [androidJvm]
interface [OpenId4VciManager](-open-id4-vci-manager/index.md)
OpenId4VciManager is the main entry point to issue documents using the OpenId4Vci protocol It provides methods to issue documents using a document type or an offer, and to resolve an offer |
+| Name | Summary |
+|-----------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [IssueEvent](-issue-event/index.md) | [androidJvm]
interface [IssueEvent](-issue-event/index.md) |
+| [Offer](-offer/index.md) | [androidJvm]
interface [Offer](-offer/index.md)
An offer of credentials to be issued. |
+| [OfferResult](-offer-result/index.md) | [androidJvm]
interface [OfferResult](-offer-result/index.md)
The result of an offer operation. |
+| [OpenId4VciManager](-open-id4-vci-manager/index.md) | [androidJvm]
interface [OpenId4VciManager](-open-id4-vci-manager/index.md)
OpenId4VciManager is the main entry point to issue documents using the OpenId4Vci protocol It provides methods to issue documents using a document type or an offer, and to resolve an offer |
+| [UnsupportedAlgorithmException](-unsupported-algorithm-exception/index.md) | [androidJvm]
class [UnsupportedAlgorithmException](-unsupported-algorithm-exception/index.md) : [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html) |
+| [UnsupportedProofTypeException](-unsupported-proof-type-exception/index.md) | [androidJvm]
class [UnsupportedProofTypeException](-unsupported-proof-type-exception/index.md) : [Throwable](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throwable/index.html) |
diff --git a/docs/wallet-core/package-list b/docs/wallet-core/package-list
index ff216ba2..7ec9b09e 100644
--- a/docs/wallet-core/package-list
+++ b/docs/wallet-core/package-list
@@ -96,6 +96,10 @@ $dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager/reso
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager/resumeWithAuthorization/#android.content.Intent/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/resume-with-authorization.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager/resumeWithAuthorization/#android.net.Uri/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/resume-with-authorization.md
$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/OpenId4VciManager/resumeWithAuthorization/#kotlin.String/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-open-id4-vci-manager/resume-with-authorization.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/UnsupportedAlgorithmException///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-algorithm-exception/index.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/UnsupportedAlgorithmException/UnsupportedAlgorithmException/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-algorithm-exception/-unsupported-algorithm-exception.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/UnsupportedProofTypeException///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-proof-type-exception/index.md
+$dokka.location:eu.europa.ec.eudi.wallet.issue.openid4vci/UnsupportedProofTypeException/UnsupportedProofTypeException/#/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.issue.openid4vci/-unsupported-proof-type-exception/-unsupported-proof-type-exception.md
$dokka.location:eu.europa.ec.eudi.wallet.transfer.openid4vp////PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.transfer.openid4vp/index.md
$dokka.location:eu.europa.ec.eudi.wallet.transfer.openid4vp/ClientIdScheme.Preregistered///PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.transfer.openid4vp/-client-id-scheme/-preregistered/index.md
$dokka.location:eu.europa.ec.eudi.wallet.transfer.openid4vp/ClientIdScheme.Preregistered/Preregistered/#kotlin.collections.List[eu.europa.ec.eudi.wallet.transfer.openid4vp.PreregisteredVerifier]/PointingToDeclaration/wallet-core/eu.europa.ec.eudi.wallet.transfer.openid4vp/-client-id-scheme/-preregistered/-preregistered.md
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/CWTProofSigner.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/CWTProofSigner.kt
index 62c8545c..aef084be 100644
--- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/CWTProofSigner.kt
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/CWTProofSigner.kt
@@ -24,12 +24,25 @@ import eu.europa.ec.eudi.openid4vci.PopSigner
import eu.europa.ec.eudi.wallet.document.Algorithm
import eu.europa.ec.eudi.wallet.document.IssuanceRequest
+/**
+ * A [ProofSigner] and [PopSigner.Cwt] implementation for CWT.
+ * @property issuanceRequest the issuance request
+ * @property coseAlgorithm the COSE algorithm to use
+ * @property coseCurve the COSE curve to use
+ * @constructor Creates a CWT proof signer.
+ * @param issuanceRequest The issuance request.
+ * @param coseAlgorithm The COSE algorithm to use.
+ * @param coseCurve The COSE curve to use.
+ */
internal class CWTProofSigner(
private val issuanceRequest: IssuanceRequest,
private val coseAlgorithm: CoseAlgorithm,
private val coseCurve: CoseCurve
) : ProofSigner() {
+ /**
+ * The JWK of the public key.
+ */
private val jwk = JWK.parseFromPEMEncodedObjects(issuanceRequest.publicKey.pem)
override val popSigner: PopSigner.Cwt = PopSigner.Cwt(
algorithm = coseAlgorithm,
@@ -43,6 +56,13 @@ internal class CWTProofSigner(
CWTAlgorithmMap[it] ?: throw UnsupportedAlgorithmException()
}
+ /**
+ * Signs the signing input with the authentication key from issuance request for the given algorithm and curve.
+ * @param signingInput The input to sign.
+ * @throws UserAuthRequiredException If user authentication is required.
+ * @throws Throwable If an error occurs during signing.
+ * @return The signature of the signing input.
+ */
fun sign(signingInput: ByteArray): ByteArray {
return doSign(issuanceRequest, signingInput, algorithm)
}
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Exceptions.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Exceptions.kt
index f6e5a9e6..119de4a9 100644
--- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Exceptions.kt
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Exceptions.kt
@@ -16,6 +16,6 @@
package eu.europa.ec.eudi.wallet.issue.openid4vci
-class UserAuthRequiredException : Throwable()
+internal class UserAuthRequiredException : Throwable()
class UnsupportedAlgorithmException : Throwable()
class UnsupportedProofTypeException : Throwable()
\ No newline at end of file
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSDPoPSigner.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSDPoPSigner.kt
index 2f2a0436..0aed4c5f 100644
--- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSDPoPSigner.kt
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSDPoPSigner.kt
@@ -35,7 +35,11 @@ import java.security.Signature
import java.time.Instant
import java.util.*
-class JWSDPoPSigner private constructor() {
+internal class JWSDPoPSigner private constructor() : JWSSigner {
+
+ private val jcaContext = JCAContext()
+
+ override fun getJCAContext(): JCAContext = jcaContext
private val keyStore: KeyStore
get() = KeyStore.getInstance("AndroidKeyStore").apply { load(null) }
@@ -47,38 +51,30 @@ class JWSDPoPSigner private constructor() {
get() = PopSigner.Jwt(
algorithm = SupportedAlgorithms.keys.first(),
bindingKey = JwtBindingKey.Jwk(jwk),
- jwsSigner = jwsSigner
+ jwsSigner = this
)
init {
generateKeyPair()
}
- private val jwsSigner: JWSSigner
- get() = object : JWSSigner {
-
- private val jcaContext = JCAContext()
-
- override fun getJCAContext(): JCAContext = jcaContext
-
- override fun sign(header: JWSHeader, signingInput: ByteArray): Base64URL {
- val algorithm = SupportedAlgorithms[header.algorithm]
- ?: throw JOSEException(
- AlgorithmSupportMessage.unsupportedJWSAlgorithm(
- header.algorithm,
- supportedJWSAlgorithms()
- )
- )
- val privateKey = (keyStore.getEntry(KEY_ALIAS, null) as KeyStore.PrivateKeyEntry).privateKey
- val signature = Signature.getInstance(algorithm).apply {
- initSign(privateKey)
- update(signingInput)
- }.sign()
- return Base64URL.encode(signature.derToJose(header.algorithm))
- }
+ override fun sign(header: JWSHeader, signingInput: ByteArray): Base64URL {
+ val algorithm = SupportedAlgorithms[header.algorithm]
+ ?: throw JOSEException(
+ AlgorithmSupportMessage.unsupportedJWSAlgorithm(
+ header.algorithm,
+ supportedJWSAlgorithms()
+ )
+ )
+ val privateKey = (keyStore.getEntry(KEY_ALIAS, null) as KeyStore.PrivateKeyEntry).privateKey
+ val signature = Signature.getInstance(algorithm).apply {
+ initSign(privateKey)
+ update(signingInput)
+ }.sign()
+ return Base64URL.encode(signature.derToJose(header.algorithm))
+ }
- override fun supportedJWSAlgorithms(): MutableSet = SupportedAlgorithms.keys.toMutableSet()
- }
+ override fun supportedJWSAlgorithms(): MutableSet = SupportedAlgorithms.keys.toMutableSet()
private fun generateKeyPair() {
if (keyStore.containsAlias(KEY_ALIAS)) {
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSProofSigner.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSProofSigner.kt
index 6dd680c9..2a9201a9 100644
--- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSProofSigner.kt
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/JWSProofSigner.kt
@@ -31,6 +31,14 @@ import eu.europa.ec.eudi.openid4vci.ProofTypeMeta
import eu.europa.ec.eudi.wallet.document.Algorithm
import eu.europa.ec.eudi.wallet.document.IssuanceRequest
+/**
+ * A [ProofSigner] and [JWSSigner] implementation for JWS.
+ * @property issuanceRequest the issuance request
+ * @constructor Creates a JWS proof signer.
+ * @param issuanceRequest The issuance request.
+ * @param jwsAlgorithm The JWS algorithm to use.
+ *
+ */
internal class JWSProofSigner(
private val issuanceRequest: IssuanceRequest,
jwsAlgorithm: JWSAlgorithm
@@ -38,6 +46,9 @@ internal class JWSProofSigner(
private val jcaContext = JCAContext()
+ /**
+ * The JWK of the public key.
+ */
private val jwk = JWK.parseFromPEMEncodedObjects(issuanceRequest.publicKey.pem)
override val popSigner: PopSigner.Jwt = PopSigner.Jwt(
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/ProofSigner.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/ProofSigner.kt
index 07956cc2..ed7e4864 100644
--- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/ProofSigner.kt
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/ProofSigner.kt
@@ -23,11 +23,26 @@ import eu.europa.ec.eudi.wallet.document.Algorithm
import eu.europa.ec.eudi.wallet.document.IssuanceRequest
import eu.europa.ec.eudi.wallet.document.SignedWithAuthKeyResult
+/**
+ * Abstract class for signing proofs.
+ *
+ * @property popSigner The signer for the proof of possession as required by the vci library.
+ * @property userAuthStatus The status of the user authentication.
+ */
internal abstract class ProofSigner {
abstract val popSigner: PopSigner
var userAuthStatus: UserAuthStatus = UserAuthStatus.NotRequired
protected set
+ /**
+ * Signs the signing input with the authentication key from issuance request for the given algorithm.
+ * @param issuanceRequest The issuance request.
+ * @param signingInput The input to sign.
+ * @param algorithm The algorithm to use for signing.
+ * @throws UserAuthRequiredException If user authentication is required.
+ * @throws Throwable If an error occurs during signing.
+ * @return The signature of the signing input.
+ */
protected fun doSign(
issuanceRequest: IssuanceRequest,
signingInput: ByteArray,
@@ -46,12 +61,22 @@ internal abstract class ProofSigner {
}
}
- companion object Factory {
+ /**
+ * Companion object for the ProofSigner class.
+ * @property SupportedProofTypes The supported proof types.
+ */
+ companion object {
val SupportedProofTypes = mapOf(
ProofType.JWT to ProofTypeMeta.Jwt(listOf(JWSAlgorithm.ES256)),
ProofType.CWT to ProofTypeMeta.Cwt(listOf(CoseAlgorithm.ES256), listOf(CoseCurve.P_256))
)
+ /**
+ * Selects the supported proof type from the issuer supported proof types.
+ * @param issuerSupportedProofTypes The issuer supported proof types.
+ * @return The supported proof type or null if none is supported.
+ */
+ @JvmStatic
fun selectSupportedProofType(issuerSupportedProofTypes: ProofTypesSupported): ProofTypeMeta? {
return issuerSupportedProofTypes.values
.firstOrNull { it.type() in SupportedProofTypes.keys }
@@ -64,11 +89,23 @@ internal abstract class ProofSigner {
}
}
+ /**
+ * Selects the supported algorithm from given JWT proof type metadata.
+ * @param metadata The proof type metadata.
+ * @return The supported algorithm or null if none is supported.
+ */
+ @JvmStatic
fun selectSupportedAlgorithm(metadata: ProofTypeMeta.Jwt): JWSAlgorithm? {
val supportedType = SupportedProofTypes[ProofType.JWT] as ProofTypeMeta.Jwt
return supportedType.algorithms.firstOrNull { it in metadata.algorithms }
}
+ /**
+ * Selects the supported algorithm and curve from given CWT proof type metadata.
+ * @param metadata The proof type metadata.
+ * @return The supported algorithm and curve or null if none is supported.
+ */
+ @JvmStatic
fun selectSupportedAlgorithm(metadata: ProofTypeMeta.Cwt): Pair? {
val supportedType = SupportedProofTypes[ProofType.CWT] as ProofTypeMeta.Cwt
return supportedType.algorithms.firstOrNull { it in metadata.algorithms }
@@ -79,11 +116,27 @@ internal abstract class ProofSigner {
}
+ /**
+ * Creates a proof signer for the given issuance request and credential configuration.
+ * @param issuanceRequest The issuance request.
+ * @param credentialConfiguration The credential configuration.
+ * @return The proof signer or a failure if the proof type is not supported.
+ */
+ @JvmStatic
operator fun invoke(
issuanceRequest: IssuanceRequest,
credentialConfiguration: CredentialConfiguration,
) = invoke(issuanceRequest, credentialConfiguration.proofTypesSupported)
+ /**
+ * Creates a proof signer for the given issuance request and issuer supported proof types.
+ * The proof signer is selected based on the issuer supported proof types and the [SupportedProofTypes]
+ * of the [ProofSigner].
+ * @param issuanceRequest The issuance request.
+ * @param issuerSupportedProofTypes The issuer supported proof types.
+ * @return The proof signer or a failure if the proof type is not supported.
+ */
+ @JvmStatic
operator fun invoke(
issuanceRequest: IssuanceRequest,
issuerSupportedProofTypes: ProofTypesSupported,
@@ -101,14 +154,25 @@ internal abstract class ProofSigner {
CWTProofSigner(issuanceRequest, alg, crv)
}
- else -> null
+ else -> null // should never happen. LDP_VP is not supported in [SupportedProofTypes]
}?.let { Result.success(it) }
- ?: Result.failure(UnsupportedProofTypeException())
+ ?: Result.failure(UnsupportedAlgorithmException())
}
}
+ /**
+ * Sealed interface for the user authentication status.
+ */
sealed interface UserAuthStatus {
+ /**
+ * User authentication is not required.
+ */
object NotRequired : UserAuthStatus
+
+ /**
+ * User authentication is required.
+ * @property cryptoObject The crypto object to use for authentication.
+ */
data class Required(val cryptoObject: CryptoObject? = null) : UserAuthStatus
}
}
\ No newline at end of file
diff --git a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Utils.kt b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Utils.kt
index 0a0998ad..9390c0bd 100644
--- a/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Utils.kt
+++ b/wallet-core/src/main/java/eu/europa/ec/eudi/wallet/issue/openid4vci/Utils.kt
@@ -23,7 +23,7 @@ import eu.europa.ec.eudi.openid4vci.MsoMdocCredential
import eu.europa.ec.eudi.wallet.document.CreateIssuanceRequestResult
import eu.europa.ec.eudi.wallet.document.DocumentManager
import eu.europa.ec.eudi.wallet.document.IssuanceRequest
-import eu.europa.ec.eudi.wallet.issue.openid4vci.ProofSigner.Factory.selectSupportedProofType
+import eu.europa.ec.eudi.wallet.issue.openid4vci.ProofSigner.Companion.selectSupportedProofType
import org.bouncycastle.util.io.pem.PemObject
import org.bouncycastle.util.io.pem.PemWriter
import java.io.StringWriter