From ab4d8ba6685ce20b4b3368abb4e84c3a54f6c9b3 Mon Sep 17 00:00:00 2001
From: Lukas Lechner <lukas.lechner@sap.com>
Date: Thu, 1 Apr 2021 16:37:06 +0200
Subject: [PATCH] Update CheckIn and CheckInEntity (EXPOSUREAPP-6065) (#2735)

* Update from https://github.com/corona-warn-app/cwa-protocol-buffers/commit/8037bb0a273a815c083d4842b412ad141824ad91

* Update from https://github.com/corona-warn-app/cwa-protocol-buffers/commit/4e280653de2dd8a6d32a8ac43ed876879d5803b4

* Fix CheckInsTransformer.kt and TraceTimeIntervalWarningRepository.kt

* Delete TraceLocationQRCodeVerifier.kt, Adapt VerifiedTraceLocation.kt

* More adaptions

* Fix check-in database test

* Adapt TraceLocationEntity.kt and tests

* Added calculation for tracelocationId to VerifiedTraceLocation
Used id in checkin creation

* Added initial tests for trace location id generation

* Ktlint fixes

* Merge branch 'release/2.0.x' into chore/DEV-update-checkin-entity

Co-authored-by: corona-warn-app <cwa.technical-user@sap.com>
Co-authored-by: harambasicluka <64483219+harambasicluka@users.noreply.github.com>
Co-authored-by: Kolya Opahle <k.opahle@sap.com>
---
 .../1.json                                    |  30 +-
 .../qrcode/VerifiedTraceLocationTest.kt       | 293 ++++++++++--------
 .../storage/CheckInDatabaseData.kt            |  11 +-
 .../eventregistration/checkins/CheckIn.kt     |  16 +-
 .../checkins/qrcode/VerifiedTraceLocation.kt  |  14 +
 .../entity/TraceLocationCheckInEntity.kt      |  11 +-
 .../storage/entity/TraceLocationEntity.kt     |   1 -
 .../risk/CheckInWarningMatcher.kt             |   3 +-
 .../confirm/ConfirmCheckInViewModel.kt        |   5 +-
 .../checkins/CheckInRepositoryTest.kt         |  26 +-
 .../CheckInTransmissionRiskLevelTest.kt       |   6 +-
 .../checkins/CheckInsTransformerTest.kt       |  16 +-
 .../checkins/split/CheckInSplitterTest.kt     |   6 +-
 .../storage/retention/CheckInCleanerTest.kt   |   8 +-
 .../checkins/checkout/CheckOutHandlerTest.kt  |   6 +-
 .../checkout/auto/AutoCheckOutTest.kt         |   6 +-
 .../risk/CheckInWarningMatcherTest.kt         |  14 +-
 .../presencetracing/risk/FindMatchesTest.kt   |   4 +-
 .../presencetracing/risk/OverlapTest.kt       |  34 +-
 19 files changed, 328 insertions(+), 182 deletions(-)

diff --git a/Corona-Warn-App/schemas/de.rki.coronawarnapp.eventregistration.storage.TraceLocationDatabase/1.json b/Corona-Warn-App/schemas/de.rki.coronawarnapp.eventregistration.storage.TraceLocationDatabase/1.json
index 1ad43a6bf..9e78f2a34 100644
--- a/Corona-Warn-App/schemas/de.rki.coronawarnapp.eventregistration.storage.TraceLocationDatabase/1.json
+++ b/Corona-Warn-App/schemas/de.rki.coronawarnapp.eventregistration.storage.TraceLocationDatabase/1.json
@@ -2,11 +2,11 @@
   "formatVersion": 1,
   "database": {
     "version": 1,
-    "identityHash": "3017a63593d3342376a56b56743815b7",
+    "identityHash": "1dc5f8a56361d50b8bb18050bce59d20",
     "entities": [
       {
         "tableName": "checkin",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `guid` TEXT NOT NULL, `version` INTEGER NOT NULL, `type` INTEGER NOT NULL, `description` TEXT NOT NULL, `address` TEXT NOT NULL, `traceLocationStart` TEXT, `traceLocationEnd` TEXT, `defaultCheckInLengthInMinutes` INTEGER, `checkInStart` TEXT NOT NULL, `checkInEnd` TEXT NOT NULL, `completed` INTEGER NOT NULL, `createJournalEntry` INTEGER NOT NULL)",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `traceLocationIdBase64` TEXT NOT NULL, `traceLocationIdHashBase64` TEXT NOT NULL, `version` INTEGER NOT NULL, `type` INTEGER NOT NULL, `description` TEXT NOT NULL, `address` TEXT NOT NULL, `traceLocationStart` TEXT, `traceLocationEnd` TEXT, `defaultCheckInLengthInMinutes` INTEGER, `cryptographicSeedBase64` TEXT NOT NULL, `cnPublicKey` TEXT NOT NULL, `checkInStart` TEXT NOT NULL, `checkInEnd` TEXT NOT NULL, `completed` INTEGER NOT NULL, `createJournalEntry` INTEGER NOT NULL)",
         "fields": [
           {
             "fieldPath": "id",
@@ -15,8 +15,14 @@
             "notNull": true
           },
           {
-            "fieldPath": "guid",
-            "columnName": "guid",
+            "fieldPath": "traceLocationIdBase64",
+            "columnName": "traceLocationIdBase64",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "traceLocationIdHashBase64",
+            "columnName": "traceLocationIdHashBase64",
             "affinity": "TEXT",
             "notNull": true
           },
@@ -62,6 +68,18 @@
             "affinity": "INTEGER",
             "notNull": false
           },
+          {
+            "fieldPath": "cryptographicSeedBase64",
+            "columnName": "cryptographicSeedBase64",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "cnPublicKey",
+            "columnName": "cnPublicKey",
+            "affinity": "TEXT",
+            "notNull": true
+          },
           {
             "fieldPath": "checkInStart",
             "columnName": "checkInStart",
@@ -174,7 +192,7 @@
     "views": [],
     "setupQueries": [
       "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
-      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '3017a63593d3342376a56b56743815b7')"
+      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1dc5f8a56361d50b8bb18050bce59d20')"
     ]
   }
-}
+}
\ No newline at end of file
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/VerifiedTraceLocationTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/VerifiedTraceLocationTest.kt
index 81af820c4..8bbe73ab7 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/VerifiedTraceLocationTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/VerifiedTraceLocationTest.kt
@@ -1,184 +1,227 @@
 package de.rki.coronawarnapp.eventregistration.checkins.qrcode
 
-/*@RunWith(JUnit4::class)
+import de.rki.coronawarnapp.environment.EnvironmentSetup
+import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass
+import io.kotest.matchers.shouldBe
+import io.mockk.MockKAnnotations
+import io.mockk.every
+import io.mockk.impl.annotations.MockK
+import okio.ByteString.Companion.decodeBase64
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import testhelpers.BaseTestInstrumentation
+
+@RunWith(JUnit4::class)
 class VerifiedTraceLocationTest : BaseTestInstrumentation() {
 
-@MockK lateinit var environmentSetup: EnvironmentSetup
+    @MockK lateinit var environmentSetup: EnvironmentSetup
 
-@Before
-fun setUp() {
-    MockKAnnotations.init(this)
-    every { environmentSetup.appConfigVerificationKey } returns PUB_KEY
-}
+    @Before
+    fun setUp() {
+        MockKAnnotations.init(this)
+        every { environmentSetup.appConfigVerificationKey } returns PUB_KEY
+    }
+
+    // TODO: Ugly but kinda works
+    @Test
+    fun verifyTraceLocationIdGenerationHash1() {
+        val base64Payload = "CAESLAgBEhFNeSBCaXJ0aGRheSBQYXJ0eRoLYXQgbXkgcGxhY2Uo04ekAT" +
+            "D3h6QBGmUIARJbMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEc7DEst" +
+            "cUIRcyk35OYDJ95/hTg3UVhsaDXKT0zK7NhHPXoyzipEnOp3GyNXDVpaPi3" +
+            "cAfQmxeuFMZAIX2+6A5XhoEMTIzNCIECAEQAg=="
+        val base64LocationID = "jNcJTCajd9Sen6Tbexl2Yb7O3J7ps47b6k4+QMT4xS0="
 
-disabled because of incompatibilities due to latest tech spec changes... needs to be re-written anyway
+        val qrCodePayload =
+            TraceLocationOuterClass.QRCodePayload.parseFrom(base64Payload.decodeBase64()!!.toByteArray())
+        val instance = VerifiedTraceLocation(qrCodePayload)
+
+        instance.traceLocationID.sha256().base64() shouldBe base64LocationID
+    }
+
+    @Test
+    fun verifyTraceLocationIdGenerationHash2() {
+        val base64Payload = "CAESIAgBEg1JY2VjcmVhbSBTaG9wGg1NYWluIFN0cmVldCAxGmUIARJ" +
+            "bMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEc7DEstcUIRcyk35OYDJ95/hTg3UVhsaDXKT" +
+            "0zK7NhHPXoyzipEnOp3GyNXDVpaPi3cAfQmxeuFMZAIX2+6A5XhoEMTIzNCIGCAEQARgK"
+        val base64LocationID = "GMuCjqNmOdYyrFhyvFNTVEeLaZh+uShgUoY0LYJo4YQ="
+
+        val qrCodePayload =
+            TraceLocationOuterClass.QRCodePayload.parseFrom(base64Payload.decodeBase64()!!.toByteArray())
+        val instance = VerifiedTraceLocation(qrCodePayload)
+
+        instance.traceLocationID.sha256().base64() shouldBe base64LocationID
+    }
+
+    /* disabled because of incompatibilities due to latest tech spec changes... needs to be re-written anyway
 
 @Test
 fun verifyEventSuccess() = runBlockingTest {
-val instant = Instant.ofEpochMilli(2687960 * 1_000L)
-shouldNotThrowAny {
-    val verifyResult = traceLocationQRCodeVerifier.verify(ENCODED_EVENT1.decodeBase32().toByteArray())
-    verifyResult.apply {
-        traceLocation.description shouldBe "My Birthday Party"
-        traceLocation.isBeforeStartTime(instant) shouldBe false
-        traceLocation.isAfterEndTime(instant) shouldBe false
+    val instant = Instant.ofEpochMilli(2687960 * 1_000L)
+    shouldNotThrowAny {
+        val verifyResult = traceLocationQRCodeVerifier.verify(ENCODED_EVENT1.decodeBase32().toByteArray())
+        verifyResult.apply {
+            traceLocation.description shouldBe "My Birthday Party"
+            traceLocation.isBeforeStartTime(instant) shouldBe false
+            traceLocation.isAfterEndTime(instant) shouldBe false
+        }
     }
 }
-}
 
 @Test
 fun verifyParcelization() = runBlockingTest {
-val verifyResult = traceLocationQRCodeVerifier.verify(ENCODED_EVENT1.decodeBase32().toByteArray())
-
-val expectedTraceLocation = TraceLocation(
-    guid = "3055331c-2306-43f3-9742-6d8fab54e848",
-    version = 1,
-    type = TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_TEMPORARY_OTHER,
-    description = "My Birthday Party",
-    address = "at my place",
-    startDate = Instant.ofEpochSecond(2687955),
-    endDate = Instant.ofEpochSecond(2687991),
-    defaultCheckInLengthInMinutes = 0,
-    byteRepresentation = verifyResult.traceLocationBytes,
-    signature = verifyResult.signature.toByteArray().toByteString(),
-)
-
-verifyResult.traceLocation shouldBe expectedTraceLocation
-
-val bundle = Bundle().apply {
-    putParcelable("test", verifyResult.traceLocation)
-}
+    val verifyResult = traceLocationQRCodeVerifier.verify(ENCODED_EVENT1.decodeBase32().toByteArray())
 
-val parcelRaw = Parcel.obtain().apply {
-    writeBundle(bundle)
-}.marshall()
+    val expectedTraceLocation = TraceLocation(
+        guid = "3055331c-2306-43f3-9742-6d8fab54e848",
+        version = 1,
+        type = TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_TEMPORARY_OTHER,
+        description = "My Birthday Party",
+        address = "at my place",
+        startDate = Instant.ofEpochSecond(2687955),
+        endDate = Instant.ofEpochSecond(2687991),
+        defaultCheckInLengthInMinutes = 0,
+        byteRepresentation = verifyResult.traceLocationBytes,
+        signature = verifyResult.signature.toByteArray().toByteString(),
+    )
 
-val restoredParcel = Parcel.obtain().apply {
-    unmarshall(parcelRaw, 0, parcelRaw.size)
-    setDataPosition(0)
-}
+    verifyResult.traceLocation shouldBe expectedTraceLocation
 
-val restoredData = restoredParcel.readBundle()!!.run {
-    classLoader = TraceLocation::class.java.classLoader
-    getParcelable<TraceLocation>("test")
-}
-restoredData shouldBe expectedTraceLocation
+    val bundle = Bundle().apply {
+        putParcelable("test", verifyResult.traceLocation)
+    }
+
+    val parcelRaw = Parcel.obtain().apply {
+        writeBundle(bundle)
+    }.marshall()
+
+    val restoredParcel = Parcel.obtain().apply {
+        unmarshall(parcelRaw, 0, parcelRaw.size)
+        setDataPosition(0)
+    }
+
+    val restoredData = restoredParcel.readBundle()!!.run {
+        classLoader = TraceLocation::class.java.classLoader
+        getParcelable<TraceLocation>("test")
+    }
+    restoredData shouldBe expectedTraceLocation
 }
 
 @Test
 fun verifyEventStartTimeWaning() = runBlockingTest {
-val instant = Instant.ofEpochMilli(2687940 * 1_000L)
-shouldNotThrowAny {
-    val verifyResult = traceLocationQRCodeVerifier.verify(ENCODED_EVENT1.decodeBase32().toByteArray())
-    verifyResult.apply {
-        traceLocation.description shouldBe "My Birthday Party"
-        traceLocation.isBeforeStartTime(instant) shouldBe true
-        traceLocation.isAfterEndTime(instant) shouldBe false
+    val instant = Instant.ofEpochMilli(2687940 * 1_000L)
+    shouldNotThrowAny {
+        val verifyResult = traceLocationQRCodeVerifier.verify(ENCODED_EVENT1.decodeBase32().toByteArray())
+        verifyResult.apply {
+            traceLocation.description shouldBe "My Birthday Party"
+            traceLocation.isBeforeStartTime(instant) shouldBe true
+            traceLocation.isAfterEndTime(instant) shouldBe false
+        }
     }
 }
-}
 
 @Test
 fun verifyEventEndTimeWarning() = runBlockingTest {
-val instant = Instant.now()
-shouldNotThrowAny {
-    val verifyResult = traceLocationQRCodeVerifier.verify(ENCODED_EVENT1.decodeBase32().toByteArray())
-    verifyResult.apply {
-        traceLocation.description shouldBe "My Birthday Party"
-        traceLocation.isBeforeStartTime(instant) shouldBe false
-        traceLocation.isAfterEndTime(instant) shouldBe true
+    val instant = Instant.now()
+    shouldNotThrowAny {
+        val verifyResult = traceLocationQRCodeVerifier.verify(ENCODED_EVENT1.decodeBase32().toByteArray())
+        verifyResult.apply {
+            traceLocation.description shouldBe "My Birthday Party"
+            traceLocation.isBeforeStartTime(instant) shouldBe false
+            traceLocation.isAfterEndTime(instant) shouldBe true
+        }
     }
 }
-}
 
 @Test
 fun verifyEventWithInvalidKey() = runBlockingTest {
-every { environmentSetup.appConfigVerificationKey } returns INVALID_PUB_KEY
-shouldThrow<InvalidQRCodeSignatureException> {
-    traceLocationQRCodeVerifier.verify(ENCODED_EVENT1.decodeBase32().toByteArray())
-}
+    every { environmentSetup.appConfigVerificationKey } returns INVALID_PUB_KEY
+    shouldThrow<InvalidQRCodeSignatureException> {
+        traceLocationQRCodeVerifier.verify(ENCODED_EVENT1.decodeBase32().toByteArray())
+    }
 }
 
 @Test
 fun eventHasMalformedData() = runBlockingTest {
-shouldThrow<InvalidQRCodeDataException> {
-    traceLocationQRCodeVerifier.verify(
-        INVALID_ENCODED_EVENT.decodeBase32().toByteArray()
-    )
-}
+    shouldThrow<InvalidQRCodeDataException> {
+        traceLocationQRCodeVerifier.verify(
+            INVALID_ENCODED_EVENT.decodeBase32().toByteArray()
+        )
+    }
 }
 
 @Test
 fun decodingTest1() = runBlockingTest {
-val signedTraceLocation = TraceLocationOuterClass.SignedTraceLocation.parseFrom(
-    ENCODED_EVENT1.decodeBase32().toByteArray()
-)
-val expectedSignature =
-    "MEQCIGVKfqPF2851IrEyDeVMazlRnIzLX16H6r1TB37PRzjbAiBGP13ADQcbQZsztKUCZMRcvnv5Mgdo0LY/v3qFMnrUkQ=="
+    val signedTraceLocation = TraceLocationOuterClass.SignedTraceLocation.parseFrom(
+        ENCODED_EVENT1.decodeBase32().toByteArray()
+    )
+    val expectedSignature =
+        "MEQCIGVKfqPF2851IrEyDeVMazlRnIzLX16H6r1TB37PRzjbAiBGP13ADQcbQZsztKUCZMRcvnv5Mgdo0LY/v3qFMnrUkQ=="
 
-val base32 = signedTraceLocation.toByteArray().toByteString().base32()
+    val base32 = signedTraceLocation.toByteArray().toByteString().base32()
 
-shouldNotThrowAny {
-    val verifyResult = traceLocationQRCodeVerifier.verify(base32.decodeBase32().toByteArray())
+    shouldNotThrowAny {
+        val verifyResult = traceLocationQRCodeVerifier.verify(base32.decodeBase32().toByteArray())
 
-    verifyResult.apply {
-        traceLocation.description shouldBe "My Birthday Party"
-        signedTraceLocation.signature.toByteArray().toByteString().base64() shouldBe expectedSignature
+        verifyResult.apply {
+            traceLocation.description shouldBe "My Birthday Party"
+            signedTraceLocation.signature.toByteArray().toByteString().base64() shouldBe expectedSignature
+        }
     }
 }
-}
 
 @Test
 fun decodingTest2() = runBlockingTest {
-val signedTraceLocation = TraceLocationOuterClass.SignedTraceLocation.parseFrom(
-    ENCODED_EVENT2.decodeBase32().toByteArray()
-)
-val expectedSignature =
-    "MEQCIDWRTM4ujn1GFPuHlgpUnQIWwwzwI8abxSrF5Er2I5HaAiAbucxg+6d3nC/Iwzo7AXehJAS20TRX1S2rl0LO8kcYxA=="
+    val signedTraceLocation = TraceLocationOuterClass.SignedTraceLocation.parseFrom(
+        ENCODED_EVENT2.decodeBase32().toByteArray()
+    )
+    val expectedSignature =
+        "MEQCIDWRTM4ujn1GFPuHlgpUnQIWwwzwI8abxSrF5Er2I5HaAiAbucxg+6d3nC/Iwzo7AXehJAS20TRX1S2rl0LO8kcYxA=="
 
-val base32 = signedTraceLocation.toByteArray().toByteString().base32()
+    val base32 = signedTraceLocation.toByteArray().toByteString().base32()
 
-shouldNotThrowAny {
-    val verifyResult = traceLocationQRCodeVerifier.verify(base32.decodeBase32().toByteArray())
+    shouldNotThrowAny {
+        val verifyResult = traceLocationQRCodeVerifier.verify(base32.decodeBase32().toByteArray())
 
-    verifyResult.apply {
-        traceLocation.description shouldBe "Icecream Shop"
-        signedTraceLocation.signature.toByteArray().toByteString().base64() shouldBe expectedSignature
+        verifyResult.apply {
+            traceLocation.description shouldBe "Icecream Shop"
+            signedTraceLocation.signature.toByteArray().toByteString().base64() shouldBe expectedSignature
+        }
     }
 }
-}
 
 @Test
 fun testVerifiedTraceLocationMapping() {
-shouldNotThrowAny {
-    val signedTraceLocation = TraceLocationOuterClass.SignedTraceLocation.parseFrom(
-        ENCODED_EVENT1.decodeBase32().toByteArray()
-    )
-
-    val traceLocation = TraceLocationOuterClass.TraceLocation.parseFrom(
-        ENCODED_EVENT1_LOCATION.decodeBase32().toByteArray()
-    )
-    val verifiedTraceLocation = VerifiedTraceLocation(
-        protoSignedTraceLocation = signedTraceLocation,
-        protoTraceLocation = traceLocation
-    ).traceLocation
-
-    verifiedTraceLocation shouldBe TraceLocation(
-        guid = "3055331c-2306-43f3-9742-6d8fab54e848",
-        version = 1,
-        type = TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_TEMPORARY_OTHER,
-        description = "My Birthday Party",
-        address = "at my place",
-        startDate = Instant.ofEpochSecond(2687955),
-        endDate = Instant.ofEpochSecond(2687991),
-        defaultCheckInLengthInMinutes = 0,
-        byteRepresentation = signedTraceLocation.location.toByteArray().toByteString(),
-        signature = signedTraceLocation.signature.toByteArray().toByteString()
-    )
-}
+    shouldNotThrowAny {
+        val signedTraceLocation = TraceLocationOuterClass.SignedTraceLocation.parseFrom(
+            ENCODED_EVENT1.decodeBase32().toByteArray()
+        )
+
+        val traceLocation = TraceLocationOuterClass.TraceLocation.parseFrom(
+            ENCODED_EVENT1_LOCATION.decodeBase32().toByteArray()
+        )
+        val verifiedTraceLocation = VerifiedTraceLocation(
+            protoSignedTraceLocation = signedTraceLocation,
+            protoTraceLocation = traceLocation
+        ).traceLocation
+
+        verifiedTraceLocation shouldBe TraceLocation(
+            guid = "3055331c-2306-43f3-9742-6d8fab54e848",
+            version = 1,
+            type = TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_TEMPORARY_OTHER,
+            description = "My Birthday Party",
+            address = "at my place",
+            startDate = Instant.ofEpochSecond(2687955),
+            endDate = Instant.ofEpochSecond(2687991),
+            defaultCheckInLengthInMinutes = 0,
+            byteRepresentation = signedTraceLocation.location.toByteArray().toByteString(),
+            signature = signedTraceLocation.signature.toByteArray().toByteString()
+        )
+    }
 }
 
-
+*/
 
     companion object {
 
@@ -223,5 +266,3 @@ shouldNotThrowAny {
             "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEc7DEstcUIRcyk35OYDJ95/hTg3UVhsaDXKT0zK7NhHPXoyzipEnOp3GyNXDVpaPi3cAfQmxeuFMZAIX2+6A5Xg=="
     }
 }
-
- */
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/storage/CheckInDatabaseData.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/storage/CheckInDatabaseData.kt
index ee256cba8..500e91485 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/storage/CheckInDatabaseData.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/storage/CheckInDatabaseData.kt
@@ -2,12 +2,14 @@ package de.rki.coronawarnapp.eventregistration.storage
 
 import de.rki.coronawarnapp.eventregistration.storage.entity.TraceLocationCheckInEntity
 import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass
+import okio.ByteString.Companion.encode
 import org.joda.time.Instant
 
 object CheckInDatabaseData {
 
     val testCheckIn = TraceLocationCheckInEntity(
-        guid = "testGuid1",
+        traceLocationIdBase64 = "traceLocationId1".encode().base64(),
+        traceLocationIdHashBase64 = "traceLocationIdHash1".encode().base64(),
         version = 1,
         type = TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_TEMPORARY_OTHER.number,
         description = "testDescription1",
@@ -15,6 +17,8 @@ object CheckInDatabaseData {
         traceLocationStart = Instant.parse("2021-01-01T12:00:00.000Z"),
         traceLocationEnd = Instant.parse("2021-01-01T15:00:00.000Z"),
         defaultCheckInLengthInMinutes = 15,
+        cryptographicSeedBase64 = "cryptographicSeed".encode().base64(),
+        cnPublicKey = "cnPublicKey",
         checkInStart = Instant.parse("2021-01-01T12:30:00.000Z"),
         checkInEnd = Instant.parse("2021-01-01T14:00:00.000Z"),
         completed = false,
@@ -22,7 +26,8 @@ object CheckInDatabaseData {
     )
 
     val testCheckInWithoutCheckOutTime = TraceLocationCheckInEntity(
-        guid = "testGuid2",
+        traceLocationIdBase64 = "traceLocationId1".encode().base64(),
+        traceLocationIdHashBase64 = "traceLocationIdHash1".encode().base64(),
         version = 1,
         type = TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_TEMPORARY_OTHER.number,
         description = "testDescription2",
@@ -30,6 +35,8 @@ object CheckInDatabaseData {
         traceLocationStart = null,
         traceLocationEnd = null,
         defaultCheckInLengthInMinutes = null,
+        cryptographicSeedBase64 = "cryptographicSeed".encode().base64(),
+        cnPublicKey = "cnPublicKey",
         checkInStart = Instant.parse("2021-01-01T12:30:00.000Z"),
         checkInEnd = Instant.parse("2021-01-01T14:00:00.000Z"),
         completed = false,
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/CheckIn.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/CheckIn.kt
index 431ec9f8b..eae4e6abe 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/CheckIn.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/CheckIn.kt
@@ -1,14 +1,15 @@
 package de.rki.coronawarnapp.eventregistration.checkins
 
-import com.google.protobuf.ByteString.copyFromUtf8
 import de.rki.coronawarnapp.eventregistration.storage.entity.TraceLocationCheckInEntity
-import de.rki.coronawarnapp.util.HashExtensions.toSHA256
+import okio.ByteString
+import okio.ByteString.Companion.encode
 import org.joda.time.Instant
 
 @Suppress("LongParameterList")
 data class CheckIn(
     val id: Long = 0L,
-    val guid: String,
+    val traceLocationId: ByteString = "TODO: calculate".encode(),
+    val traceLocationIdHash: ByteString = "TODO: calculate".encode(),
     val version: Int,
     val type: Int,
     val description: String,
@@ -16,17 +17,20 @@ data class CheckIn(
     val traceLocationStart: Instant?,
     val traceLocationEnd: Instant?,
     val defaultCheckInLengthInMinutes: Int?,
+    val cryptographicSeed: ByteString,
+    val cnPublicKey: String,
     val checkInStart: Instant,
     val checkInEnd: Instant,
     val completed: Boolean,
     val createJournalEntry: Boolean
 ) {
-    val locationGuidHash: com.google.protobuf.ByteString by lazy { copyFromUtf8(guid.toSHA256()) }
+    // val locationGuidHash: com.google.protobuf.ByteString by lazy { copyFromUtf8(guid.toSHA256()) }
 }
 
 fun CheckIn.toEntity() = TraceLocationCheckInEntity(
     id = id,
-    guid = guid,
+    traceLocationIdBase64 = traceLocationId.base64(),
+    traceLocationIdHashBase64 = traceLocationIdHash.base64(),
     version = version,
     type = type,
     description = description,
@@ -34,6 +38,8 @@ fun CheckIn.toEntity() = TraceLocationCheckInEntity(
     traceLocationStart = traceLocationStart,
     traceLocationEnd = traceLocationEnd,
     defaultCheckInLengthInMinutes = defaultCheckInLengthInMinutes,
+    cryptographicSeedBase64 = cryptographicSeed.base64(),
+    cnPublicKey = cnPublicKey,
     checkInStart = checkInStart,
     checkInEnd = checkInEnd,
     completed = completed,
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/VerifiedTraceLocation.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/VerifiedTraceLocation.kt
index 40d43c745..6eb4f3645 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/VerifiedTraceLocation.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/VerifiedTraceLocation.kt
@@ -7,6 +7,9 @@ import kotlinx.parcelize.IgnoredOnParcel
 import kotlinx.parcelize.Parceler
 import kotlinx.parcelize.Parcelize
 import kotlinx.parcelize.TypeParceler
+import okio.Buffer
+import okio.ByteString
+import okio.ByteString.Companion.encode
 import okio.ByteString.Companion.toByteString
 import org.joda.time.Instant
 import java.util.concurrent.TimeUnit
@@ -37,6 +40,17 @@ data class VerifiedTraceLocation(
         )
     }
 
+    @IgnoredOnParcel private val traceLocationHeader: ByteString by lazy {
+        "CWA-GUID".encode(Charsets.UTF_8)
+    }
+
+    @IgnoredOnParcel val traceLocationID: ByteString by lazy {
+        Buffer()
+            .write(traceLocationHeader)
+            .write(protoQrCodePayload.toByteArray())
+            .readByteString()
+    }
+
     /**
      * Converts time in seconds into [Instant]
      */
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationCheckInEntity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationCheckInEntity.kt
index 8417c4df1..2df991c63 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationCheckInEntity.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationCheckInEntity.kt
@@ -4,12 +4,14 @@ import androidx.room.ColumnInfo
 import androidx.room.Entity
 import androidx.room.PrimaryKey
 import de.rki.coronawarnapp.eventregistration.checkins.CheckIn
+import okio.ByteString.Companion.decodeBase64
 import org.joda.time.Instant
 
 @Entity(tableName = "checkin")
 data class TraceLocationCheckInEntity(
     @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") val id: Long = 0L,
-    @ColumnInfo(name = "guid") val guid: String,
+    @ColumnInfo(name = "traceLocationIdBase64") val traceLocationIdBase64: String,
+    @ColumnInfo(name = "traceLocationIdHashBase64") val traceLocationIdHashBase64: String,
     @ColumnInfo(name = "version") val version: Int,
     @ColumnInfo(name = "type") val type: Int,
     @ColumnInfo(name = "description") val description: String,
@@ -17,6 +19,8 @@ data class TraceLocationCheckInEntity(
     @ColumnInfo(name = "traceLocationStart") val traceLocationStart: Instant?,
     @ColumnInfo(name = "traceLocationEnd") val traceLocationEnd: Instant?,
     @ColumnInfo(name = "defaultCheckInLengthInMinutes") val defaultCheckInLengthInMinutes: Int?,
+    @ColumnInfo(name = "cryptographicSeedBase64") val cryptographicSeedBase64: String,
+    @ColumnInfo(name = "cnPublicKey") val cnPublicKey: String,
     @ColumnInfo(name = "checkInStart") val checkInStart: Instant,
     @ColumnInfo(name = "checkInEnd") val checkInEnd: Instant,
     @ColumnInfo(name = "completed") val completed: Boolean,
@@ -25,7 +29,8 @@ data class TraceLocationCheckInEntity(
 
 fun TraceLocationCheckInEntity.toCheckIn() = CheckIn(
     id = id,
-    guid = guid,
+    traceLocationId = traceLocationIdBase64.decodeBase64()!!,
+    traceLocationIdHash = traceLocationIdHashBase64.decodeBase64()!!,
     version = version,
     type = type,
     description = description,
@@ -33,6 +38,8 @@ fun TraceLocationCheckInEntity.toCheckIn() = CheckIn(
     traceLocationStart = traceLocationStart,
     traceLocationEnd = traceLocationEnd,
     defaultCheckInLengthInMinutes = defaultCheckInLengthInMinutes,
+    cryptographicSeed = cryptographicSeedBase64.decodeBase64()!!,
+    cnPublicKey = cnPublicKey,
     checkInStart = checkInStart,
     checkInEnd = checkInEnd,
     completed = completed,
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationEntity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationEntity.kt
index d441d385c..abfdc5698 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationEntity.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationEntity.kt
@@ -9,7 +9,6 @@ import org.joda.time.Instant
 
 @Entity(tableName = "traceLocations")
 data class TraceLocationEntity(
-
     @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") val id: Long = 0L,
     @ColumnInfo(name = "version") val version: Int,
     @ColumnInfo(name = "type") val type: TraceLocationOuterClass.TraceLocationType,
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/presencetracing/risk/CheckInWarningMatcher.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/presencetracing/risk/CheckInWarningMatcher.kt
index fed793d67..66f82291f 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/presencetracing/risk/CheckInWarningMatcher.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/presencetracing/risk/CheckInWarningMatcher.kt
@@ -14,6 +14,7 @@ import kotlinx.coroutines.async
 import kotlinx.coroutines.awaitAll
 import kotlinx.coroutines.flow.firstOrNull
 import kotlinx.coroutines.withContext
+import okio.ByteString.Companion.toByteString
 import org.joda.time.Instant
 import timber.log.Timber
 import java.lang.reflect.Modifier.PRIVATE
@@ -134,7 +135,7 @@ internal fun CheckIn.calculateOverlap(
     traceWarningPackageId: String
 ): CheckInWarningOverlap? {
 
-    if (warning.locationIdHash != locationGuidHash) return null
+    if (warning.locationIdHash.toByteArray().toByteString() != traceLocationIdHash) return null
 
     val warningStartMillis = warning.startIntervalNumber.tenMinIntervalToMillis()
     val warningEndMillis = (warning.startIntervalNumber + warning.period).tenMinIntervalToMillis()
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/confirm/ConfirmCheckInViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/confirm/ConfirmCheckInViewModel.kt
index 3451c004c..bd50ffcbe 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/confirm/ConfirmCheckInViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/confirm/ConfirmCheckInViewModel.kt
@@ -89,7 +89,8 @@ class ConfirmCheckInViewModel @AssistedInject constructor(
         completed: Boolean = false,
         createJournalEntry: Boolean = true
     ): CheckIn = CheckIn(
-        guid = "", // traceLocation.id,
+        traceLocationId = verifiedTraceLocation.traceLocationID,
+        traceLocationIdHash = verifiedTraceLocation.traceLocationID.sha256(),
         version = traceLocation.version,
         type = traceLocation.type.number,
         description = traceLocation.description,
@@ -97,6 +98,8 @@ class ConfirmCheckInViewModel @AssistedInject constructor(
         traceLocationStart = traceLocation.startDate,
         traceLocationEnd = traceLocation.endDate,
         defaultCheckInLengthInMinutes = traceLocation.defaultCheckInLengthInMinutes,
+        cryptographicSeed = traceLocation.cryptographicSeed,
+        cnPublicKey = traceLocation.cnPublicKey,
         checkInStart = checkInStart,
         checkInEnd = checkInEnd,
         completed = completed,
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInRepositoryTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInRepositoryTest.kt
index 46fe74481..e869c2869 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInRepositoryTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInRepositoryTest.kt
@@ -16,6 +16,7 @@ import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.test.runBlockingTest
+import okio.ByteString.Companion.encode
 import org.joda.time.Instant
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
@@ -46,7 +47,8 @@ class CheckInRepositoryTest : BaseTest() {
         shouldThrow<IllegalArgumentException> {
             val checkIn = CheckIn(
                 id = 1L,
-                guid = "41da2115-eba2-49bd-bf17-adb3d635ddaf",
+                traceLocationId = "41da2115-eba2-49bd-bf17-adb3d635ddaf".encode(),
+                traceLocationIdHash = "41da2115-eba2-49bd-bf17-adb3d635ddaf".encode(),
                 version = 1,
                 type = 2,
                 description = "brothers birthday",
@@ -54,6 +56,8 @@ class CheckInRepositoryTest : BaseTest() {
                 traceLocationStart = Instant.EPOCH,
                 traceLocationEnd = null,
                 defaultCheckInLengthInMinutes = null,
+                cryptographicSeed = "cryptographicSeed".encode(),
+                cnPublicKey = "cnPublicKey",
                 checkInStart = Instant.EPOCH,
                 checkInEnd = Instant.EPOCH,
                 completed = false,
@@ -72,7 +76,8 @@ class CheckInRepositoryTest : BaseTest() {
             createInstance(scope = this).addCheckIn(
                 CheckIn(
                     id = 0L,
-                    guid = "41da2115-eba2-49bd-bf17-adb3d635ddaf",
+                    traceLocationId = "41da2115-eba2-49bd-bf17-adb3d635ddaf".encode(),
+                    traceLocationIdHash = "41da2115-eba2-49bd-bf17-adb3d635ddaf".encode(),
                     version = 1,
                     type = 2,
                     description = "brothers birthday",
@@ -80,6 +85,8 @@ class CheckInRepositoryTest : BaseTest() {
                     traceLocationStart = time,
                     traceLocationEnd = null,
                     defaultCheckInLengthInMinutes = null,
+                    cryptographicSeed = "cryptographicSeed".encode(),
+                    cnPublicKey = "cnPublicKey",
                     checkInStart = time,
                     checkInEnd = end,
                     completed = false,
@@ -90,7 +97,8 @@ class CheckInRepositoryTest : BaseTest() {
                 checkInDao.insert(
                     TraceLocationCheckInEntity(
                         id = 0L,
-                        guid = "41da2115-eba2-49bd-bf17-adb3d635ddaf",
+                        traceLocationIdBase64 = "41da2115-eba2-49bd-bf17-adb3d635ddaf".encode().base64(),
+                        traceLocationIdHashBase64 = "41da2115-eba2-49bd-bf17-adb3d635ddaf".encode().base64(),
                         version = 1,
                         type = 2,
                         description = "brothers birthday",
@@ -98,6 +106,8 @@ class CheckInRepositoryTest : BaseTest() {
                         traceLocationStart = time,
                         traceLocationEnd = null,
                         defaultCheckInLengthInMinutes = null,
+                        cryptographicSeedBase64 = "cryptographicSeed".encode().base64(),
+                        cnPublicKey = "cnPublicKey",
                         checkInStart = time,
                         checkInEnd = end,
                         completed = false,
@@ -132,7 +142,8 @@ class CheckInRepositoryTest : BaseTest() {
         allEntriesFlow.value = listOf(
             TraceLocationCheckInEntity(
                 id = 1L,
-                guid = "6e5530ce-1afc-4695-a4fc-572e6443eacd",
+                traceLocationIdBase64 = "41da2115-eba2-49bd-bf17-adb3d635ddaf".encode().base64(),
+                traceLocationIdHashBase64 = "41da2115-eba2-49bd-bf17-adb3d635ddaf".encode().base64(),
                 version = 1,
                 type = 2,
                 description = "sisters birthday",
@@ -140,6 +151,8 @@ class CheckInRepositoryTest : BaseTest() {
                 traceLocationStart = start,
                 traceLocationEnd = end,
                 defaultCheckInLengthInMinutes = null,
+                cryptographicSeedBase64 = "cryptographicSeed".encode().base64(),
+                cnPublicKey = "cnPublicKey",
                 checkInStart = start,
                 checkInEnd = end,
                 completed = false,
@@ -150,7 +163,8 @@ class CheckInRepositoryTest : BaseTest() {
             createInstance(scope = this).allCheckIns.first() shouldBe listOf(
                 CheckIn(
                     id = 1L,
-                    guid = "6e5530ce-1afc-4695-a4fc-572e6443eacd",
+                    traceLocationId = "41da2115-eba2-49bd-bf17-adb3d635ddaf".encode(),
+                    traceLocationIdHash = "41da2115-eba2-49bd-bf17-adb3d635ddaf".encode(),
                     version = 1,
                     type = 2,
                     description = "sisters birthday",
@@ -158,6 +172,8 @@ class CheckInRepositoryTest : BaseTest() {
                     traceLocationStart = start,
                     traceLocationEnd = end,
                     defaultCheckInLengthInMinutes = null,
+                    cryptographicSeed = "cryptographicSeed".encode(),
+                    cnPublicKey = "cnPublicKey",
                     checkInStart = start,
                     checkInEnd = end,
                     completed = false,
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInTransmissionRiskLevelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInTransmissionRiskLevelTest.kt
index 00a7739a2..bafd28dd1 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInTransmissionRiskLevelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInTransmissionRiskLevelTest.kt
@@ -2,6 +2,7 @@ package de.rki.coronawarnapp.eventregistration.checkins
 
 import de.rki.coronawarnapp.submission.task.TransmissionRiskVector
 import io.kotest.matchers.shouldBe
+import okio.ByteString.Companion.encode
 import org.joda.time.Instant
 import org.junit.jupiter.api.Test
 import testhelpers.BaseTest
@@ -10,7 +11,8 @@ class CheckInTransmissionRiskLevelTest : BaseTest() {
 
     private val checkIn = CheckIn(
         id = 1L,
-        guid = "trace_location_1",
+        traceLocationId = "41da2115-eba2-49bd-bf17-adb3d635ddaf".encode(),
+        traceLocationIdHash = "41da2115-eba2-49bd-bf17-adb3d635ddaf".encode(),
         version = 1,
         type = 2,
         description = "restaurant_1",
@@ -18,6 +20,8 @@ class CheckInTransmissionRiskLevelTest : BaseTest() {
         traceLocationStart = null,
         traceLocationEnd = null,
         defaultCheckInLengthInMinutes = null,
+        cryptographicSeed = "cryptographicSeed".encode(),
+        cnPublicKey = "cnPublicKey",
         checkInStart = Instant.parse("2021-03-04T10:20:00Z"),
         checkInEnd = Instant.parse("2021-03-04T10:30:00Z"),
         completed = false,
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInsTransformerTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInsTransformerTest.kt
index f242f86a7..14d50535d 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInsTransformerTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInsTransformerTest.kt
@@ -23,6 +23,7 @@ import io.mockk.every
 import io.mockk.impl.annotations.MockK
 import io.mockk.mockk
 import kotlinx.coroutines.test.runBlockingTest
+import okio.ByteString.Companion.encode
 import org.joda.time.Instant
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
@@ -40,7 +41,8 @@ class CheckInsTransformerTest : BaseTest() {
     // CheckIn can not be derived
     private val checkIn1 = CheckIn(
         id = 1L,
-        guid = "trace_location_1",
+        traceLocationId = "traceLocationId1".encode(),
+        traceLocationIdHash = "traceLocationIdHash1".encode(),
         version = 1,
         type = 1,
         description = "restaurant_1",
@@ -48,6 +50,8 @@ class CheckInsTransformerTest : BaseTest() {
         traceLocationStart = null,
         traceLocationEnd = null,
         defaultCheckInLengthInMinutes = null,
+        cryptographicSeed = "cryptographicSeed".encode(),
+        cnPublicKey = "cnPublicKey",
         checkInStart = Instant.parse("2021-03-04T10:21:00Z"),
         checkInEnd = Instant.parse("2021-03-04T10:29:00Z"),
         completed = false,
@@ -62,7 +66,8 @@ class CheckInsTransformerTest : BaseTest() {
      */
     private val checkIn2 = CheckIn(
         id = 2L,
-        guid = "trace_location_2",
+        traceLocationId = "traceLocationId2".encode(),
+        traceLocationIdHash = "traceLocationIdHash2".encode(),
         version = 1,
         type = 2,
         description = "restaurant_2",
@@ -70,6 +75,8 @@ class CheckInsTransformerTest : BaseTest() {
         traceLocationStart = null,
         traceLocationEnd = null,
         defaultCheckInLengthInMinutes = null,
+        cryptographicSeed = "cryptographicSeed".encode(),
+        cnPublicKey = "cnPublicKey",
         checkInStart = Instant.parse("2021-03-04T10:20:00Z"),
         checkInEnd = Instant.parse("2021-03-04T10:30:00Z"),
         completed = false,
@@ -79,7 +86,8 @@ class CheckInsTransformerTest : BaseTest() {
     // CheckIn that can be derived and can be splitted
     private val checkIn3 = CheckIn(
         id = 3L,
-        guid = "trace_location_3",
+        traceLocationId = "traceLocationId3".encode(),
+        traceLocationIdHash = "traceLocationIdHash3".encode(),
         version = 1,
         type = 3,
         description = "restaurant_3",
@@ -87,6 +95,8 @@ class CheckInsTransformerTest : BaseTest() {
         traceLocationStart = Instant.parse("2021-03-04T09:00:00Z"),
         traceLocationEnd = Instant.parse("2021-03-10T11:00:00Z"),
         defaultCheckInLengthInMinutes = 10,
+        cryptographicSeed = "cryptographicSeed".encode(),
+        cnPublicKey = "cnPublicKey",
         checkInStart = Instant.parse("2021-03-04T09:30:00Z"),
         checkInEnd = Instant.parse("2021-03-10T09:45:00Z"),
         completed = false,
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/split/CheckInSplitterTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/split/CheckInSplitterTest.kt
index 0e3e7ebc0..dc037d1ca 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/split/CheckInSplitterTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/split/CheckInSplitterTest.kt
@@ -2,6 +2,7 @@ package de.rki.coronawarnapp.eventregistration.checkins.split
 
 import de.rki.coronawarnapp.eventregistration.checkins.CheckIn
 import io.kotest.matchers.shouldBe
+import okio.ByteString.Companion.encode
 import org.joda.time.Instant
 import org.junit.jupiter.api.Test
 import testhelpers.BaseTest
@@ -14,7 +15,8 @@ class CheckInSplitterTest : BaseTest() {
 
     private val defaultCheckIn = CheckIn(
         id = 1L,
-        guid = "eventOne",
+        traceLocationId = "traceLocationId1".encode(),
+        traceLocationIdHash = "traceLocationIdHash1".encode(),
         version = 1,
         type = 1,
         description = "Restaurant",
@@ -22,6 +24,8 @@ class CheckInSplitterTest : BaseTest() {
         traceLocationStart = null,
         traceLocationEnd = null,
         defaultCheckInLengthInMinutes = null,
+        cryptographicSeed = "cryptographicSeed".encode(),
+        cnPublicKey = "cnPublicKey",
         checkInStart = Instant.now(),
         checkInEnd = Instant.now(),
         completed = false,
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/retention/CheckInCleanerTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/retention/CheckInCleanerTest.kt
index 844daabd8..0dc18d477 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/retention/CheckInCleanerTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/retention/CheckInCleanerTest.kt
@@ -12,6 +12,7 @@ import io.mockk.impl.annotations.MockK
 import io.mockk.just
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.test.runBlockingTest
+import okio.ByteString.Companion.encode
 import org.joda.time.Instant
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
@@ -69,7 +70,8 @@ internal class CheckInCleanerTest : BaseTest() {
         }
 
     private fun createCheckIn(checkOutDate: Instant) = CheckIn(
-        guid = "",
+        traceLocationId = "traceLocationId1".encode(),
+        traceLocationIdHash = "traceLocationIdHash1".encode(),
         version = 1,
         type = 1,
         description = "",
@@ -77,7 +79,9 @@ internal class CheckInCleanerTest : BaseTest() {
         traceLocationStart = null,
         traceLocationEnd = null,
         defaultCheckInLengthInMinutes = 30,
-        // checkInStart not relevant for this that's,
+        cryptographicSeed = "cryptographicSeed".encode(),
+        cnPublicKey = "cnPublicKey",
+        // checkInStart not relevant for this
         checkInStart = Instant.parse("1970-01-01T00:00:00.000Z"),
         checkInEnd = checkOutDate,
         completed = true,
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/checkins/checkout/CheckOutHandlerTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/checkins/checkout/CheckOutHandlerTest.kt
index 80d421ca9..e420e844c 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/checkins/checkout/CheckOutHandlerTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/checkins/checkout/CheckOutHandlerTest.kt
@@ -10,6 +10,7 @@ import io.mockk.coEvery
 import io.mockk.every
 import io.mockk.impl.annotations.MockK
 import kotlinx.coroutines.test.runBlockingTest
+import okio.ByteString.Companion.encode
 import org.joda.time.Instant
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
@@ -23,7 +24,8 @@ class CheckOutHandlerTest : BaseTest() {
 
     private val testCheckIn = CheckIn(
         id = 42L,
-        guid = "eventOne",
+        traceLocationId = "traceLocationId1".encode(),
+        traceLocationIdHash = "traceLocationIdHash1".encode(),
         version = 1,
         type = 1,
         description = "Restaurant",
@@ -31,6 +33,8 @@ class CheckOutHandlerTest : BaseTest() {
         traceLocationStart = null,
         traceLocationEnd = null,
         defaultCheckInLengthInMinutes = null,
+        cryptographicSeed = "cryptographicSeed".encode(),
+        cnPublicKey = "cnPublicKey",
         checkInStart = Instant.EPOCH,
         checkInEnd = Instant.EPOCH.plus(100),
         completed = false,
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/checkins/checkout/auto/AutoCheckOutTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/checkins/checkout/auto/AutoCheckOutTest.kt
index 0dfb7658a..41c1f47c9 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/checkins/checkout/auto/AutoCheckOutTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/checkins/checkout/auto/AutoCheckOutTest.kt
@@ -21,6 +21,7 @@ import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.test.TestCoroutineScope
 import kotlinx.coroutines.test.runBlockingTest
+import okio.ByteString.Companion.encode
 import org.joda.time.Instant
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
@@ -36,7 +37,8 @@ class AutoCheckOutTest : BaseTest() {
 
     private val baseCheckin = CheckIn(
         id = 0L,
-        guid = "41da2115-eba2-49bd-bf17-adb3d635ddaf",
+        traceLocationId = "traceLocationId1".encode(),
+        traceLocationIdHash = "traceLocationIdHash1".encode(),
         version = 1,
         type = 2,
         description = "brothers birthday",
@@ -44,6 +46,8 @@ class AutoCheckOutTest : BaseTest() {
         traceLocationStart = Instant.EPOCH,
         traceLocationEnd = null,
         defaultCheckInLengthInMinutes = null,
+        cryptographicSeed = "cryptographicSeed".encode(),
+        cnPublicKey = "cnPublicKey",
         checkInStart = Instant.EPOCH,
         checkInEnd = Instant.EPOCH,
         completed = false,
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/CheckInWarningMatcherTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/CheckInWarningMatcherTest.kt
index 26643e4b4..1a3dcc048 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/CheckInWarningMatcherTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/CheckInWarningMatcherTest.kt
@@ -41,13 +41,13 @@ class CheckInWarningMatcherTest : BaseTest() {
     fun `reports new matches`() {
         val checkIn1 = createCheckIn(
             id = 2L,
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T10:15+01:00",
             endDateStr = "2021-03-04T10:17+01:00"
         )
         val checkIn2 = createCheckIn(
             id = 3L,
-            traceLocationGuid = "69eb427e1a48133970486244487e31b3f1c5bde47415db9b52cc5a2ece1e0060",
+            traceLocationId = "69eb427e1a48133970486244487e31b3f1c5bde47415db9b52cc5a2ece1e0060",
             startDateStr = "2021-03-04T09:15+01:00",
             endDateStr = "2021-03-04T10:12+01:00"
         )
@@ -90,13 +90,13 @@ class CheckInWarningMatcherTest : BaseTest() {
     fun `report empty list if no matches found`() {
         val checkIn1 = createCheckIn(
             id = 2L,
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T10:15+01:00",
             endDateStr = "2021-03-04T10:17+01:00"
         )
         val checkIn2 = createCheckIn(
             id = 3L,
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T09:15+01:00",
             endDateStr = "2021-03-04T10:12+01:00"
         )
@@ -139,13 +139,13 @@ class CheckInWarningMatcherTest : BaseTest() {
     fun `report empty list if package is empty`() {
         val checkIn1 = createCheckIn(
             id = 2L,
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T10:15+01:00",
             endDateStr = "2021-03-04T10:17+01:00"
         )
         val checkIn2 = createCheckIn(
             id = 3L,
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T09:15+01:00",
             endDateStr = "2021-03-04T10:12+01:00"
         )
@@ -212,7 +212,7 @@ class CheckInWarningMatcherTest : BaseTest() {
         val checkIns = (1L..100L).map {
             createCheckIn(
                 id = it,
-                traceLocationGuid = it.toString(),
+                traceLocationId = it.toString(),
                 startDateStr = "2021-03-04T09:50+01:00",
                 endDateStr = "2021-03-04T10:05:15+01:00"
             )
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/FindMatchesTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/FindMatchesTest.kt
index 03c384f2e..cc9d5e580 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/FindMatchesTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/FindMatchesTest.kt
@@ -12,13 +12,13 @@ class FindMatchesTest {
     fun `findMatches works`() {
         val checkIn1 = createCheckIn(
             id = 2L,
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T10:15+01:00",
             endDateStr = "2021-03-04T10:17+01:00"
         )
         val checkIn2 = createCheckIn(
             id = 3L,
-            traceLocationGuid = "69eb427e1a48133970486244487e31b3f1c5bde47415db9b52cc5a2ece1e0060",
+            traceLocationId = "69eb427e1a48133970486244487e31b3f1c5bde47415db9b52cc5a2ece1e0060",
             startDateStr = "2021-03-04T09:15+01:00",
             endDateStr = "2021-03-04T10:45+01:00"
         )
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/OverlapTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/OverlapTest.kt
index 59f57bfc7..fa1af775d 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/OverlapTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/OverlapTest.kt
@@ -5,6 +5,7 @@ import de.rki.coronawarnapp.eventregistration.checkins.CheckIn
 import de.rki.coronawarnapp.server.protocols.internal.pt.TraceWarning
 import de.rki.coronawarnapp.util.HashExtensions.toSHA256
 import io.kotest.matchers.shouldBe
+import okio.ByteString.Companion.encode
 import org.joda.time.Duration
 import org.joda.time.Instant
 import org.junit.Test
@@ -17,7 +18,7 @@ class OverlapTest : BaseTest() {
     @Test
     fun `returns null if guids do not match`() {
         createCheckIn(
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T09:30+01:00",
             endDateStr = "2021-03-04T09:45+01:00"
         ).calculateOverlap(
@@ -34,7 +35,7 @@ class OverlapTest : BaseTest() {
     @Test
     fun `returns null if check-in precedes warning`() {
         createCheckIn(
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T09:30+01:00",
             endDateStr = "2021-03-04T09:45+01:00"
         ).calculateOverlap(
@@ -51,7 +52,7 @@ class OverlapTest : BaseTest() {
     @Test
     fun `returns null if check-in is preceded by warning`() {
         createCheckIn(
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T11:15+01:00",
             endDateStr = "2021-03-04T11:20+01:00"
         ).calculateOverlap(
@@ -68,7 +69,7 @@ class OverlapTest : BaseTest() {
     @Test
     fun `returns null if check-in meets warning at the start`() {
         createCheckIn(
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T09:30+01:00",
             endDateStr = "2021-03-04T10:00+01:00"
         ).calculateOverlap(
@@ -85,7 +86,7 @@ class OverlapTest : BaseTest() {
     @Test
     fun `returns null if check-in meets warning at the end`() {
         createCheckIn(
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T11:00+01:00",
             endDateStr = "2021-03-04T11:10+01:00"
         ).calculateOverlap(
@@ -102,7 +103,7 @@ class OverlapTest : BaseTest() {
     @Test
     fun `returns overlap if check-in overlaps warning at the start`() {
         createCheckIn(
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T09:30+01:00",
             endDateStr = "2021-03-04T10:12+01:00"
         ).calculateOverlap(
@@ -119,7 +120,7 @@ class OverlapTest : BaseTest() {
     @Test
     fun `returns overlap if check-in overlaps warning at the end`() {
         createCheckIn(
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T10:45+01:00",
             endDateStr = "2021-03-04T11:12+01:00"
         ).calculateOverlap(
@@ -136,7 +137,7 @@ class OverlapTest : BaseTest() {
     @Test
     fun `returns overlap if check-in starts warning`() {
         createCheckIn(
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T10:00+01:00",
             endDateStr = "2021-03-04T10:13+01:00"
         ).calculateOverlap(
@@ -153,7 +154,7 @@ class OverlapTest : BaseTest() {
     @Test
     fun `returns overlap if check-in during warning`() {
         createCheckIn(
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T10:15+01:00",
             endDateStr = "2021-03-04T10:17+01:00"
         ).calculateOverlap(
@@ -170,7 +171,7 @@ class OverlapTest : BaseTest() {
     @Test
     fun `returns overlap if check-in finishes warning`() {
         createCheckIn(
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T10:30+01:00",
             endDateStr = "2021-03-04T11:00+01:00"
         ).calculateOverlap(
@@ -187,7 +188,7 @@ class OverlapTest : BaseTest() {
     @Test
     fun `returns overlap if check-in equals warning`() {
         createCheckIn(
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T10:00+01:00",
             endDateStr = "2021-03-04T11:00+01:00"
         ).calculateOverlap(
@@ -204,7 +205,7 @@ class OverlapTest : BaseTest() {
     @Test
     fun `returns overlap after rounding (up)`() {
         createCheckIn(
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T09:50+01:00",
             endDateStr = "2021-03-04T10:05:45+01:00"
         ).calculateOverlap(
@@ -221,7 +222,7 @@ class OverlapTest : BaseTest() {
     @Test
     fun `returns overlap after rounding (down)`() {
         createCheckIn(
-            traceLocationGuid = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
+            traceLocationId = "fe84394e73838590cc7707aba0350c130f6d0fb6f0f2535f9735f481dee61871",
             startDateStr = "2021-03-04T09:50+01:00",
             endDateStr = "2021-03-04T10:05:15+01:00"
         ).calculateOverlap(
@@ -238,12 +239,13 @@ class OverlapTest : BaseTest() {
 
 fun createCheckIn(
     id: Long = 1L,
-    traceLocationGuid: String,
+    traceLocationId: String,
     startDateStr: String,
     endDateStr: String
 ) = CheckIn(
     id = id,
-    guid = traceLocationGuid,
+    traceLocationId = traceLocationId.toSHA256().encode(),
+    traceLocationIdHash = traceLocationId.toSHA256().encode(),
     version = 1,
     type = 2,
     description = "My birthday party",
@@ -251,6 +253,8 @@ fun createCheckIn(
     traceLocationStart = Instant.parse(startDateStr),
     traceLocationEnd = null,
     defaultCheckInLengthInMinutes = null,
+    cryptographicSeed = "cryptographicSeed".encode(),
+    cnPublicKey = "cnPublicKey",
     checkInStart = Instant.parse(startDateStr),
     checkInEnd = Instant.parse(endDateStr),
     completed = false,
-- 
GitLab