Skip to content

Commit

Permalink
Merge branch 'release/2.1.0' into feature/kmmresult15
Browse files Browse the repository at this point in the history
  • Loading branch information
JesusMcCloud committed Aug 25, 2023
2 parents 7f6ed1d + 5cc7d83 commit bf4521a
Show file tree
Hide file tree
Showing 34 changed files with 409 additions and 368 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# Changelog

Release 2.1.0:
- tbd
- Creating, issung, managing and verifying ISO/IEC 18013-5:2021 credentials
- Kotlin 1.9
- Generic structure for public keys
- kotlinx.serialization fork with CBOR enhancements for COSE support

Release 2.0.2:
- `vclib-openid`: Add response modes for query and fragment, i.e. Wallet may return the authentication response in query params or as fragment params on a SIOPv2 call
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# KMM VC Library
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-brightgreen.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0)
[![Kotlin](https://img.shields.io/badge/kotlin-multiplatform--mobile-orange.svg?logo=kotlin)](http://kotlinlang.org)
[![Kotlin](https://img.shields.io/badge/kotlin-1.8.10-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![Kotlin](https://img.shields.io/badge/kotlin-1.9.0-blue.svg?logo=kotlin)](http://kotlinlang.org)
![Java](https://img.shields.io/badge/java-11-blue.svg?logo=OPENJDK)
[![Maven Central](https://img.shields.io/maven-central/v/at.asitplus.wallet/vclib)](https://mvnrepository.com/artifact/at.asitplus.wallet/vclib/)

This [Kotlin Multiplatform](https://kotlinlang.org/docs/multiplatform.html) library implements the [W3C VC Data Model](https://w3c.github.io/vc-data-model/) to support several use cases of verifiable credentials, verifiable presentations, and validation thereof. This library may be shared between Wallet Apps, Verifier Apps and a Backend Service issuing credentials.


## Architecture

This library was built with [Kotlin Multiplatform](https://kotlinlang.org/docs/multiplatform.html) and [Multiplatform Mobile](https://kotlinlang.org/lp/mobile/) in mind. Its primary targets are JVM, Android and iOS. In order to achieve smooth usage especially under iOS, there have been some notable design decisions:
Expand Down
1 change: 0 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ plugins {

//access dokka plugin from conventions plugin's classpath in root project → no need to specify version
apply(plugin = "org.jetbrains.dokka")

tasks.getByName("dokkaHtmlMultiModule") {
(this as DokkaMultiModuleTask)
outputDirectory.set(File("$buildDir/dokka"))
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ kotlin.experimental.tryK2=false
# workaround dokka bug (need to wait for next snapshot build)
org.jetbrains.dokka.classpath.excludePlatformDependencyFiles=true

artifactVersion = 2.1.0-SNAPSHOT
artifactVersion = 2.1.0
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ class IssueCredentialProtocolTest : FreeSpec({
oobInvitation.shouldBeInstanceOf<InternalNextMessage.SendAndWrap>()
val invitationMessage = oobInvitation.message

val parsedInvitation = holderProtocol.parseMessage(invitationMessage, issuerCryptoService.toJsonWebKey())
val parsedInvitation = holderProtocol.parseMessage(invitationMessage, issuerCryptoService.toPublicKey().toJsonWebKey())
parsedInvitation.shouldBeInstanceOf<InternalNextMessage.SendAndWrap>()
val requestCredential = parsedInvitation.message

val parsedRequestCredential = issuerProtocol.parseMessage(requestCredential, holderCryptoService.toJsonWebKey())
val parsedRequestCredential = issuerProtocol.parseMessage(requestCredential, holderCryptoService.toPublicKey().toJsonWebKey())
parsedRequestCredential.shouldBeInstanceOf<InternalNextMessage.SendAndWrap>()
val issueCredential = parsedRequestCredential.message

val parsedIssueCredential = holderProtocol.parseMessage(issueCredential, issuerCryptoService.toJsonWebKey())
val parsedIssueCredential = holderProtocol.parseMessage(issueCredential, issuerCryptoService.toPublicKey().toJsonWebKey())
parsedIssueCredential.shouldBeInstanceOf<InternalNextMessage.Finished>()

val issuedCredential = parsedIssueCredential.lastMessage
Expand All @@ -70,11 +70,11 @@ class IssueCredentialProtocolTest : FreeSpec({
requestCredential.shouldBeInstanceOf<InternalNextMessage.SendAndWrap>()

val parsedRequestCredential =
issuerProtocol.parseMessage(requestCredential.message, holderCryptoService.toJsonWebKey())
issuerProtocol.parseMessage(requestCredential.message, holderCryptoService.toPublicKey().toJsonWebKey())
parsedRequestCredential.shouldBeInstanceOf<InternalNextMessage.SendAndWrap>()
val issueCredential = parsedRequestCredential.message

val parsedIssueCredential = holderProtocol.parseMessage(issueCredential, issuerCryptoService.toJsonWebKey())
val parsedIssueCredential = holderProtocol.parseMessage(issueCredential, issuerCryptoService.toPublicKey().toJsonWebKey())
parsedIssueCredential.shouldBeInstanceOf<InternalNextMessage.Finished>()

val issuedCredential = parsedIssueCredential.lastMessage
Expand All @@ -88,7 +88,7 @@ class IssueCredentialProtocolTest : FreeSpec({
threadId = uuid4().toString(),
attachment = JwmAttachment(id = uuid4().toString(), "mimeType", JwmAttachmentData())
),
issuerCryptoService.toJsonWebKey()
issuerCryptoService.toPublicKey().toJsonWebKey()
)
parsed.shouldBeInstanceOf<InternalNextMessage.IncorrectState>()
}
Expand All @@ -98,7 +98,7 @@ class IssueCredentialProtocolTest : FreeSpec({
oobInvitation.shouldBeInstanceOf<InternalNextMessage.SendAndWrap>()
val invitationMessage = oobInvitation.message

val parsedInvitation = holderProtocol.parseMessage(invitationMessage, issuerCryptoService.toJsonWebKey())
val parsedInvitation = holderProtocol.parseMessage(invitationMessage, issuerCryptoService.toPublicKey().toJsonWebKey())
parsedInvitation.shouldBeInstanceOf<InternalNextMessage.SendAndWrap>()
val requestCredential = parsedInvitation.message

Expand All @@ -116,7 +116,7 @@ class IssueCredentialProtocolTest : FreeSpec({
)
)
val parsedRequestCredential =
issuerProtocol.parseMessage(wrongRequestCredential, holderCryptoService.toJsonWebKey())
issuerProtocol.parseMessage(wrongRequestCredential, holderCryptoService.toPublicKey().toJsonWebKey())
parsedRequestCredential.shouldBeInstanceOf<InternalNextMessage.SendProblemReport>()
val problemReport = parsedRequestCredential.message

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,16 @@ class PresentProofProtocolTest : FreeSpec({
oobInvitation.shouldBeInstanceOf<InternalNextMessage.SendAndWrap>()
val invitationMessage = oobInvitation.message

val parsedInvitation = verifierProtocol.parseMessage(invitationMessage, holderCryptoService.toJsonWebKey())
val parsedInvitation = verifierProtocol.parseMessage(invitationMessage, holderCryptoService.toPublicKey().toJsonWebKey())
parsedInvitation.shouldBeInstanceOf<InternalNextMessage.SendAndWrap>()
val requestPresentation = parsedInvitation.message

val parsedRequestPresentation =
holderProtocol.parseMessage(requestPresentation, verifierCryptoService.toJsonWebKey())
holderProtocol.parseMessage(requestPresentation, verifierCryptoService.toPublicKey().toJsonWebKey())
parsedRequestPresentation.shouldBeInstanceOf<InternalNextMessage.SendAndWrap>()
val presentation = parsedRequestPresentation.message

val parsedPresentation = verifierProtocol.parseMessage(presentation, holderCryptoService.toJsonWebKey())
val parsedPresentation = verifierProtocol.parseMessage(presentation, holderCryptoService.toPublicKey().toJsonWebKey())
parsedPresentation.shouldBeInstanceOf<InternalNextMessage.Finished>()

val receivedPresentation = parsedPresentation.lastMessage
Expand All @@ -89,11 +89,11 @@ class PresentProofProtocolTest : FreeSpec({
requestPresentation.shouldBeInstanceOf<InternalNextMessage.SendAndWrap>()

val parsedRequestPresentation =
holderProtocol.parseMessage(requestPresentation.message, verifierCryptoService.toJsonWebKey())
holderProtocol.parseMessage(requestPresentation.message, verifierCryptoService.toPublicKey().toJsonWebKey())
parsedRequestPresentation.shouldBeInstanceOf<InternalNextMessage.SendAndWrap>()
val presentation = parsedRequestPresentation.message

val parsedPresentation = verifierProtocol.parseMessage(presentation, holderCryptoService.toJsonWebKey())
val parsedPresentation = verifierProtocol.parseMessage(presentation, holderCryptoService.toPublicKey().toJsonWebKey())
parsedPresentation.shouldBeInstanceOf<InternalNextMessage.Finished>()

val receivedPresentation = parsedPresentation.lastMessage
Expand All @@ -107,7 +107,7 @@ class PresentProofProtocolTest : FreeSpec({
parentThreadId = uuid4().toString(),
attachment = JwmAttachment(id = uuid4().toString(), "mimeType", JwmAttachmentData())
),
holderCryptoService.toJsonWebKey()
holderCryptoService.toPublicKey().toJsonWebKey()
)
parsed.shouldBeInstanceOf<InternalNextMessage.IncorrectState>()
}
Expand All @@ -117,12 +117,12 @@ class PresentProofProtocolTest : FreeSpec({
oobInvitation.shouldBeInstanceOf<InternalNextMessage.SendAndWrap>()
val invitationMessage = oobInvitation.message

val parsedInvitation = verifierProtocol.parseMessage(invitationMessage, holderCryptoService.toJsonWebKey())
val parsedInvitation = verifierProtocol.parseMessage(invitationMessage, holderCryptoService.toPublicKey().toJsonWebKey())
parsedInvitation.shouldBeInstanceOf<InternalNextMessage.SendAndWrap>()
val requestPresentation = parsedInvitation.message

val parsedRequestPresentation =
holderProtocol.parseMessage(requestPresentation, verifierCryptoService.toJsonWebKey())
holderProtocol.parseMessage(requestPresentation, verifierCryptoService.toPublicKey().toJsonWebKey())
parsedRequestPresentation.shouldBeInstanceOf<InternalNextMessage.SendProblemReport>()
val problemReport = parsedRequestPresentation.message

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package at.asitplus.wallet.lib.oidc

import at.asitplus.wallet.lib.CryptoPublicKey
import at.asitplus.wallet.lib.agent.CryptoService
import at.asitplus.wallet.lib.agent.DefaultVerifierCryptoService
import at.asitplus.wallet.lib.agent.Verifier
Expand All @@ -18,7 +19,6 @@ import at.asitplus.wallet.lib.data.dif.SchemaReference
import at.asitplus.wallet.lib.iso.IsoDataModelConstants.NAMESPACE_MDL
import at.asitplus.wallet.lib.jws.DefaultJwsService
import at.asitplus.wallet.lib.jws.DefaultVerifierJwsService
import at.asitplus.wallet.lib.jws.JsonWebKey
import at.asitplus.wallet.lib.jws.JwsAlgorithm
import at.asitplus.wallet.lib.jws.JwsHeader
import at.asitplus.wallet.lib.jws.JwsService
Expand Down Expand Up @@ -54,7 +54,7 @@ import kotlin.time.toDuration
class OidcSiopVerifier(
private val verifier: Verifier,
private val relyingPartyUrl: String,
private val agentPublicKey: JsonWebKey,
private val agentPublicKey: CryptoPublicKey,
private val jwsService: JwsService,
private val verifierJwsService: VerifierJwsService,
timeLeewaySeconds: Long = 300L,
Expand All @@ -80,7 +80,7 @@ class OidcSiopVerifier(
) = OidcSiopVerifier(
verifier = verifier,
relyingPartyUrl = relyingPartyUrl,
agentPublicKey = cryptoService.toJsonWebKey(),
agentPublicKey = cryptoService.toPublicKey(),
jwsService = jwsService,
verifierJwsService = verifierJwsService,
timeLeewaySeconds = timeLeewaySeconds,
Expand Down Expand Up @@ -175,7 +175,7 @@ class OidcSiopVerifier(
)
val metadata = RelyingPartyMetadata(
redirectUris = arrayOf(relyingPartyUrl),
jsonWebKeySet = JsonWebKeySet(arrayOf(agentPublicKey)),
jsonWebKeySet = JsonWebKeySet(arrayOf(agentPublicKey.toJsonWebKey())),
subjectSyntaxTypesSupported = arrayOf(URN_TYPE_JWK_THUMBPRINT, PREFIX_DID_KEY),
vpFormats = vpFormats,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package at.asitplus.wallet.lib.oidc

import at.asitplus.KmmResult
import at.asitplus.wallet.lib.CryptoPublicKey
import at.asitplus.wallet.lib.agent.CryptoService
import at.asitplus.wallet.lib.agent.Holder
import at.asitplus.wallet.lib.data.dif.ClaimFormatEnum
import at.asitplus.wallet.lib.data.dif.PresentationSubmission
import at.asitplus.wallet.lib.data.dif.PresentationSubmissionDescriptor
import at.asitplus.wallet.lib.jws.DefaultJwsService
import at.asitplus.wallet.lib.jws.DefaultVerifierJwsService
import at.asitplus.wallet.lib.jws.JsonWebKey
import at.asitplus.wallet.lib.jws.JwsAlgorithm
import at.asitplus.wallet.lib.jws.JwsHeader
import at.asitplus.wallet.lib.jws.JwsService
Expand Down Expand Up @@ -48,7 +48,7 @@ import kotlin.time.Duration.Companion.seconds
*/
class OidcSiopWallet(
private val holder: Holder,
private val agentPublicKey: JsonWebKey,
private val agentPublicKey: CryptoPublicKey,
private val jwsService: JwsService,
private val verifierJwsService: VerifierJwsService = DefaultVerifierJwsService(),
private val clock: Clock = Clock.System,
Expand All @@ -65,7 +65,7 @@ class OidcSiopWallet(
clientId: String = "https://wallet.a-sit.at/"
) = OidcSiopWallet(
holder = holder,
agentPublicKey = cryptoService.toJsonWebKey(),
agentPublicKey = cryptoService.toPublicKey(),
jwsService = jwsService,
verifierJwsService = verifierJwsService,
clock = clock,
Expand Down Expand Up @@ -218,9 +218,9 @@ class OidcSiopWallet(
val now = clock.now()
// we'll assume jwk-thumbprint
val idToken = IdToken(
issuer = agentPublicKey.jwkThumbprint,
subject = agentPublicKey.jwkThumbprint,
subjectJwk = agentPublicKey,
issuer = agentPublicKey.toJsonWebKey().jwkThumbprint,
subject = agentPublicKey.toJsonWebKey().jwkThumbprint,
subjectJwk = agentPublicKey.toJsonWebKey(),
audience = params.redirectUrl,
issuedAt = now,
expiration = now + 60.seconds,
Expand Down
Loading

0 comments on commit bf4521a

Please sign in to comment.