diff --git a/CHANGELOG.md b/CHANGELOG.md
index dd8435e3af951f4cf4f64a94fb577ecb1a53127e..ddf8b885dc74a30bd11522587d5c994018071284 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
 # Changelog
 
+Release 3.0.1
+ - Dependency Updates
+   - OKIO 3.5.0
+   - UUID 0.8.1
+   - Encodings 1.2.3
+   - JOSE+JWT 9.31
+   - JSON 20230618
+
 Release 3.0.0:
  - Creating, issuing, managing and verifying ISO/IEC 18013-5:2021 credentials
  - Kotlin 1.9.10
diff --git a/conventions-vclib/gradle-conventions-plugin b/conventions-vclib/gradle-conventions-plugin
index edc666d4fd9cdb8da87b935ef92d5736a62ce80f..4aec06670f8b4b13551281fa466e81458c2c7bbd 160000
--- a/conventions-vclib/gradle-conventions-plugin
+++ b/conventions-vclib/gradle-conventions-plugin
@@ -1 +1 @@
-Subproject commit edc666d4fd9cdb8da87b935ef92d5736a62ce80f
+Subproject commit 4aec06670f8b4b13551281fa466e81458c2c7bbd
diff --git a/conventions-vclib/src/main/kotlin/VcLibVersions.kt b/conventions-vclib/src/main/kotlin/VcLibVersions.kt
index 603e672a0860a7a896962900c23a63aff45e5487..01319540d9c14061cc89105d42605863b2f9784b 100644
--- a/conventions-vclib/src/main/kotlin/VcLibVersions.kt
+++ b/conventions-vclib/src/main/kotlin/VcLibVersions.kt
@@ -1,11 +1,11 @@
 object VcLibVersions {
-    const val uuid = "0.5.0"
+    const val uuid = "0.8.1"
     const val resultlib = "1.5.3"
-    const val encoding = "1.1.3"
-    const val okio = "3.2.0"
+    const val encoding = "1.2.3"
+    const val okio = "3.5.0"
 
     object Jvm {
-        const val `jose-jwt` = "9.25.6"
-        const val json = "20210307"
+        const val `jose-jwt` = "9.31"
+        const val json = "20230618"
     }
 }
diff --git a/gradle.properties b/gradle.properties
index 529d97213f7fd464f9aca9482adbbc2dc85c60b4..1613a6d13a7fd1104b02a01001403431f6007457 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -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 = 3.0.0
+artifactVersion = 3.0.1
diff --git a/vclib-aries/src/commonMain/kotlin/at/asitplus/wallet/lib/msg/JwmAttachment.kt b/vclib-aries/src/commonMain/kotlin/at/asitplus/wallet/lib/msg/JwmAttachment.kt
index 279c1fe95f0bb2d3b032beb3c7e1afde3ca8a2cc..d524ae231739420e8de0ba0b93344d9d575a5adc 100644
--- a/vclib-aries/src/commonMain/kotlin/at/asitplus/wallet/lib/msg/JwmAttachment.kt
+++ b/vclib-aries/src/commonMain/kotlin/at/asitplus/wallet/lib/msg/JwmAttachment.kt
@@ -5,6 +5,9 @@ import com.benasher44.uuid.uuid4
 import io.github.aakira.napier.Napier
 import io.matthewnelson.component.base64.decodeBase64ToArray
 import io.matthewnelson.component.base64.encodeBase64
+import io.matthewnelson.encoding.base64.Base64
+import io.matthewnelson.encoding.core.Decoder.Companion.decodeToByteArrayOrNull
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlinx.serialization.SerialName
 import kotlinx.serialization.Serializable
 import kotlinx.serialization.decodeFromString
@@ -30,7 +33,7 @@ data class JwmAttachment(
 
     fun decodeString(): String? {
         if (data.base64 != null)
-            return data.base64.decodeBase64ToArray()?.decodeToString()
+            return data.base64.decodeToByteArrayOrNull(Base64())?.decodeToString()
         if (data.jws != null)
             return data.jws
         return null
@@ -39,7 +42,7 @@ data class JwmAttachment(
 
     fun decodeBinary(): ByteArray? {
         if (data.base64 != null)
-            return data.base64.decodeBase64ToArray()
+            return data.base64.decodeToByteArrayOrNull(Base64())
         return null
             .also { Napier.w("Could not binary decode JWM attachment") }
     }
@@ -57,7 +60,7 @@ data class JwmAttachment(
             id = uuid4().toString(),
             mediaType = "application/base64",
             data = JwmAttachmentData(
-                base64 = data.encodeToByteArray().encodeBase64()
+                base64 = data.encodeToByteArray().encodeToString(Base64())
             )
         )
 
@@ -65,7 +68,7 @@ data class JwmAttachment(
             id = uuid4().toString(),
             mediaType = "application/base64",
             data = JwmAttachmentData(
-                base64 = data.encodeBase64()
+                base64 = data.encodeToString(Base64())
             )
         )
 
@@ -75,7 +78,7 @@ data class JwmAttachment(
             filename = filename,
             parent = parent,
             data = JwmAttachmentData(
-                base64 = data.encodeBase64()
+                base64 = data.encodeToString(Base64())
             )
         )
 
diff --git a/vclib-openid/src/commonMain/kotlin/at/asitplus/wallet/lib/oidc/OidcSiopWallet.kt b/vclib-openid/src/commonMain/kotlin/at/asitplus/wallet/lib/oidc/OidcSiopWallet.kt
index 7dc6fcce904899cf2f9873cc93304ba419e51dd9..040b304e171697ca5e27f18cb0bb2df19c95144f 100644
--- a/vclib-openid/src/commonMain/kotlin/at/asitplus/wallet/lib/oidc/OidcSiopWallet.kt
+++ b/vclib-openid/src/commonMain/kotlin/at/asitplus/wallet/lib/oidc/OidcSiopWallet.kt
@@ -35,6 +35,8 @@ import io.ktor.http.URLBuilder
 import io.ktor.http.Url
 import io.ktor.util.flattenEntries
 import io.matthewnelson.component.encoding.base16.encodeBase16
+import io.matthewnelson.encoding.base16.Base16
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlinx.datetime.Clock
 import kotlin.time.Duration.Companion.seconds
 
@@ -290,7 +292,7 @@ class OidcSiopWallet(
                     AuthenticationResponseParameters(
                         idToken = signedIdToken,
                         state = params.state,
-                        vpToken = vp.document.serialize().encodeBase16(),
+                        vpToken = vp.document.serialize().encodeToString(Base16()),
                         presentationSubmission = presentationSubmission,
                     )
                 )
diff --git a/vclib-openid/src/commonMain/kotlin/at/asitplus/wallet/lib/oidvci/IssuerService.kt b/vclib-openid/src/commonMain/kotlin/at/asitplus/wallet/lib/oidvci/IssuerService.kt
index 061e6bb7f97d89e12c077cbffd39334be96a3c43..157c88e0a719f6d49f7aba727e129e694c512ccc 100644
--- a/vclib-openid/src/commonMain/kotlin/at/asitplus/wallet/lib/oidvci/IssuerService.kt
+++ b/vclib-openid/src/commonMain/kotlin/at/asitplus/wallet/lib/oidvci/IssuerService.kt
@@ -22,9 +22,9 @@ import at.asitplus.wallet.lib.oidc.OpenIdConstants.TOKEN_PREFIX_BEARER
 import at.asitplus.wallet.lib.oidc.OpenIdConstants.TOKEN_TYPE_BEARER
 import at.asitplus.wallet.lib.oidc.OpenIdConstants.URN_TYPE_JWK_THUMBPRINT
 import at.asitplus.wallet.lib.oidvci.mdl.RequestedCredentialClaimSpecification
-import io.ktor.http.URLBuilder
-import io.matthewnelson.component.base64.Base64.UrlSafe
-import io.matthewnelson.component.base64.encodeBase64
+import io.ktor.http.*
+import io.matthewnelson.encoding.base64.Base64
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlin.coroutines.cancellation.CancellationException
 
 /**
@@ -167,7 +167,8 @@ class IssuerService(
         return when (val issuedCredential = issuedCredentialResult.successful.first()) {
             is Issuer.IssuedCredential.Iso -> CredentialResponseParameters(
                 format = CredentialFormatEnum.MSO_MDOC,
-                credential = issuedCredential.issuerSigned.serialize().encodeBase64(UrlSafe())
+                credential = issuedCredential.issuerSigned.serialize()
+                    .encodeToString(Base64 { encodeToUrlSafe = true; padEncoded = false })
             )
 
             is Issuer.IssuedCredential.Vc -> CredentialResponseParameters(
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/InMemoryIssuerCredentialStore.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/InMemoryIssuerCredentialStore.kt
index 8ed4f1d1c76542f69fe00f930874451a95f68986..5dd33d2ca4041a174d70f4d02bdc5ebcd2a2716f 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/InMemoryIssuerCredentialStore.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/InMemoryIssuerCredentialStore.kt
@@ -4,6 +4,8 @@ import at.asitplus.wallet.lib.data.CredentialSubject
 import at.asitplus.wallet.lib.iso.IssuerSignedItem
 import at.asitplus.wallet.lib.iso.sha256
 import io.matthewnelson.component.encoding.base16.encodeBase16
+import io.matthewnelson.encoding.base16.Base16
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlinx.datetime.Instant
 
 
@@ -45,7 +47,7 @@ class InMemoryIssuerCredentialStore : IssuerCredentialStore {
         val list = map.getOrPut(timePeriod) { mutableListOf() }
         val newIndex = (list.maxOfOrNull { it.statusListIndex } ?: 0) + 1
         list += Credential(
-            vcId = issuerSignedItemList.toString().encodeToByteArray().sha256().encodeBase16(),
+            vcId = issuerSignedItemList.toString().encodeToByteArray().sha256().encodeToString(Base16()),
             statusListIndex = newIndex,
             revoked = false,
             expirationDate = expirationDate
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/IssuerAgent.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/IssuerAgent.kt
index 81817e8c29bec0b2cfe9ed5a76ffb77a635fdbf7..26d026c4ff4880f24d974efa36299785a8a01e02 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/IssuerAgent.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/IssuerAgent.kt
@@ -29,6 +29,8 @@ import at.asitplus.wallet.lib.jws.JwsService
 import com.benasher44.uuid.uuid4
 import io.github.aakira.napier.Napier
 import io.matthewnelson.component.base64.encodeBase64
+import io.matthewnelson.encoding.base64.Base64
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlinx.datetime.Clock
 import kotlinx.datetime.DateTimeUnit
 import kotlinx.datetime.plus
@@ -219,7 +221,7 @@ class IssuerAgent(
         issuerCredentialStore.getRevokedStatusListIndexList(timePeriod)
             .forEach { bitset[it] = true }
         val input = bitset.toByteArray()
-        return zlibService.compress(input)?.encodeBase64()
+        return zlibService.compress(input)?.encodeToString(Base64())
     }
 
     /**
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/Validator.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/Validator.kt
index b21d183efe8df3cef57c18bf5d4578af6dd687fd..04a0742ee818487d1f71d220faf548a493fc2fe8 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/Validator.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/Validator.kt
@@ -26,6 +26,10 @@ import at.asitplus.wallet.lib.toBitSet
 import io.github.aakira.napier.Napier
 import io.matthewnelson.component.base64.decodeBase64ToArray
 import io.matthewnelson.component.encoding.base16.encodeBase16
+import io.matthewnelson.encoding.base16.Base16
+import io.matthewnelson.encoding.base64.Base64
+import io.matthewnelson.encoding.core.Decoder.Companion.decodeToByteArrayOrNull
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlinx.serialization.cbor.ByteStringWrapper
 
 
@@ -86,7 +90,7 @@ class Validator(
             return false
                 .also { Napier.d("credentialSubject invalid") }
         val encodedList = parsedVc.jws.vc.credentialSubject.encodedList
-        this.revocationList = encodedList.decodeBase64ToArray()?.let {
+        this.revocationList = encodedList.decodeToByteArrayOrNull(Base64())?.let {
             zlibService.decompress(it)?.toBitSet() ?: return false.also { Napier.d("Invalid ZLIB") }
         } ?: return false.also { Napier.d("Invalid Base64") }
         Napier.d("Revocation list is valid")
@@ -186,10 +190,10 @@ class Validator(
      */
     fun verifyDocument(doc: Document, challenge: String): Verifier.VerifyPresentationResult {
         if (doc.docType != DOC_TYPE_MDL)
-            return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeBase16())
+            return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeToString(Base16()))
                 .also { Napier.w("Invalid docType: ${doc.docType}") }
         if (doc.errors != null) {
-            return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeBase16())
+            return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeToString(Base16()))
                 .also { Napier.w("Document has errors: ${doc.errors}") }
         }
         val issuerSigned = doc.issuerSigned
@@ -197,45 +201,45 @@ class Validator(
 
         val issuerKey = issuerAuth.unprotectedHeader?.certificateChain?.let {
             CryptoUtils.extractPublicKeyFromX509Cert(it)?.toCoseKey()
-        } ?: return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeBase16())
+        } ?: return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeToString(Base16()))
             .also { Napier.w("Got no issuer key in $issuerAuth") }
 
         if (verifierCoseService.verifyCose(issuerAuth, issuerKey).getOrNull() != true) {
-            return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeBase16())
+            return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeToString(Base16()))
                 .also { Napier.w("IssuerAuth not verified: $issuerAuth") }
         }
 
         val mso = issuerSigned.getIssuerAuthPayloadAsMso()
-            ?: return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeBase16())
-                .also { Napier.w("MSO is null: ${issuerAuth.payload?.encodeBase16()}") }
+            ?: return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeToString(Base16()))
+                .also { Napier.w("MSO is null: ${issuerAuth.payload?.encodeToString(Base16())}") }
         if (mso.docType != DOC_TYPE_MDL) {
-            return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeBase16())
+            return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeToString(Base16()))
                 .also { Napier.w("Invalid docType in MSO: ${mso.docType}") }
         }
         val mdlItems = mso.valueDigests[NAMESPACE_MDL]
-            ?: return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeBase16())
+            ?: return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeToString(Base16()))
                 .also { Napier.w("mdlItems are null in MSO: ${mso.valueDigests}") }
 
         val walletKey = mso.deviceKeyInfo.deviceKey
         val deviceSignature = doc.deviceSigned.deviceAuth.deviceSignature
-            ?: return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeBase16())
+            ?: return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeToString(Base16()))
                 .also { Napier.w("DeviceSignature is null: ${doc.deviceSigned.deviceAuth}") }
 
         if (verifierCoseService.verifyCose(deviceSignature, walletKey).getOrNull() != true) {
-            return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeBase16())
+            return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeToString(Base16()))
                 .also { Napier.w("DeviceSignature not verified") }
         }
 
         val deviceSignaturePayload = deviceSignature.payload
-            ?: return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeBase16())
+            ?: return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeToString(Base16()))
                 .also { Napier.w("DeviceSignature does not contain challenge") }
         if (!deviceSignaturePayload.contentEquals(challenge.encodeToByteArray())) {
-            return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeBase16())
+            return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeToString(Base16()))
                 .also { Napier.w("DeviceSignature does not contain correct challenge") }
         }
 
         val issuerSignedItems = issuerSigned.namespaces?.get(NAMESPACE_MDL)
-            ?: return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeBase16())
+            ?: return Verifier.VerifyPresentationResult.InvalidStructure(doc.serialize().encodeToString(Base16()))
                 .also { Napier.w("No issuer signed items in ${issuerSigned.namespaces}") }
 
         val validatedItems = issuerSignedItems.entries.associateWith { it.verify(mdlItems) }
@@ -251,7 +255,7 @@ class Validator(
         val issuerHash = mdlItems.entries.first { it.key == value.digestId }
         // TODO analyze usages of tag wrapping
         val verifierHash = serialized.wrapInCborTag(24).sha256()
-        if (!verifierHash.encodeBase16().contentEquals(issuerHash.value.encodeBase16())) {
+        if (!verifierHash.encodeToString(Base16()).contentEquals(issuerHash.value.encodeToString(Base16()))) {
             Napier.w("Could not verify hash of value for ${value.elementIdentifier}")
             return false
         }
@@ -303,12 +307,12 @@ class Validator(
         Napier.d("Verifying ISO Cred $it")
         if (issuerKey == null) {
             Napier.w("ISO: No issuer key")
-            return Verifier.VerifyCredentialResult.InvalidStructure(it.serialize().encodeBase16())
+            return Verifier.VerifyCredentialResult.InvalidStructure(it.serialize().encodeToString(Base16()))
         }
         val result = verifierCoseService.verifyCose(it.issuerAuth, issuerKey)
         if (result.getOrNull() != true) {
             Napier.w("ISO: Could not verify credential", result.exceptionOrNull())
-            return Verifier.VerifyCredentialResult.InvalidStructure(it.serialize().encodeBase16())
+            return Verifier.VerifyCredentialResult.InvalidStructure(it.serialize().encodeToString(Base16()))
         }
         return Verifier.VerifyCredentialResult.SuccessIso(it)
     }
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/VerifierAgent.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/VerifierAgent.kt
index ff0f67dfc9d1d2a6f0365e353ffdfb4ae7f1b637..ea5ed0f46611d1d5801eb791cec7587654b96177 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/VerifierAgent.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/agent/VerifierAgent.kt
@@ -6,6 +6,8 @@ import at.asitplus.wallet.lib.iso.Document
 import at.asitplus.wallet.lib.jws.JwsSigned
 import io.github.aakira.napier.Napier
 import io.matthewnelson.component.encoding.base16.decodeBase16ToArray
+import io.matthewnelson.encoding.base16.Base16
+import io.matthewnelson.encoding.core.Decoder.Companion.decodeToByteArrayOrNull
 
 
 /**
@@ -56,7 +58,7 @@ class VerifierAgent private constructor(
             return validator.verifyVpJws(it, challenge, identifier)
         }
         val document =
-            runCatching { it.decodeBase16ToArray()?.let { bytes -> Document.deserialize(bytes) } }.getOrNull()
+            runCatching { it.decodeToByteArrayOrNull(Base16())?.let { bytes -> Document.deserialize(bytes) } }.getOrNull()
         if (document != null) {
             return validator.verifyDocument(document, challenge)
         }
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/cbor/CoseHeader.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/cbor/CoseHeader.kt
index abec236deacc509a42b3c81919a9520766f5be05..a055283222d9e69b7feef6064fa829b8eabdf741 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/cbor/CoseHeader.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/cbor/CoseHeader.kt
@@ -4,6 +4,8 @@ import at.asitplus.wallet.lib.iso.cborSerializer
 import io.github.aakira.napier.Napier
 import io.ktor.http.content.ByteArrayContent
 import io.matthewnelson.component.encoding.base16.encodeBase16
+import io.matthewnelson.encoding.base16.Base16
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.SerialName
 import kotlinx.serialization.Serializable
@@ -93,10 +95,10 @@ data class CoseHeader(
         return "CoseHeader(algorithm=$algorithm," +
                 " criticalHeaders=$criticalHeaders," +
                 " contentType=$contentType," +
-                " kid=${kid?.encodeBase16()}," +
-                " iv=${iv?.encodeBase16()}," +
-                " partialIv=${partialIv?.encodeBase16()}," +
-                " certificateChain=${certificateChain?.encodeBase16()})"
+                " kid=${kid?.encodeToString(Base16())}," +
+                " iv=${iv?.encodeToString(Base16())}," +
+                " partialIv=${partialIv?.encodeToString(Base16())}," +
+                " certificateChain=${certificateChain?.encodeToString(Base16())})"
     }
 
     companion object {
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/cbor/CoseKey.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/cbor/CoseKey.kt
index 1e3c9dcb1b4efd5452847a210d4f7533101b27fc..72063ba3e7a4e47e4c1cb2bba0909f4dbcbed94b 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/cbor/CoseKey.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/cbor/CoseKey.kt
@@ -10,6 +10,8 @@ import at.asitplus.wallet.lib.jws.MultibaseHelper
 import io.github.aakira.napier.Napier
 import io.matthewnelson.component.base64.encodeBase64
 import io.matthewnelson.component.encoding.base16.encodeBase16
+import io.matthewnelson.encoding.base16.Base16
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.SerialName
 import kotlinx.serialization.Serializable
@@ -113,14 +115,14 @@ data class CoseKey(
 
     override fun toString(): String {
         return "CoseKey(type=$type," +
-                " keyId=${keyId?.encodeBase16()}," +
+                " keyId=${keyId?.encodeToString(Base16())}," +
                 " algorithm=$algorithm," +
                 " operations=${operations?.contentToString()}," +
-                " baseIv=${baseIv?.encodeBase16()}," +
+                " baseIv=${baseIv?.encodeToString(Base16())}," +
                 " curve=$curve," +
-                " x=${x?.encodeBase16()}," +
-                " y=${y?.encodeBase16()}," +
-                " d=${d?.encodeBase16()})"
+                " x=${x?.encodeToString(Base16())}," +
+                " y=${y?.encodeToString(Base16())}," +
+                " d=${d?.encodeToString(Base16())})"
     }
 
     override fun equals(other: Any?): Boolean {
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/cbor/CoseSigned.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/cbor/CoseSigned.kt
index 031dfbbed28f8881263a0ca8554970508072d654..45992ad7871a9f34db85c7321117efa9ead937f9 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/cbor/CoseSigned.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/cbor/CoseSigned.kt
@@ -1,21 +1,19 @@
+@file:OptIn(ExperimentalUnsignedTypes::class)
+
 package at.asitplus.wallet.lib.cbor
 
 import at.asitplus.wallet.lib.iso.cborSerializer
 import io.github.aakira.napier.Napier
-import io.matthewnelson.component.encoding.base16.encodeBase16
-import kotlinx.serialization.ExperimentalSerializationApi
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.Serializable
+import io.matthewnelson.encoding.base16.Base16
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
+import kotlinx.serialization.*
 import kotlinx.serialization.builtins.ByteArraySerializer
 import kotlinx.serialization.cbor.ByteString
 import kotlinx.serialization.cbor.ByteStringWrapper
-import kotlinx.serialization.cbor.Cbor
 import kotlinx.serialization.cbor.CborArray
-import kotlinx.serialization.decodeFromByteArray
 import kotlinx.serialization.descriptors.PrimitiveKind
 import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
 import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encodeToByteArray
 import kotlinx.serialization.encoding.Decoder
 import kotlinx.serialization.encoding.Encoder
 
@@ -64,8 +62,8 @@ data class CoseSigned(
     override fun toString(): String {
         return "CoseSigned(protectedHeader=${protectedHeader.value}," +
                 " unprotectedHeader=$unprotectedHeader," +
-                " payload=${payload?.encodeBase16()}," +
-                " signature=${signature.encodeBase16()})"
+                " payload=${payload?.encodeToString(Base16())}," +
+                " signature=${signature.encodeToString(Base16())})"
     }
 
     companion object {
@@ -121,8 +119,8 @@ data class CoseSignatureInput(
     override fun toString(): String {
         return "CoseSignatureInput(contextString='$contextString'," +
                 " protectedHeader=${protectedHeader.value}," +
-                " externalAad=${externalAad.encodeBase16()}," +
-                " payload=${payload?.encodeBase16()})"
+                " externalAad=${externalAad.encodeToString(Base16())}," +
+                " payload=${payload?.encodeToString(Base16())})"
     }
 
 
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/iso/DeviceRequest.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/iso/DeviceRequest.kt
index 46531bef2a63c351c1d6fcf19a6c520ebd967e41..7c3f9e34b54658ed9318c04cf03cff13bad83fd2 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/iso/DeviceRequest.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/iso/DeviceRequest.kt
@@ -6,6 +6,8 @@ import at.asitplus.wallet.lib.cbor.CoseSigned
 import at.asitplus.wallet.lib.iso.IsoDataModelConstants.NAMESPACE_MDL
 import io.github.aakira.napier.Napier
 import io.matthewnelson.component.encoding.base16.encodeBase16
+import io.matthewnelson.encoding.base16.Base16
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlinx.datetime.LocalDate
 import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.InternalSerializationApi
@@ -407,7 +409,7 @@ data class IssuerSignedItem(
 
     override fun toString(): String {
         return "IssuerSignedItem(digestId=$digestId," +
-                " random=${random.encodeBase16()}," +
+                " random=${random.encodeToString(Base16())}," +
                 " elementIdentifier='$elementIdentifier'," +
                 " elementValue=$elementValue)"
     }
@@ -437,7 +439,7 @@ data class ElementValue(
     fun serialize() = cborSerializer.encodeToByteArray(this)
 
     override fun toString(): String {
-        return "ElementValue(bytes=${bytes?.encodeBase16()}," +
+        return "ElementValue(bytes=${bytes?.encodeToString(Base16())}," +
                 " date=${date}," +
                 " string=$string," +
                 " drivingPrivilege=$drivingPrivilege)"
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/iso/MobileDrivingLicence.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/iso/MobileDrivingLicence.kt
index c34f5f55e851493fac92f07a0551750a7eb511cd..59bc1111faf5198353eccd5babaf8467eb603bff 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/iso/MobileDrivingLicence.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/iso/MobileDrivingLicence.kt
@@ -37,6 +37,8 @@ import at.asitplus.wallet.lib.iso.IsoDataModelConstants.DataElements.WEIGHT
 import at.asitplus.wallet.lib.jws.ByteArrayBase64UrlSerializer
 import io.github.aakira.napier.Napier
 import io.matthewnelson.component.encoding.base16.encodeBase16
+import io.matthewnelson.encoding.base16.Base16
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlinx.datetime.LocalDate
 import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.SerialName
@@ -211,7 +213,7 @@ data class MobileDrivingLicence(
                 " issuingCountry='$issuingCountry'," +
                 " issuingAuthority='$issuingAuthority'," +
                 " licenceNumber='$licenceNumber'," +
-                " portrait=${portrait.encodeBase16()}," +
+                " portrait=${portrait.encodeToString(Base16())}," +
                 " drivingPrivileges=${drivingPrivileges}," +
                 " unDistinguishingSign='$unDistinguishingSign'," +
                 " administrativeNumber=$administrativeNumber," +
@@ -234,7 +236,7 @@ data class MobileDrivingLicence(
                 " residentCountry=$residentCountry," +
                 " familyNameNationalCharacters=$familyNameNationalCharacters," +
                 " givenNameNationalCharacters=$givenNameNationalCharacters," +
-                " signatureOrUsualMark=${signatureOrUsualMark?.encodeBase16()})"
+                " signatureOrUsualMark=${signatureOrUsualMark?.encodeToString(Base16())})"
     }
 
     companion object {
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/iso/MobileSecurityObject.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/iso/MobileSecurityObject.kt
index c73be6c18a15f013ed05bbd33b50020c5ee2dbe1..a68dcdee60ff16d8e14615e6d821302e1efe6674 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/iso/MobileSecurityObject.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/iso/MobileSecurityObject.kt
@@ -5,6 +5,8 @@ package at.asitplus.wallet.lib.iso
 import at.asitplus.wallet.lib.cbor.CoseKey
 import io.github.aakira.napier.Napier
 import io.matthewnelson.component.encoding.base16.encodeBase16
+import io.matthewnelson.encoding.base16.Base16
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlinx.datetime.Instant
 import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.KSerializer
@@ -104,7 +106,7 @@ data class ValueDigest(
     }
 
     override fun toString(): String {
-        return "MobileSecurityObjectNamespaceEntry(key=$key, value=${value.encodeBase16()})"
+        return "MobileSecurityObjectNamespaceEntry(key=$key, value=${value.encodeToString(Base16())})"
     }
 
     companion object {
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/ByteArrayBase64Serializer.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/ByteArrayBase64Serializer.kt
index e6c61aee55fd71557f0439d9f33c11afdd600434..d247bd32e9685dcd854ece834262a50f40541ed9 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/ByteArrayBase64Serializer.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/ByteArrayBase64Serializer.kt
@@ -2,6 +2,9 @@ package at.asitplus.wallet.lib.jws
 
 import io.matthewnelson.component.base64.decodeBase64ToArray
 import io.matthewnelson.component.base64.encodeBase64
+import io.matthewnelson.encoding.base64.Base64
+import io.matthewnelson.encoding.core.Decoder.Companion.decodeToByteArrayOrNull
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlinx.serialization.KSerializer
 import kotlinx.serialization.descriptors.PrimitiveKind
 import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
@@ -15,11 +18,11 @@ object ByteArrayBase64Serializer : KSerializer<ByteArray> {
         PrimitiveSerialDescriptor("ByteArrayBase64Serializer", PrimitiveKind.STRING)
 
     override fun serialize(encoder: Encoder, value: ByteArray) {
-        encoder.encodeString(value.encodeBase64())
+        encoder.encodeString(value.encodeToString(Base64()))
     }
 
     override fun deserialize(decoder: Decoder): ByteArray {
-        return decoder.decodeString().decodeBase64ToArray() ?: byteArrayOf()
+        return decoder.decodeString().decodeToByteArrayOrNull(Base64()) ?: byteArrayOf()
     }
 
 }
\ No newline at end of file
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/ByteArrayBase64UrlSerializer.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/ByteArrayBase64UrlSerializer.kt
index 4b556bcac38bce829dd0aa6d4044db166d06f49b..7510394acfc9d9e432e9d74a57cfaf1f00431970 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/ByteArrayBase64UrlSerializer.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/ByteArrayBase64UrlSerializer.kt
@@ -1,8 +1,9 @@
 package at.asitplus.wallet.lib.jws
 
-import io.matthewnelson.component.base64.Base64
 import io.matthewnelson.component.base64.decodeBase64ToArray
-import io.matthewnelson.component.base64.encodeBase64
+import io.matthewnelson.encoding.base64.Base64
+import io.matthewnelson.encoding.core.Decoder.Companion.decodeToByteArrayOrNull
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlinx.serialization.KSerializer
 import kotlinx.serialization.descriptors.PrimitiveKind
 import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
@@ -16,11 +17,11 @@ object ByteArrayBase64UrlSerializer : KSerializer<ByteArray> {
         PrimitiveSerialDescriptor("ByteArrayBase64UrlSerializer", PrimitiveKind.STRING)
 
     override fun serialize(encoder: Encoder, value: ByteArray) {
-        encoder.encodeString(value.encodeBase64(Base64.UrlSafe(pad = false)))
+        encoder.encodeString(value.encodeToString(Base64 { encodeToUrlSafe = true; padEncoded = false }))
     }
 
     override fun deserialize(decoder: Decoder): ByteArray {
-        return decoder.decodeString().decodeBase64ToArray() ?: byteArrayOf()
+        return decoder.decodeString().decodeToByteArrayOrNull(Base64()) ?: byteArrayOf()
     }
 
 }
\ No newline at end of file
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JsonWebKey.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JsonWebKey.kt
index aaaddbf80ea8db568ad93b89d481452661a48d6c..bdfb19b385c4c2cd5dee9207a692c23023c604b6 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JsonWebKey.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JsonWebKey.kt
@@ -4,7 +4,8 @@ import at.asitplus.KmmResult
 import at.asitplus.wallet.lib.CryptoPublicKey
 import at.asitplus.wallet.lib.data.jsonSerializer
 import io.github.aakira.napier.Napier
-import io.matthewnelson.component.base64.encodeBase64
+import io.matthewnelson.encoding.base64.Base64
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlinx.serialization.SerialName
 import kotlinx.serialization.Serializable
 import kotlinx.serialization.encodeToString
@@ -135,7 +136,9 @@ data class JsonWebKey(
     }
 
     override fun toString(): String {
-        return "JsonWebKey(type=$type, curve=$curve, keyId=$keyId, x=${x?.encodeBase64()}, y=${y?.encodeBase64()})"
+        return "JsonWebKey(type=$type, curve=$curve, keyId=$keyId, x=${x?.encodeToString(Base64())}, y=${
+            y?.encodeToString(Base64())
+        })"
     }
 
     fun toCryptoPublicKey(): CryptoPublicKey? {
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JweEncrypted.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JweEncrypted.kt
index b3a0e0bcef0c27e51b6ea4f401cce3c70886feb6..ea9ec61ad4f7fd110b4f49348d2e2d954aead5df 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JweEncrypted.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JweEncrypted.kt
@@ -1,9 +1,9 @@
 package at.asitplus.wallet.lib.jws
 
 import io.github.aakira.napier.Napier
-import io.matthewnelson.component.base64.Base64
-import io.matthewnelson.component.base64.decodeBase64ToArray
-import io.matthewnelson.component.base64.encodeBase64
+import io.matthewnelson.encoding.base64.Base64
+import io.matthewnelson.encoding.core.Decoder.Companion.decodeToByteArrayOrNull
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 
 /**
  * Representation of an encrypted JSON Web Encryption object, consisting of its 5 parts: Header, encrypted key,
@@ -22,11 +22,11 @@ data class JweEncrypted(
         get() = JweHeader.deserialize(headerAsParsed.decodeToString())
 
     fun serialize(): String {
-        return headerAsParsed.encodeBase64(Base64.UrlSafe(pad = false)) +
-                ".${encryptedKey?.encodeBase64(Base64.UrlSafe(pad = false)) ?: ""}" +
-                ".${iv.encodeBase64(Base64.UrlSafe(pad = false))}" +
-                ".${ciphertext.encodeBase64(Base64.UrlSafe(pad = false))}" +
-                ".${authTag.encodeBase64(Base64.UrlSafe(pad = false))}"
+        return headerAsParsed.encodeToString(Base64 { encodeToUrlSafe = true; padEncoded = false }) +
+                ".${encryptedKey?.encodeToString(Base64 { encodeToUrlSafe = true; padEncoded = false }) ?: ""}" +
+                ".${iv.encodeToString(Base64 { encodeToUrlSafe = true; padEncoded = false })}" +
+                ".${ciphertext.encodeToString(Base64 { encodeToUrlSafe = true; padEncoded = false })}" +
+                ".${authTag.encodeToString(Base64 { encodeToUrlSafe = true; padEncoded = false })}"
     }
 
     override fun equals(other: Any?): Boolean {
@@ -61,14 +61,14 @@ data class JweEncrypted(
         fun parse(it: String): JweEncrypted? {
             val stringList = it.replace("[^A-Za-z0-9-_.]".toRegex(), "").split(".")
             if (stringList.size != 5) return null.also { Napier.w("Could not parse JWE: $it") }
-            val headerAsParsed = stringList[0].decodeBase64ToArray()
+            val headerAsParsed = stringList[0].decodeToByteArrayOrNull(Base64())
                 ?: return null.also { Napier.w("Could not parse JWE: $it") }
-            val encryptedKey = stringList[1].decodeBase64ToArray()
-            val iv = stringList[2].decodeBase64ToArray()
+            val encryptedKey = stringList[1].decodeToByteArrayOrNull(Base64())
+            val iv = stringList[2].decodeToByteArrayOrNull(Base64())
                 ?: return null.also { Napier.w("Could not parse JWE: $it") }
-            val ciphertext = stringList[3].decodeBase64ToArray()
+            val ciphertext = stringList[3].decodeToByteArrayOrNull(Base64())
                 ?: return null.also { Napier.w("Could not parse JWE: $it") }
-            val authTag = stringList[4].decodeBase64ToArray()
+            val authTag = stringList[4].decodeToByteArrayOrNull(Base64())
                 ?: return null.also { Napier.w("Could not parse JWE: $it") }
             return JweEncrypted(headerAsParsed, encryptedKey, iv, ciphertext, authTag)
         }
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JwsService.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JwsService.kt
index 963ef50813737a85dfb1d180987b416c1ca44b7e..54b006761b3465dc8413a7a0026a5da1ba3202f5 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JwsService.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JwsService.kt
@@ -8,9 +8,9 @@ import at.asitplus.wallet.lib.jws.JwsExtensions.encodeToByteArray
 import at.asitplus.wallet.lib.jws.JwsExtensions.encodeWithLength
 import at.asitplus.wallet.lib.jws.JwsExtensions.extractSignatureValues
 import io.github.aakira.napier.Napier
-import io.matthewnelson.component.base64.Base64
-import io.matthewnelson.component.base64.encodeBase64
-import io.matthewnelson.component.base64.encodeBase64ToByteArray
+import io.matthewnelson.encoding.base64.Base64
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToByteArray
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 import kotlin.random.Random
 
 /**
@@ -82,7 +82,8 @@ class DefaultJwsService(private val cryptoService: CryptoService) : JwsService {
             return null.also { Napier.w("Algorithm or keyId not matching to cryptoService") }
         }
         val signatureInput = header.serialize().encodeToByteArray()
-            .encodeBase64(Base64.UrlSafe(pad = false)) + "." + payload.encodeBase64(Base64.UrlSafe(pad = false))
+            .encodeToString(Base64 { encodeToUrlSafe = true; padEncoded = false }) +
+                "." + payload.encodeToString(Base64 { encodeToUrlSafe = true; padEncoded = false })
         val signatureInputBytes = signatureInput.encodeToByteArray()
         val signature = cryptoService.sign(signatureInputBytes).getOrElse {
             Napier.w("No signature from native code", it)
@@ -130,7 +131,7 @@ class DefaultJwsService(private val cryptoService: CryptoService) : JwsService {
             return null
         }
         val iv = jweObject.iv
-        val aad = jweObject.headerAsParsed.encodeBase64ToByteArray(Base64.UrlSafe(pad = false))
+        val aad = jweObject.headerAsParsed.encodeToByteArray(Base64 { encodeToUrlSafe = true; padEncoded = false })
         val ciphertext = jweObject.ciphertext
         val authTag = jweObject.authTag
         val plaintext =
@@ -177,7 +178,7 @@ class DefaultJwsService(private val cryptoService: CryptoService) : JwsService {
         val iv = Random.Default.nextBytes(jweEncryption.ivLengthBits / 8)
         val headerSerialized = jweHeader.serialize()
         val aad = headerSerialized.encodeToByteArray()
-        val aadForCipher = aad.encodeBase64ToByteArray(Base64.UrlSafe(pad = false))
+        val aadForCipher = aad.encodeToByteArray(Base64 { encodeToUrlSafe = true; padEncoded = false })
         val ciphertext =
             cryptoService.encrypt(key, iv, aadForCipher, payload, jweEncryption).getOrElse {
                 Napier.w("No ciphertext from native code", it)
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JwsSigned.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JwsSigned.kt
index b18e6a752d8e7fc1f8f0480d64d8cb1c23ba97ba..8d89787a1f6c3beb4fa7cb76573c5cafff731c0f 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JwsSigned.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/JwsSigned.kt
@@ -1,9 +1,10 @@
 package at.asitplus.wallet.lib.jws
 
-import io.matthewnelson.component.base64.Base64
-import io.matthewnelson.component.base64.decodeBase64ToArray
-import io.matthewnelson.component.base64.encodeBase64
 import io.github.aakira.napier.Napier
+import io.matthewnelson.component.base64.decodeBase64ToArray
+import io.matthewnelson.encoding.base64.Base64
+import io.matthewnelson.encoding.core.Decoder.Companion.decodeToByteArrayOrNull
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 
 /**
  * Representation of a signed JSON Web Signature object, i.e. consisting of header, payload and signature.
@@ -15,7 +16,11 @@ data class JwsSigned(
     val plainSignatureInput: String,
 ) {
     fun serialize(): String {
-        return "${plainSignatureInput}.${signature.encodeBase64(Base64.UrlSafe(pad = false))}"
+        return "${plainSignatureInput}.${
+            signature.encodeToString(Base64 {
+                encodeToUrlSafe = true; padEncoded = false
+            })
+        }"
     }
 
     override fun equals(other: Any?): Boolean {
@@ -42,13 +47,13 @@ data class JwsSigned(
         fun parse(it: String): JwsSigned? {
             val stringList = it.replace("[^A-Za-z0-9-_.]".toRegex(), "").split(".")
             if (stringList.size != 3) return null.also { Napier.w("Could not parse JWS: $it") }
-            val headerInput = stringList[0].decodeBase64ToArray()
+            val headerInput = stringList[0].decodeToByteArrayOrNull(Base64())
                 ?: return null.also { Napier.w("Could not parse JWS: $it") }
             val header = JwsHeader.deserialize(headerInput.decodeToString())
                 ?: return null.also { Napier.w("Could not parse JWS: $it") }
-            val payload = stringList[1].decodeBase64ToArray()
+            val payload = stringList[1].decodeToByteArrayOrNull(Base64())
                 ?: return null.also { Napier.w("Could not parse JWS: $it") }
-            val signature = stringList[2].decodeBase64ToArray()
+            val signature = stringList[2].decodeToByteArrayOrNull(Base64())
                 ?: return null.also { Napier.w("Could not parse JWS: $it") }
             return JwsSigned(header, payload, signature, "${stringList[0]}.${stringList[1]}")
         }
diff --git a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/MultibaseHelper.kt b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/MultibaseHelper.kt
index 0f3d6b845038f3a0ac0f2261ed28bf9f48c6ffde..5793f52c8f78e5241746126bb2931b79b0e6801c 100644
--- a/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/MultibaseHelper.kt
+++ b/vclib/src/commonMain/kotlin/at/asitplus/wallet/lib/jws/MultibaseHelper.kt
@@ -3,6 +3,9 @@ package at.asitplus.wallet.lib.jws
 import at.asitplus.wallet.lib.cbor.CoseEllipticCurve
 import io.matthewnelson.component.base64.decodeBase64ToArray
 import io.matthewnelson.component.base64.encodeBase64
+import io.matthewnelson.encoding.base64.Base64
+import io.matthewnelson.encoding.core.Decoder.Companion.decodeToByteArrayOrNull
+import io.matthewnelson.encoding.core.Encoder.Companion.encodeToString
 
 
 object MultibaseHelper {
@@ -41,11 +44,11 @@ object MultibaseHelper {
         return decodeP256Key(multicodecDecode(multibaseDecode(stripped)))
     }
 
-    private fun multibaseWrapBase64(it: ByteArray) = "m${it.encodeBase64()}"
+    private fun multibaseWrapBase64(it: ByteArray) = "m${it.encodeToString(Base64())}"
 
     private fun multibaseDecode(it: String?) =
         if (it != null && it.startsWith("m")) {
-            it.removePrefix("m").decodeBase64ToArray()
+            it.removePrefix("m").decodeToByteArrayOrNull(Base64())
         } else null
 
     // 0x1200 would be with compression, so we'll use 0x1290