diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/compression/ZLIBCompression.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/compression/ZLIBCompression.kt
index 0c585d8bb3c30561a85492713a9467bf89c257b2..d03ef22a3372422c6651b5b12f62c12fdb4fa182 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/compression/ZLIBCompression.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/compression/ZLIBCompression.kt
@@ -1,14 +1,13 @@
 package de.rki.coronawarnapp.util.compression
 
 import okio.Buffer
-import okio.ByteString
 import okio.inflate
 import java.util.zip.Inflater
 import javax.inject.Inject
 
 class ZLIBCompression @Inject constructor() {
     @Suppress("NestedBlockDepth")
-    fun decompress(input: ByteString, sizeLimit: Long = -1L): ByteString = try {
+    fun decompress(input: ByteArray, sizeLimit: Long = -1L): ByteArray = try {
         val inflaterSource = input.let {
             val buffer = Buffer().write(it)
             buffer.inflate(Inflater())
@@ -24,10 +23,10 @@ class ZLIBCompression @Inject constructor() {
             }
         }
 
-        sink.readByteString()
+        sink.readByteArray()
     } catch (e: Throwable) {
         throw InvalidInputException("ZLIB decompression failed.", e)
     }
 }
 
-fun ByteString.inflate(sizeLimit: Long = -1L) = ZLIBCompression().decompress(this, sizeLimit)
+fun ByteArray.inflate(sizeLimit: Long = -1L) = ZLIBCompression().decompress(this, sizeLimit)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/encoding/Base45Extensions.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/encoding/Base45Extensions.kt
index aeddd2010e19329da9e2e337a899a1a5dccd90ed..9edb3c513aecd78e1ec6da3c000aecc5161c246b 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/encoding/Base45Extensions.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/encoding/Base45Extensions.kt
@@ -1,16 +1,13 @@
 package de.rki.coronawarnapp.util.encoding
 
-import okio.ByteString
-import okio.ByteString.Companion.toByteString
-
 /**
- * Decodes [String] into [ByteString] using Base45 decoder
- * @return [ByteString]
+ * Decodes [String] into [ByteArray] using Base45 decoder
+ * @return [ByteArray]
  */
-fun String.decodeBase45(): ByteString = Base45Decoder.decode(this).toByteString()
+fun String.decodeBase45(): ByteArray = Base45Decoder.decode(this)
 
 /**
- * Encodes [ByteString] into base45 [String]
+ * Encodes [ByteArray] into base45 [String]
  * @return [String]
  */
-fun ByteString.base45(): String = Base45Decoder.encode(this.toByteArray())
+fun ByteArray.base45(): String = Base45Decoder.encode(this)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/VaccinationCertificate.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/VaccinationCertificate.kt
index 71737e4627f3a185e671b8bdcd8f5bb1b8b87f56..98c5018ec7464e0c8301d8cbc1f3287bba641d5e 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/VaccinationCertificate.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/VaccinationCertificate.kt
@@ -1,6 +1,7 @@
 package de.rki.coronawarnapp.vaccination.core
 
 import de.rki.coronawarnapp.ui.Country
+import de.rki.coronawarnapp.vaccination.core.qrcode.QrCodeString
 import org.joda.time.Instant
 import org.joda.time.LocalDate
 
@@ -27,4 +28,6 @@ interface VaccinationCertificate {
     val issuer: String
     val issuedAt: Instant
     val expiresAt: Instant
+
+    val vaccinationQrCodeString: QrCodeString
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/certificate/HealthCertificateCOSEDecoder.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/certificate/HealthCertificateCOSEDecoder.kt
index af6a7aaf0781b977e6c40570f0842d80d19e68f8..fbb291dcd3dee0f8be7c67f9d11813b453d6727b 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/certificate/HealthCertificateCOSEDecoder.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/certificate/HealthCertificateCOSEDecoder.kt
@@ -9,7 +9,7 @@ import javax.inject.Inject
 class HealthCertificateCOSEDecoder @Inject constructor() {
 
     fun decode(input: RawCOSEObject): CBORObject = try {
-        val messageObject = CBORObject.DecodeFromBytes(input.asByteArray).validate()
+        val messageObject = CBORObject.DecodeFromBytes(input).validate()
         val content = messageObject[2].GetByteString()
         CBORObject.DecodeFromBytes(content)
     } catch (e: InvalidHealthCertificateException) {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/certificate/RawCOSEObject.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/certificate/RawCOSEObject.kt
index 28fdf8f2a2362233297bf952100920bab351181e..0a13bb0971b82d0456b0539469d6e0e63a16d690 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/certificate/RawCOSEObject.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/certificate/RawCOSEObject.kt
@@ -1,82 +1,3 @@
 package de.rki.coronawarnapp.vaccination.core.certificate
 
-import com.google.gson.JsonParseException
-import com.google.gson.TypeAdapter
-import com.google.gson.stream.JsonReader
-import com.google.gson.stream.JsonWriter
-import okhttp3.MediaType.Companion.toMediaTypeOrNull
-import okhttp3.RequestBody
-import okhttp3.RequestBody.Companion.toRequestBody
-import okhttp3.ResponseBody
-import okio.ByteString
-import okio.ByteString.Companion.decodeBase64
-import okio.ByteString.Companion.toByteString
-import org.json.JSONObject
-import retrofit2.Converter
-import retrofit2.Retrofit
-import java.lang.reflect.Type
-import javax.inject.Inject
-
-data class RawCOSEObject(
-    val data: ByteString
-) {
-    constructor(data: ByteArray) : this(data.toByteString())
-
-    val asByteArray: ByteArray
-        get() = data.toByteArray()
-
-    companion object {
-        val EMPTY = RawCOSEObject(data = ByteString.EMPTY)
-    }
-
-    class JsonAdapter : TypeAdapter<RawCOSEObject>() {
-        override fun write(out: JsonWriter, value: RawCOSEObject?) {
-            if (value == null) out.nullValue()
-            else value.data.base64().let { out.value(it) }
-        }
-
-        override fun read(reader: JsonReader): RawCOSEObject? = when (reader.peek()) {
-            JSONObject.NULL -> reader.nextNull().let { null }
-            else -> {
-                val raw = reader.nextString()
-                raw.decodeBase64()?.let { RawCOSEObject(data = it) }
-                    ?: throw JsonParseException("Can't decode base64 ByteArray: $raw")
-            }
-        }
-    }
-
-    class RetroFitConverterFactory @Inject constructor() : Converter.Factory() {
-
-        override fun requestBodyConverter(
-            type: Type,
-            parameterAnnotations: Array<out Annotation>,
-            methodAnnotations: Array<out Annotation>,
-            retrofit: Retrofit
-        ): Converter<RawCOSEObject, RequestBody> {
-            return ConverterToBody()
-        }
-
-        override fun responseBodyConverter(
-            type: Type,
-            annotations: Array<out Annotation>,
-            retrofit: Retrofit
-        ): Converter<ResponseBody, RawCOSEObject> {
-            return ConverterFromBody()
-        }
-
-        class ConverterFromBody : Converter<ResponseBody, RawCOSEObject> {
-            override fun convert(value: ResponseBody): RawCOSEObject {
-                val rawData = value.byteString()
-                return RawCOSEObject(rawData)
-            }
-        }
-
-        class ConverterToBody : Converter<RawCOSEObject, RequestBody> {
-            override fun convert(value: RawCOSEObject): RequestBody {
-                return value.data.toRequestBody(
-                    "application/octet-stream".toMediaTypeOrNull()
-                )
-            }
-        }
-    }
-}
+typealias RawCOSEObject = ByteArray
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/certificate/VaccinationDGCV1Parser.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/certificate/VaccinationDGCV1Parser.kt
index c2d664c19e97452d97cc9ca4f5c2e80c4f9fdb16..e25defbc9cab81c1be8c37c0f6aba41716b14f75 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/certificate/VaccinationDGCV1Parser.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/certificate/VaccinationDGCV1Parser.kt
@@ -35,9 +35,9 @@ class VaccinationDGCV1Parser @Inject constructor(
         if (vaccinationDatas.isEmpty()) {
             throw InvalidHealthCertificateException(VC_NO_VACCINATION_ENTRY)
         }
+        // Force date parsing
         dateOfBirth
         vaccinationDatas.forEach {
-            // Force date parsing
             it.vaccinatedAt
         }
         return this
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/common/RawCOSEObject.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/common/RawCOSEObject.kt
deleted file mode 100644
index 170af7e10caadfd5dc1149ca9472cd5b85a4463d..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/common/RawCOSEObject.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-package de.rki.coronawarnapp.vaccination.core.common
-
-import com.google.gson.JsonParseException
-import com.google.gson.TypeAdapter
-import com.google.gson.stream.JsonReader
-import com.google.gson.stream.JsonWriter
-import okio.ByteString
-import okio.ByteString.Companion.decodeBase64
-import okio.ByteString.Companion.toByteString
-import org.json.JSONObject
-
-data class RawCOSEObject(
-    val data: ByteString
-) {
-    constructor(data: ByteArray) : this(data.toByteString())
-
-    val asByteArray: ByteArray
-        get() = data.toByteArray()
-
-    companion object {
-        val EMPTY = RawCOSEObject(data = ByteString.EMPTY)
-    }
-
-    class JsonAdapter : TypeAdapter<RawCOSEObject>() {
-        override fun write(out: JsonWriter, value: RawCOSEObject?) {
-            if (value == null) out.nullValue()
-            else value.data.base64().let { out.value(it) }
-        }
-
-        override fun read(reader: JsonReader): RawCOSEObject? = when (reader.peek()) {
-            JSONObject.NULL -> reader.nextNull().let { null }
-            else -> {
-                val raw = reader.nextString()
-                raw.decodeBase64()?.let { RawCOSEObject(data = it) }
-                    ?: throw JsonParseException("Can't decode base64 ByteArray: $raw")
-            }
-        }
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationCertificateCOSEParser.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationCertificateCOSEParser.kt
deleted file mode 100644
index 45bdaf3263040a11abdf843ffb590127c437be46..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationCertificateCOSEParser.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package de.rki.coronawarnapp.vaccination.core.qrcode
-
-import de.rki.coronawarnapp.vaccination.core.certificate.HealthCertificateCOSEDecoder
-import de.rki.coronawarnapp.vaccination.core.certificate.HealthCertificateHeaderParser
-import de.rki.coronawarnapp.vaccination.core.certificate.RawCOSEObject
-import de.rki.coronawarnapp.vaccination.core.certificate.VaccinationDGCV1Parser
-import timber.log.Timber
-import javax.inject.Inject
-
-class VaccinationCertificateCOSEParser @Inject constructor(
-    private val coseDecoder: HealthCertificateCOSEDecoder,
-    private val headerParser: HealthCertificateHeaderParser,
-    private val bodyParser: VaccinationDGCV1Parser,
-) {
-
-    fun parse(rawCOSEObject: RawCOSEObject): VaccinationCertificateData {
-        Timber.v("Parsing COSE for vaccination certificate.")
-        val cbor = coseDecoder.decode(rawCOSEObject)
-
-        return VaccinationCertificateData(
-            header = headerParser.parse(cbor),
-            certificate = bodyParser.parse(cbor)
-        ).also {
-            Timber.v("Parsed vaccination certificate for %s", it.certificate.nameData.familyNameStandardized)
-        }
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationCertificateData.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationCertificateData.kt
index b0661dcc7a824926c4c9aa971f66ca66879b32ac..31da1c88bc2ad193a46614debcbcaea02feae7a6 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationCertificateData.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationCertificateData.kt
@@ -4,7 +4,7 @@ import de.rki.coronawarnapp.vaccination.core.certificate.CoseCertificateHeader
 import de.rki.coronawarnapp.vaccination.core.certificate.VaccinationDGCV1
 
 /**
- * Represents the information gained from data in COSE representation
+ * Represents the parsed data from the QR code
  */
 data class VaccinationCertificateData(
     val header: CoseCertificateHeader,
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationCertificateQRCode.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationCertificateQRCode.kt
index 994fd52a3c25d7b32bd169c9c02ecf5769a9dc47..5d72448a8a526c2954b15ffb67fa244fb20768b5 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationCertificateQRCode.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationCertificateQRCode.kt
@@ -1,11 +1,11 @@
 package de.rki.coronawarnapp.vaccination.core.qrcode
 
-import de.rki.coronawarnapp.vaccination.core.certificate.RawCOSEObject
-
 data class VaccinationCertificateQRCode(
+    val qrCodeString: QrCodeString,
     val parsedData: VaccinationCertificateData,
-    val certificateCOSE: RawCOSEObject,
 ) {
     val uniqueCertificateIdentifier: String
         get() = parsedData.certificate.vaccinationDatas.single().uniqueCertificateIdentifier
 }
+
+typealias QrCodeString = String
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeExtractor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeExtractor.kt
index bf604bbf7601819b97cfdb92f7b84218250621ce..b4ab3e75377eb1e08946d52e27f01f3175155e9e 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeExtractor.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeExtractor.kt
@@ -2,51 +2,68 @@ package de.rki.coronawarnapp.vaccination.core.qrcode
 
 import de.rki.coronawarnapp.coronatest.qrcode.QrCodeExtractor
 import de.rki.coronawarnapp.util.compression.inflate
-import de.rki.coronawarnapp.util.encoding.decodeBase45
+import de.rki.coronawarnapp.util.encoding.Base45Decoder
+import de.rki.coronawarnapp.vaccination.core.certificate.HealthCertificateCOSEDecoder
+import de.rki.coronawarnapp.vaccination.core.certificate.HealthCertificateHeaderParser
 import de.rki.coronawarnapp.vaccination.core.certificate.InvalidHealthCertificateException
 import de.rki.coronawarnapp.vaccination.core.certificate.InvalidHealthCertificateException.ErrorCode.HC_BASE45_DECODING_FAILED
 import de.rki.coronawarnapp.vaccination.core.certificate.InvalidHealthCertificateException.ErrorCode.HC_ZLIB_DECOMPRESSION_FAILED
 import de.rki.coronawarnapp.vaccination.core.certificate.RawCOSEObject
-import okio.ByteString
+import de.rki.coronawarnapp.vaccination.core.certificate.VaccinationDGCV1Parser
 import timber.log.Timber
 import javax.inject.Inject
 
 class VaccinationQRCodeExtractor @Inject constructor(
-    private val vaccinationCertificateCOSEParser: VaccinationCertificateCOSEParser,
+    private val coseDecoder: HealthCertificateCOSEDecoder,
+    private val headerParser: HealthCertificateHeaderParser,
+    private val bodyParser: VaccinationDGCV1Parser,
 ) : QrCodeExtractor<VaccinationCertificateQRCode> {
 
     override fun canHandle(rawString: String): Boolean = rawString.startsWith(PREFIX)
 
     override fun extract(rawString: String): VaccinationCertificateQRCode {
-        val rawCOSEObject = rawString
+        val parsedData = rawString
             .removePrefix(PREFIX)
-            .tryDecodeBase45()
+            .decodeBase45()
             .decompress()
+            .parse()
 
         return VaccinationCertificateQRCode(
-            parsedData = vaccinationCertificateCOSEParser.parse(rawCOSEObject),
-            certificateCOSE = rawCOSEObject,
+            parsedData = parsedData,
+            qrCodeString = rawString,
         )
     }
 
-    private fun String.tryDecodeBase45(): ByteString = try {
-        this.decodeBase45()
+    private fun String.decodeBase45(): ByteArray = try {
+        Base45Decoder.decode(this)
     } catch (e: Throwable) {
         Timber.e(e)
         throw InvalidHealthCertificateException(HC_BASE45_DECODING_FAILED)
     }
 
-    private fun ByteString.decompress(): RawCOSEObject = try {
-        RawCOSEObject(this.inflate(sizeLimit = DEFAULT_SIZE_LIMIT))
+    private fun ByteArray.decompress(): RawCOSEObject = try {
+        this.inflate(sizeLimit = DEFAULT_SIZE_LIMIT)
     } catch (e: Throwable) {
         Timber.e(e)
         throw InvalidHealthCertificateException(HC_ZLIB_DECOMPRESSION_FAILED)
     }
 
+    fun RawCOSEObject.parse(): VaccinationCertificateData {
+        Timber.v("Parsing COSE for vaccination certificate.")
+        val cbor = coseDecoder.decode(this)
+
+        return VaccinationCertificateData(
+            header = headerParser.parse(cbor),
+            certificate = bodyParser.parse(cbor)
+        ).also {
+            Timber.v("Parsed vaccination certificate for %s", it.certificate.nameData.familyNameStandardized)
+        }
+    }
+
     companion object {
         private const val PREFIX = "HC1:"
 
         // Zip bomb
-        const val DEFAULT_SIZE_LIMIT = 1024L * 1024 * 10L // 10 MB
+        private const val DEFAULT_SIZE_LIMIT = 1024L * 1024 * 10L // 10 MB
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/VaccinationRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/VaccinationRepository.kt
index ca2b7dc7eee993fbf82ce56d147aa0265bd833fd..1621f9eea96f84d4e1af2dcda9450efd73ab6fcc 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/VaccinationRepository.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/VaccinationRepository.kt
@@ -10,8 +10,8 @@ import de.rki.coronawarnapp.vaccination.core.VaccinatedPerson
 import de.rki.coronawarnapp.vaccination.core.VaccinatedPersonIdentifier
 import de.rki.coronawarnapp.vaccination.core.VaccinationCertificate
 import de.rki.coronawarnapp.vaccination.core.personIdentifier
-import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationCertificateCOSEParser
 import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationCertificateQRCode
+import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationQRCodeExtractor
 import de.rki.coronawarnapp.vaccination.core.repository.errors.VaccinationCertificateNotFoundException
 import de.rki.coronawarnapp.vaccination.core.repository.storage.VaccinatedPersonData
 import de.rki.coronawarnapp.vaccination.core.repository.storage.VaccinationContainer
@@ -36,8 +36,8 @@ class VaccinationRepository @Inject constructor(
     dispatcherProvider: DispatcherProvider,
     private val timeStamper: TimeStamper,
     private val storage: VaccinationStorage,
-    private val valueSetsRepository: ValueSetsRepository,
-    private val vaccionationCoseParser: VaccinationCertificateCOSEParser,
+    valueSetsRepository: ValueSetsRepository,
+    private val vaccinationQRCodeExtractor: VaccinationQRCodeExtractor,
 ) {
 
     private val internalData: HotDataFlow<Set<VaccinatedPerson>> = HotDataFlow(
@@ -102,7 +102,7 @@ class VaccinationRepository @Inject constructor(
 
             val newCertificate = qrCode.toVaccinationContainer(
                 scannedAt = timeStamper.nowUTC,
-                coseParser = vaccionationCoseParser,
+                qrCodeExtractor = vaccinationQRCodeExtractor,
             )
 
             val modifiedPerson = originalPerson.copy(
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/ContainerPostProcessor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/ContainerPostProcessor.kt
index 636530163dea7d8e048f678347bdef61b2a100d8..c4f2debb082773d1baefb0f9483151182d42e0b5 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/ContainerPostProcessor.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/ContainerPostProcessor.kt
@@ -7,14 +7,14 @@ import com.google.gson.reflect.TypeToken
 import com.google.gson.stream.JsonReader
 import com.google.gson.stream.JsonWriter
 import dagger.Reusable
-import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationCertificateCOSEParser
+import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationQRCodeExtractor
 import timber.log.Timber
 import java.io.IOException
 import javax.inject.Inject
 
 @Reusable
 class ContainerPostProcessor @Inject constructor(
-    private val vaccinationCertificateCOSEParser: VaccinationCertificateCOSEParser,
+    private val qrCodeExtractor: VaccinationQRCodeExtractor,
 ) : TypeAdapterFactory {
     override fun <T> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T> {
         val delegate = gson.getDelegateAdapter(this, type)
@@ -30,7 +30,7 @@ class ContainerPostProcessor @Inject constructor(
                 when (obj) {
                     is VaccinationContainer -> {
                         Timber.v("Injecting VaccinationContainer %s", obj.hashCode())
-                        obj.parser = vaccinationCertificateCOSEParser
+                        obj.qrCodeExtractor = qrCodeExtractor
                     }
                 }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationContainer.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationContainer.kt
index 01dd4aaf9908afeaa2d04a6a021787d3f5b056fd..76ca4e4b5c2840800c9f0c0c19be965abad73ba9 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationContainer.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationContainer.kt
@@ -6,33 +6,33 @@ import de.rki.coronawarnapp.ui.Country
 import de.rki.coronawarnapp.vaccination.core.VaccinatedPersonIdentifier
 import de.rki.coronawarnapp.vaccination.core.VaccinationCertificate
 import de.rki.coronawarnapp.vaccination.core.certificate.CoseCertificateHeader
-import de.rki.coronawarnapp.vaccination.core.certificate.RawCOSEObject
 import de.rki.coronawarnapp.vaccination.core.certificate.VaccinationDGCV1
 import de.rki.coronawarnapp.vaccination.core.personIdentifier
-import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationCertificateCOSEParser
+import de.rki.coronawarnapp.vaccination.core.qrcode.QrCodeString
 import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationCertificateData
 import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationCertificateQRCode
+import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationQRCodeExtractor
 import de.rki.coronawarnapp.vaccination.core.server.valueset.VaccinationValueSet
 import org.joda.time.Instant
 import org.joda.time.LocalDate
 
 @Keep
 data class VaccinationContainer internal constructor(
-    @SerializedName("vaccinationCertificateCOSE") val vaccinationCertificateCOSE: RawCOSEObject,
+    @SerializedName("vaccinationQrCode") val vaccinationQrCode: QrCodeString,
     @SerializedName("scannedAt") val scannedAt: Instant,
 ) {
 
     // Either set by [ContainerPostProcessor] or via [toVaccinationContainer]
-    @Transient lateinit var parser: VaccinationCertificateCOSEParser
+    @Transient lateinit var qrCodeExtractor: VaccinationQRCodeExtractor
     @Transient internal var preParsedData: VaccinationCertificateData? = null
 
     // Otherwise GSON unsafes reflection to create this class, and sets the LAZY to null
     @Suppress("unused")
-    constructor() : this(RawCOSEObject.EMPTY, Instant.EPOCH)
+    constructor() : this("", Instant.EPOCH)
 
     @delegate:Transient
     private val certificateData: VaccinationCertificateData by lazy {
-        preParsedData ?: parser.parse(vaccinationCertificateCOSE)
+        preParsedData ?: qrCodeExtractor.extract(vaccinationQrCode).parsedData
     }
 
     val header: CoseCertificateHeader
@@ -91,16 +91,19 @@ data class VaccinationContainer internal constructor(
             get() = header.issuedAt
         override val expiresAt: Instant
             get() = header.expiresAt
+
+        override val vaccinationQrCodeString: QrCodeString
+            get() = vaccinationQrCode
     }
 }
 
 fun VaccinationCertificateQRCode.toVaccinationContainer(
     scannedAt: Instant,
-    coseParser: VaccinationCertificateCOSEParser,
+    qrCodeExtractor: VaccinationQRCodeExtractor,
 ) = VaccinationContainer(
-    vaccinationCertificateCOSE = certificateCOSE,
+    vaccinationQrCode = this.qrCodeString,
     scannedAt = scannedAt,
 ).apply {
-    parser = coseParser
+    this.qrCodeExtractor = qrCodeExtractor
     preParsedData = parsedData
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorage.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorage.kt
index 05366335217111de618e42c3c56ab9401642622b..ee8d04c714deaf19c73b3d36dde07c43b3c7bd92 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorage.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorage.kt
@@ -6,7 +6,6 @@ import com.google.gson.Gson
 import de.rki.coronawarnapp.util.di.AppContext
 import de.rki.coronawarnapp.util.serialization.BaseGson
 import de.rki.coronawarnapp.util.serialization.fromJson
-import de.rki.coronawarnapp.vaccination.core.certificate.RawCOSEObject
 import timber.log.Timber
 import javax.inject.Inject
 import javax.inject.Singleton
@@ -25,7 +24,6 @@ class VaccinationStorage @Inject constructor(
     private val gson by lazy {
         // Allow for custom type adapter.
         baseGson.newBuilder().apply {
-            registerTypeAdapter(RawCOSEObject::class.java, RawCOSEObject.JsonAdapter())
             registerTypeAdapterFactory(containerPostProcessor)
         }.create()
     }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/compression/ZLIBCompressionTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/compression/ZLIBCompressionTest.kt
index f924acfd412b7ba3b7329c771d7125efbaceb50c..4233793344df911390624521889f7bdb0a32e120 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/compression/ZLIBCompressionTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/compression/ZLIBCompressionTest.kt
@@ -12,13 +12,13 @@ class ZLIBCompressionTest : BaseTest() {
 
     @Test
     fun `basic decompression`() {
-        ZLIBCompression().decompress(compressed).utf8() shouldBe "The Cake Is A Lie"
+        ZLIBCompression().decompress(compressed.toByteArray()) shouldBe "The Cake Is A Lie".toByteArray()
     }
 
     @Test
     fun `invalid decompression`() {
         val error = shouldThrow<InvalidInputException> {
-            ZLIBCompression().decompress(compressed.substring(5))
+            ZLIBCompression().decompress(compressed.substring(5).toByteArray())
         }
         error.causes().first { it is DataFormatException }.message shouldBe "incorrect header check"
     }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/encoding/Base45ExtensionsTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/encoding/Base45ExtensionsTest.kt
index f3af93059e26963f129702b15665b9fb086deb52..b0256e9a4b3ec7bc9e4b67d76857a22788c8984c 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/encoding/Base45ExtensionsTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/encoding/Base45ExtensionsTest.kt
@@ -1,7 +1,6 @@
 package de.rki.coronawarnapp.util.encoding
 
 import io.kotest.matchers.shouldBe
-import okio.ByteString.Companion.toByteString
 import okio.internal.commonAsUtf8ToByteArray
 import org.junit.jupiter.api.Test
 import testhelpers.BaseTest
@@ -10,15 +9,15 @@ class Base45ExtensionsTest : BaseTest() {
 
     @Test
     fun `encode - extension`() {
-        "AB".toByteArray().toByteString().base45() shouldBe "BB8"
-        "Hello!!".commonAsUtf8ToByteArray().toByteString().base45() shouldBe "%69 VD92EX0"
-        "base-45".commonAsUtf8ToByteArray().toByteString().base45() shouldBe "UJCLQE7W581"
+        "AB".toByteArray().base45() shouldBe "BB8"
+        "Hello!!".commonAsUtf8ToByteArray().base45() shouldBe "%69 VD92EX0"
+        "base-45".commonAsUtf8ToByteArray().base45() shouldBe "UJCLQE7W581"
     }
 
     @Test
     fun `decode - extension`() {
-        "BB8".decodeBase45() shouldBe "AB".toByteArray().toByteString()
-        "%69 VD92EX0".decodeBase45() shouldBe "Hello!!".toByteArray().toByteString()
-        "UJCLQE7W581".decodeBase45() shouldBe "base-45".toByteArray().toByteString()
+        "BB8".decodeBase45() shouldBe "AB".toByteArray()
+        "%69 VD92EX0".decodeBase45() shouldBe "Hello!!".toByteArray()
+        "UJCLQE7W581".decodeBase45() shouldBe "base-45".toByteArray()
     }
 }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/RawCOSEObjectTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/RawCOSEObjectTest.kt
deleted file mode 100644
index b1759ba4967e7e89bc365bab262062a8f722eeb5..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/RawCOSEObjectTest.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-package de.rki.coronawarnapp.vaccination.core
-
-import com.google.gson.GsonBuilder
-import de.rki.coronawarnapp.util.serialization.fromJson
-import de.rki.coronawarnapp.vaccination.core.certificate.RawCOSEObject
-import io.kotest.matchers.shouldBe
-import io.kotest.matchers.shouldNotBe
-import org.junit.jupiter.api.BeforeEach
-import org.junit.jupiter.api.Test
-import testhelpers.BaseTest
-
-class RawCOSEObjectTest : BaseTest() {
-
-    @BeforeEach
-    fun setup() {
-    }
-
-    @Test
-    fun `comparison and conversion`() {
-        val rawRaw = "The Cake Is A Lie!".toByteArray()
-        val rawRaw2 = "The Cake Is Not A Lie!".toByteArray() // This is a lie
-        val rawCOSEObject1 = RawCOSEObject(rawRaw)
-        val rawCOSEObject2 = RawCOSEObject(rawRaw2)
-
-        rawRaw shouldNotBe rawRaw2
-        rawCOSEObject1 shouldNotBe rawCOSEObject2
-
-        rawCOSEObject1.asByteArray shouldBe rawRaw
-        rawCOSEObject2.asByteArray shouldBe rawRaw2
-    }
-
-    @Test
-    fun `serialization and deserialization`() {
-        val rawRaw = "The Cake Is A Lie!".toByteArray()
-        val rawRaw2 = "The Cake Is Not A Lie!".toByteArray() // This is a lie
-        val rawCOSEObject1 = RawCOSEObject(rawRaw)
-        val rawCOSEObject2 = RawCOSEObject(rawRaw2)
-
-        val gson = GsonBuilder().apply {
-            registerTypeAdapter(RawCOSEObject::class.java, RawCOSEObject.JsonAdapter())
-        }.create()
-
-        val json1 = gson.toJson(rawCOSEObject1)
-        json1 shouldBe "\"VGhlIENha2UgSXMgQSBMaWUh\""
-        gson.fromJson<RawCOSEObject>(json1) shouldBe rawCOSEObject1
-
-        val json2 = gson.toJson(rawCOSEObject2)
-        json2 shouldBe "\"VGhlIENha2UgSXMgTm90IEEgTGllIQ\\u003d\\u003d\""
-        gson.fromJson<RawCOSEObject>(json2) shouldBe rawCOSEObject2
-    }
-}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinationTestData.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinationTestData.kt
index a998406bb63c4697f1ae44255329d1e4798a6c6d..e5c19e3297000f5c72f776717d2ada42571fa159 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinationTestData.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinationTestData.kt
@@ -1,28 +1,20 @@
 package de.rki.coronawarnapp.vaccination.core
 
-import de.rki.coronawarnapp.util.compression.inflate
-import de.rki.coronawarnapp.util.encoding.decodeBase45
-import de.rki.coronawarnapp.vaccination.core.certificate.RawCOSEObject
 import de.rki.coronawarnapp.vaccination.core.certificate.VaccinationDGCV1
-import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationCertificateCOSEParser
+import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationQRCodeExtractor
 import de.rki.coronawarnapp.vaccination.core.repository.storage.VaccinatedPersonData
 import de.rki.coronawarnapp.vaccination.core.repository.storage.VaccinationContainer
 import org.joda.time.Instant
 import javax.inject.Inject
 
 class VaccinationTestData @Inject constructor(
-    private val vaccinationCertificateCOSEParser: VaccinationCertificateCOSEParser,
+    private var qrCodeExtractor: VaccinationQRCodeExtractor,
 ) {
 
     // AndreasAstra1.pdf
     val personAVac1QR =
         "HC1:6BFOXN*TS0BI\$ZD.P9UOL97O4-2HH77HRM3DSPTLRR+%3KXH9M9ESIGUBA KWML%6S5B9-+P70Q5VC9:BPCNYKMXEE1JAA/CXGG0JK1WL260X638J3-E3ND3DAJ-43TTTO3HK1H3QBCWNZ83UQJ:T0/8F7V0HKN:Q8.HBV+0SZ4GH00T9UKP0T9WC5PF6846A\$Q$76QW6%V98T5\$FQMI5DN9QZ5Y0Q\$UPE%5MZ5*T57ZA\$O7T6LEJOA+MZ55EII-EB1EKC422JBBD0D2K.EJJ14B2MP41WTRZPQEC5L64HX6IAS 8S8FT/MAMXP6QS03L0QIRR97I2HOAXL92L0. KOKG8VG5SI:TU+MMPZ55%PBT1YEGEA7IB65C94JBQ2NLEE:NQ% GC3MXHFLF9OIFN0IZ95LJL80P1FDLW452I8941:HH3M41GTNP8EFUNT$.FTD852IWKP/HLIJL8JF8JF172IMAS EDAHMXFBFBQSKJE72KV\$FHJ%3O%6:XM+1QD+T2/VKKER3L3%1THL7MGY.1S:T:GLOX6OCE7+RWYL3.C-L27WNV0G::M74O%K7C50AAEI4"
 
-    val personAVac1COSE: RawCOSEObject = personAVac1QR
-        .removePrefix("HC1:")
-        .decodeBase45().inflate()
-        .let { RawCOSEObject(data = it) }
-
     val personAVac1Certificate = VaccinationDGCV1(
         version = "1.0.0",
         nameData = VaccinationDGCV1.NameData(
@@ -50,20 +42,15 @@ class VaccinationTestData @Inject constructor(
 
     val personAVac1Container = VaccinationContainer(
         scannedAt = Instant.ofEpochMilli(1620062834471),
-        vaccinationCertificateCOSE = personAVac1COSE,
+        vaccinationQrCode = personAVac1QR,
     ).apply {
-        parser = vaccinationCertificateCOSEParser
+        qrCodeExtractor = this@VaccinationTestData.qrCodeExtractor
     }
 
     // AndreasAstra2.pdf
     val personAVac2QR =
         "6BFOXN*TS0BI\$ZD.P9UOL97O4-2HH77HRM3DSPTLRR+%3D H9M9ESIGUBA KWMLYX1HXK 0DV:D5VC9:BPCNYKMXEE1JAA/CZIK0JK1WL260X638J3-E3ND3DAJ-43TTTMDF6S8:B73QN VNZ.0K6HYI3CNN96BPHNW*0I85V.499TXY9KK9%OC+G9QJPNF67J6QW67KQ9G66PPM4MLJE+.PDB9L6Q2+PFQ5DB96PP5/P-59A%N+892 7J235II3NJ7PK7SLQMIPUBN9CIZI.EJJ14B2MP41IZRZPQEC5L64HX6IAS 8SAFT/MAMXP6QS03L0QIRR97I2HOAXL92L0. KOKGGVG5SI:TU+MMPZ55%PBT1YEGEA7IB65C94JBQ2NLEE:NQ% GC3MXHFLF9OIFN0IZ95LJL80P1FDLW452I8941:HH3M41GTNP8EFUNT\$.FTD852IWKP/HLIJL8JF8JF172E2JA0K*WDQMPB8T3%KLUSR43M.F\$QBQDR\$VT7V01Y7J0BOZLH+D-QF6MO\$R3%XB+.4QI596GY\$SITJP5BS0DFROC.7B.2RTB*UNYSM$*00HIL+H"
 
-    val personAVac2COSE: RawCOSEObject = personAVac2QR
-        .removePrefix("HC1:")
-        .decodeBase45().inflate()
-        .let { RawCOSEObject(data = it) }
-
     val personAVac2Certificate = VaccinationDGCV1(
         version = "1.0.0",
         nameData = VaccinationDGCV1.NameData(
@@ -91,9 +78,9 @@ class VaccinationTestData @Inject constructor(
 
     val personAVac2Container = VaccinationContainer(
         scannedAt = Instant.ofEpochMilli(1620069934471),
-        vaccinationCertificateCOSE = personAVac2COSE,
+        vaccinationQrCode = personAVac2QR,
     ).apply {
-        parser = vaccinationCertificateCOSEParser
+        qrCodeExtractor = this@VaccinationTestData.qrCodeExtractor
     }
 
     val personAData2Vac1Proof = VaccinatedPersonData(
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorageTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorageTest.kt
index f931969cdc7a2f15da06aedf736642d47e00c507..a888628a60455a202632c24e041d74366ce81758 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorageTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorageTest.kt
@@ -70,10 +70,10 @@ class VaccinationStorageTest : BaseTest() {
             {
                 "vaccinationData": [
                     {
-                        "vaccinationCertificateCOSE": "${testData.personAVac1COSE.data.base64()}",
+                        "vaccinationQrCode": "${testData.personAVac1QR}",
                         "scannedAt": 1620062834471
                     }, {
-                        "vaccinationCertificateCOSE": "${testData.personAVac2COSE.data.base64()}",
+                        "vaccinationQrCode": "${testData.personAVac2QR}",
                         "scannedAt": 1620069934471
                     }
                 ]