Skip to content

Commit

Permalink
Add: TokenStatusList RFC Draft 5
Browse files Browse the repository at this point in the history
  • Loading branch information
acrusage-iaik committed Dec 5, 2024
1 parent a61ebf6 commit 26d70af
Show file tree
Hide file tree
Showing 147 changed files with 4,134 additions and 151 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Release 5.2.0:
- Add extension functions to `JwsService` to create JWTs for OAuth 2.0 Attestation-Based Client Authentication
- New artefact `vck-openid-ktor` implements a ktor client for OpenID for Verifiable Credential Issuance and OpenID for Verifiable Presentations
- Remove `scopePresentationDefinitionRetriever` from `OidcSiopWallet` to keep implementation simple
- Add rfcs 7519, 8392, 9596, a shell of 3986 and the draft for token status list

Release 5.1.0:
- Drop ARIES protocol implementation, and the `vck-aries` artifact
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ interface Holder {
* @return `true` if the revocation list has been validated and set, `false` otherwise
*/
fun setRevocationList(it: String): Boolean
fun setRevocationStatusListJwt(it: String): Boolean

sealed class StoreCredentialInput {
data class Vc(
Expand All @@ -56,15 +57,15 @@ interface Holder {
* Stores the verifiable credential in [credential] if it parses and validates,
* and returns it for future reference.
*
* Note: Revocation credentials should not be stored, but set with [setRevocationList].
* Note: Revocation credentials should not be stored, but set with [setRevocationStatusListJwt].
*/
suspend fun storeCredential(credential: StoreCredentialInput): KmmResult<StoredCredential>

/**
* Gets a list of all stored credentials, with a revocation status.
*
* Note that the revocation status may be [Validator.RevocationStatus.UNKNOWN] if no revocation list
* has been set with [setRevocationList]
* has been set with [setRevocationStatusListJwt]
*/
suspend fun getCredentials(): Collection<StoredCredential>?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import io.github.aakira.napier.Napier
* An agent that only implements [Holder], i.e. it can receive credentials form other agents
* and present credentials to other agents.
*/
@ExperimentalUnsignedTypes
class HolderAgent(
private val validator: Validator = Validator(),
private val subjectCredentialStore: SubjectCredentialStore = InMemorySubjectCredentialStore(),
Expand Down Expand Up @@ -52,14 +53,18 @@ class HolderAgent(
* @return `true` if the revocation list has been validated and set, `false` otherwise
*/
override fun setRevocationList(it: String): Boolean {
return validator.setRevocationList(it)
return validator.setRevocationListCredential(it)
}

override fun setRevocationStatusListJwt(it: String): Boolean {
return validator.setRevocationStatusListJwt(it)
}

/**
* Stores the verifiable credential in [credential] if it parses and validates,
* and returns it for future reference.
*
* Note: Revocation credentials should not be stored, but set with [setRevocationList].
* Note: Revocation credentials should not be stored, but set with [setRevocationStatusListJwt].
*/
override suspend fun storeCredential(credential: Holder.StoreCredentialInput) = catching {
when (credential) {
Expand Down Expand Up @@ -109,7 +114,7 @@ class HolderAgent(
* Gets a list of all stored credentials, with a revocation status.
*
* Note that the revocation status may be [Validator.RevocationStatus.UNKNOWN] if no revocation list
* has been set with [setRevocationList]
* has been set with [setRevocationStatusListJwt]
*/
override suspend fun getCredentials(): Collection<Holder.StoredCredential>? {
val credentials = subjectCredentialStore.getCredentials().getOrNull()
Expand All @@ -119,15 +124,18 @@ class HolderAgent(

private fun SubjectCredentialStore.StoreEntry.toStoredCredential() = when (this) {
is SubjectCredentialStore.StoreEntry.Iso -> Holder.StoredCredential.Iso(
this, Validator.RevocationStatus.UNKNOWN
this,
Validator.RevocationStatus.UNKNOWN,
)

is SubjectCredentialStore.StoreEntry.Vc -> Holder.StoredCredential.Vc(
this, validator.checkRevocationStatus(vc)
this,
validator.checkRevocationStatus(vc),
)

is SubjectCredentialStore.StoreEntry.SdJwt -> Holder.StoredCredential.SdJwt(
this, validator.checkRevocationStatus(sdJwt)
this,
validator.checkRevocationStatus(sdJwt),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class InMemoryIssuerCredentialStore : IssuerCredentialStore {
val scheme: ConstantIndex.CredentialScheme,
)

private val map = mutableMapOf<Int, MutableList<Credential>>()
private val credentialMap = mutableMapOf<Int, MutableList<Credential>>()

override fun storeGetNextIndex(
credential: IssuerCredentialStore.Credential,
Expand All @@ -26,7 +26,7 @@ class InMemoryIssuerCredentialStore : IssuerCredentialStore {
expirationDate: Instant,
timePeriod: Int
): Long {
val list = map.getOrPut(timePeriod) { mutableListOf() }
val list = credentialMap.getOrPut(timePeriod) { mutableListOf() }
val newIndex = (list.maxOfOrNull { it.statusListIndex } ?: 0) + 1
val vcId = when (credential) {
is IssuerCredentialStore.Credential.Iso -> credential.issuerSignedItemList.toString().encodeToByteArray()
Expand All @@ -51,11 +51,22 @@ class InMemoryIssuerCredentialStore : IssuerCredentialStore {
}

override fun getRevokedStatusListIndexList(timePeriod: Int): Collection<Long> {
return map.getOrPut(timePeriod) { mutableListOf() }.filter { it.revoked }.map { it.statusListIndex }
return credentialMap.getOrPut(timePeriod) {
mutableListOf()
}.filter {
it.revoked
}.map {
it.statusListIndex
}
}

override fun revoke(vcId: String, timePeriod: Int): Boolean {
val entry = map.getOrPut(timePeriod) { mutableListOf() }.find { it.vcId == vcId } ?: return false
val entry = credentialMap.getOrPut(timePeriod) {
mutableListOf()
}.find {
it.vcId == vcId
} ?: return false

entry.revoked = true
return true
}
Expand Down
12 changes: 12 additions & 0 deletions vck/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/Issuer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ interface Issuer {
*/
suspend fun issueRevocationListCredential(timePeriod: Int? = null): String?

/**
* @return a status list jwt.
* @param timePeriod time Period to issue a revocation list for
*/
suspend fun issueRevocationStatusListJwt(timePeriod: Int? = null): String?

/**
* @return a status list jwt.
* @param timePeriod time Period to issue a revocation list for
*/
suspend fun issueRevocationStatusListCwt(timePeriod: Int? = null): ByteArray?

/**
* Returns a Base64-encoded, zlib-compressed bitstring of revoked credentials, where
* the entry at "revocationListIndex" (of the credential) is true iff it is revoked
Expand Down
Loading

0 comments on commit 26d70af

Please sign in to comment.