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

Release 5.3.2 #210

Merged
merged 6 commits into from
Feb 6, 2025
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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

Release 5.3.2:
- ISO: Do not tag instants in CBOR with tag 1004
- ISO: Fix calcluation of value digests

Release 5.3.1:
- Add optional parameter `issuerUri` to `ClientIdScheme.PreRegistered`
- Fix validation of KB-JWT for SD-JWT presentations
Expand Down Expand Up @@ -73,6 +77,11 @@ Release 5.3.0:
- Update signum to 3.12.1
- Add isolated DCQL implementation

Release 5.2.4:
- SD-JWT: Be more lenient in parsing `status` information from credentials
- ISO: Do not tag instants in CBOR with tag 1004
- ISO: Fix calcluation of value digests

Release 5.2.3:
- Be more lenient in parsing OpenId authentication requests
- OpenID4VP: Use correct format of algorithms in metadata for `vp_formats.vc+sd-jwt`
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ kotlin.mpp.enableCInteropCommonization=true
kotlin.mpp.stability.nowarn=true
kotlin.native.ignoreDisabledTargets=true

artifactVersion = 5.3.1
artifactVersion = 5.3.2
jdk.version=17


Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import at.asitplus.KmmResult
import at.asitplus.catching
import at.asitplus.openid.AuthenticationRequestParameters
import at.asitplus.openid.RequestParametersFrom
import at.asitplus.openid.odcJsonSerializer
import at.asitplus.wallet.lib.agent.CredentialSubmission
import at.asitplus.wallet.lib.agent.CryptoService
import at.asitplus.wallet.lib.agent.HolderAgent
Expand All @@ -30,6 +31,8 @@ import kotlinx.coroutines.IO
import kotlinx.coroutines.withContext
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonPrimitive

/**
* Implements the wallet side of
Expand Down Expand Up @@ -179,6 +182,7 @@ data class OpenId4VpSuccess(
private suspend fun HttpResponse.extractRedirectUri(): String? =
headers[HttpHeaders.Location]?.let {
it.ifEmpty { null }
} ?: runCatching { body<OpenId4VpSuccess>() }.getOrNull()?.let {
it.redirectUri.ifEmpty { null }
} ?: runCatching { body<String>() }.getOrNull()?.let {
runCatching { odcJsonSerializer.decodeFromString<JsonObject>(it) }.getOrNull()
?.get("redirect_uri")?.jsonPrimitive?.content
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ interface KeyMaterial : Signer {
abstract class KeyWithSelfSignedCert(
private val extensions: List<X509CertificateExtension>,
val customKeyId: String? = null,
val lifetimeInSeconds: Long = 30,
) : KeyMaterial {
override val identifier: String get() = customKeyId ?: publicKey.didEncoded
private val crtMut = Mutex()
Expand All @@ -45,7 +46,8 @@ abstract class KeyWithSelfSignedCert(
if (_certificate == null) _certificate = X509Certificate.generateSelfSignedCertificate(
publicKey,
signatureAlgorithm.toX509SignatureAlgorithm().getOrThrow(),
extensions
lifetimeInSeconds = lifetimeInSeconds,
extensions = extensions,
) {
sign(it).asKmmResult()
}.onFailure { Napier.e("Could not self-sign Cert", it) }.getOrNull()
Expand All @@ -66,7 +68,8 @@ class EphemeralKeyWithSelfSignedCert(
}.getOrThrow(),
extensions: List<X509CertificateExtension> = listOf(),
customKeyId: String? = null,
) : KeyWithSelfSignedCert(extensions, customKeyId), Signer by key.signer().getOrThrow() {
lifetimeInSeconds: Long = 30,
) : KeyWithSelfSignedCert(extensions, customKeyId, lifetimeInSeconds), Signer by key.signer().getOrThrow() {
override fun getUnderLyingSigner(): Signer = key.signer().getOrThrow()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import io.matthewnelson.encoding.base16.Base16
import io.matthewnelson.encoding.base64.Base64
import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
import kotlinx.datetime.Clock
import kotlinx.serialization.builtins.ByteArraySerializer
import kotlinx.serialization.json.buildJsonObject
import kotlin.coroutines.cancellation.CancellationException

Expand Down Expand Up @@ -353,7 +354,7 @@ class Validator(
private fun ByteStringWrapper<IssuerSignedItem>.verify(mdlItems: ValueDigestList?): Boolean {
val issuerHash = mdlItems?.entries?.firstOrNull { it.key == value.digestId }
?: return false
val verifierHash = serialized.wrapInCborTag(24).sha256()
val verifierHash = vckCborSerializer.encodeToByteArray(ByteArraySerializer(), serialized).wrapInCborTag(24).sha256()
if (!verifierHash.contentEquals(issuerHash.value)) {
Napier.w("Could not verify hash of value for ${value.elementIdentifier}")
return false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,21 @@ import kotlinx.datetime.Clock
import kotlinx.datetime.DateTimeUnit
import kotlinx.datetime.plus
import kotlin.random.Random
import kotlin.time.Duration.Companion.seconds

suspend fun X509Certificate.Companion.generateSelfSignedCertificate(
publicKey: CryptoPublicKey,
algorithm: X509SignatureAlgorithm,
lifetimeInSeconds: Long = 30,
extensions: List<X509CertificateExtension> = listOf(),
signer: suspend (ByteArray) -> KmmResult<CryptoSignature>,
): KmmResult<X509Certificate> = catching {
Napier.d { "Generating self-signed Certificate" }
val notBeforeDate = Clock.System.now()
val notAfterDate = notBeforeDate.plus(30, DateTimeUnit.SECOND)
val notAfterDate = notBeforeDate.plus(lifetimeInSeconds, DateTimeUnit.SECOND)
val tbsCertificate = TbsCertificate(
version = 2,
serialNumber = Random.nextBytes(8),
serialNumber = byteArrayOf(1),
issuerName = listOf(
RelativeDistinguishedName(
AttributeTypeAndValue.CommonName(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ open class IssuerSignedItemSerializer(private val namespace: String, private val
}

private fun Any.annotations() =
if (this is LocalDate || this is Instant) {
if (this is LocalDate) {
@OptIn(ExperimentalUnsignedTypes::class)
listOf(ValueTags(1004uL))
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package at.asitplus.wallet.lib.iso

import at.asitplus.signum.indispensable.cosef.io.ByteStringWrapper
import kotlinx.serialization.encodeToByteArray

/**
* Convenience class with a custom serializer ([IssuerSignedListSerializer]) to prevent
Expand Down Expand Up @@ -36,7 +37,10 @@ data class IssuerSignedList(
*/
fun fromIssuerSignedItems(items: List<IssuerSignedItem>, namespace: String) =
IssuerSignedList(items.map { item ->
ByteStringWrapper(item, item.serialize(namespace).wrapInCborTag(24))
ByteStringWrapper(
item,
vckCborSerializer.encodeToByteArray(item.serialize(namespace)).wrapInCborTag(24)
)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package at.asitplus.wallet.lib.iso

import io.matthewnelson.encoding.base16.Base16
import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
import kotlinx.serialization.builtins.ByteArraySerializer

/**
* Convenience class with a custom serializer ([ValueDigestListSerializer]) to prevent
Expand Down Expand Up @@ -40,7 +41,10 @@ data class ValueDigest(
fun fromIssuerSignedItem(value: IssuerSignedItem, namespace: String): ValueDigest =
ValueDigest(
value.digestId,
value.serialize(namespace).wrapInCborTag(24).sha256()
// Ensure wrapping it in the whole "bytes" cbor structure,
// afterwards wrapping it with D818
vckCborSerializer.encodeToByteArray(ByteArraySerializer(), value.serialize(namespace))
.wrapInCborTag(24).sha256()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,9 @@ class Verifier {
) {
val issuerSignedItem = issuerSignedItems.entries.first { it.value.elementIdentifier == key }
//val elementValue = issuerSignedItem.value.elementValue.toString().shouldNotBeNull()
val issuerHash = mdlItems.entries.first { it.key == issuerSignedItem.value.digestId }.shouldNotBeNull()
val issuerHash = mdlItems.entries.first { it.key == issuerSignedItem.value.digestId }.shouldNotBeNull().value
val verifierHash = issuerSignedItem.serialized.sha256()
verifierHash.encodeToString(Base16(true)) shouldBe issuerHash.value.encodeToString(Base16(true))
verifierHash.encodeToString(Base16(true)) shouldBe issuerHash.encodeToString(Base16(true))
}
}

Expand Down
Loading