diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/DefaultQRCodeVerifierTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/DefaultQRCodeVerifierTest.kt deleted file mode 100644 index d24aeab0b212a66a988e556eb1a658ea8f751257..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/DefaultQRCodeVerifierTest.kt +++ /dev/null @@ -1,161 +0,0 @@ -//package de.rki.coronawarnapp.eventregistration.checkins.qrcode -// -//import com.google.protobuf.ByteString -//import de.rki.coronawarnapp.environment.EnvironmentSetup -//import de.rki.coronawarnapp.eventregistration.common.decodeBase32 -//import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass -//import de.rki.coronawarnapp.util.security.SignatureValidation -//import io.kotest.assertions.throwables.shouldNotThrowAny -//import io.kotest.assertions.throwables.shouldThrow -//import io.kotest.matchers.shouldBe -//import io.mockk.MockKAnnotations -//import io.mockk.every -//import io.mockk.impl.annotations.MockK -//import kotlinx.coroutines.test.runBlockingTest -//import okio.ByteString.Companion.toByteString -//import org.joda.time.Instant -//import org.junit.Before -//import org.junit.Ignore -//import org.junit.Test -//import org.junit.runner.RunWith -//import org.junit.runners.JUnit4 -//import testhelpers.BaseTestInstrumentation -// -//@RunWith(JUnit4::class) -//@Ignore("Until format is clarified") -//class DefaultQRCodeVerifierTest : BaseTestInstrumentation() { -// -// @MockK lateinit var environmentSetup: EnvironmentSetup -// private lateinit var qrCodeVerifier: QRCodeVerifier -// -// @Before -// fun setUp() { -// MockKAnnotations.init(this) -// every { environmentSetup.appConfigVerificationKey } returns PUB_KEY -// qrCodeVerifier = DefaultQRCodeVerifier(SignatureValidation(environmentSetup)) -// } -// -// @Test -// fun verifyEventSuccess() = runBlockingTest { -// val time = 2687960 * 1_000L -// val instant = Instant.ofEpochMilli(time) -// shouldNotThrowAny { -// val verifyResult = qrCodeVerifier.verify(ENCODED_EVENT.decodeBase32().toByteArray()) -// verifyResult.apply { -// singedTraceLocation.location.description shouldBe "CWA Launch Party" -// verifyResult.isBeforeStartTime(instant) shouldBe false -// verifyResult.isAfterEndTime(instant) shouldBe false -// } -// } -// } -// -// @Test -// fun verifyEventStartTimeWaning() = runBlockingTest { -// val time = 2687940 * 1_000L -// val instant = Instant.ofEpochMilli(time) -// shouldNotThrowAny { -// val verifyResult = qrCodeVerifier.verify(ENCODED_EVENT.decodeBase32().toByteArray()) -// verifyResult.apply { -// singedTraceLocation.location.description shouldBe "CWA Launch Party" -// } -// verifyResult.isBeforeStartTime(instant) shouldBe true -// verifyResult.isAfterEndTime(instant) shouldBe false -// } -// } -// -// @Test -// fun verifyEventEndTimeWarning() = runBlockingTest { -// val instant = Instant.now() -// shouldNotThrowAny { -// val verifyResult = qrCodeVerifier.verify(ENCODED_EVENT.decodeBase32().toByteArray()) -// verifyResult.apply { -// singedTraceLocation.location.description shouldBe "CWA Launch Party" -// } -// verifyResult.isBeforeStartTime(instant) shouldBe false -// verifyResult.isAfterEndTime(instant) shouldBe true -// } -// } -// -// @Test -// fun verifyEventWithInvalidKey() = runBlockingTest { -// every { environmentSetup.appConfigVerificationKey } returns INVALID_PUB_KEY -// shouldThrow<InvalidQRCodeSignatureException> { -// qrCodeVerifier.verify(ENCODED_EVENT.decodeBase32().toByteArray()) -// } -// } -// -// @Test -// fun eventHasMalformedData() = runBlockingTest { -// shouldThrow<InvalidQRCodeDataException> { -// qrCodeVerifier.verify(INVALID_ENCODED_EVENT.decodeBase32().toByteArray()) -// } -// } -// -// @Test -// fun decodingTest1() = runBlockingTest { -// val signedTraceLocation = TraceLocationOuterClass.SignedTraceLocation.newBuilder().apply { -// signature = ByteString.copyFromUtf8( -// "MEYCIQCNSNL6E/XyCaemkM6//CIBo+goZKJi/URimqcvwIKzCgIhAOfZPRAfZBRmwpq4sbxrLs3EhY3i914aO4lJ59XCFhwk" -// ) -// location = TraceLocationOuterClass.TraceLocation.parseFrom( -// "BISDGMBVGUZTGMLDFUZDGMBWFU2DGZRTFU4TONBSFU3GIODGMFRDKNDFHA2DQEABDABCEEKNPEQEE2LSORUGIYLZEBIGC4TUPEVAWYLUEBWXSIDQNRQWGZJQ2OD2IAJY66D2IAKAAA" -// .decodeBase32().toByteArray() -// ) -// }.build() -// -// val base32 = signedTraceLocation.toByteArray().toByteString().base32() -// -// shouldNotThrowAny { -// val verifyResult = qrCodeVerifier.verify(base32.decodeBase32().toByteArray()) -// -// verifyResult.apply { -// singedTraceLocation.location.description shouldBe "My Birthday Party" -// signedTraceLocation.signature shouldBe "MEYCIQCNSNL6E/XyCaemkM6//CIBo+goZKJi/URimqcvwIKzCgIhAOfZPRAfZBRmwpq4sbxrLs3EhY3i914aO4lJ59XCFhwk" -// } -// } -// } -// -// @Test -// fun decodingTest2() = runBlockingTest { -// val signedTraceLocation = TraceLocationOuterClass.SignedTraceLocation.newBuilder().apply { -// signature = ByteString.copyFromUtf8( -// "MEUCIFpHvUqYAIP0Mq86R7kNO4EgRSvGJHbOlDraauKZvkgbAiEAh93bBDYviEtym4q5Oqzd7j6Dp1MLCP7YwCKlVcU2DHc=" -// ) -// location = TraceLocationOuterClass.TraceLocation.parseFrom( -// "BISGMY3BHA2GEMZXFU3DCYZQFU2GCN3DFVRDEZRYFU4DENLDMFSGINJQGZRWMEABDAASEDKJMNSWG4TFMFWSAU3IN5YCUDKNMFUW4ICTORZGKZLUEAYTAABYABAAU" -// .decodeBase32().toByteArray() -// ) -// }.build() -// -// val base32 = signedTraceLocation.toByteArray().toByteString().base32() -// -// shouldNotThrowAny { -// val verifyResult = qrCodeVerifier.verify(base32.decodeBase32().toByteArray()) -// -// verifyResult.apply { -// singedTraceLocation.location.description shouldBe "Icecream Shop" -// signedTraceLocation.signature shouldBe "MEUCIFpHvUqYAIP0Mq86R7kNO4EgRSvGJHbOlDraauKZvkgbAiEAh93bBDYviEtym4q5Oqzd7j6Dp1MLCP7YwCKlVcU2DHc=" -// } -// } -// } -// -// companion object { -// -// private const val INVALID_PUB_KEY = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEc7DEstcUIRcyk35OYDJ95/hTg" + -// "3UVhsaDXKT0zK7NhHPXoyzipEnOp3GyNXDVpaPi3cAfQmxeuFMZAIX2+6A5Xg==" -// -// private const val PUB_KEY = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEafIKZOiRPuJWjKOUmKv7OTJWTyii" + -// "4oCQLcGn3FgYoLQaJIvAM3Pl7anFDPPY/jxfqqrLyGc0f6hWQ9JPR3QjBw==" -// -// private const val INVALID_ENCODED_EVENT = -// "BIPEY33SMVWSA2LQON2W2IDEN5WG64RAONUXIIDBNVSXILBAMNXRBCM4UQARRKM6UQASAHRKCC7CTDWGQ" + -// "4JCO7RVZSWVIMQK4UPA.GBCAEIA7TEORBTUA25QHBOCWT26BCA5PORBS2E4FFWMJ3U" + -// "U3P6SXOL7SHUBCA7UEZBDDQ2R6VRJH7WBJKVF7GZYJA6YMRN27IPEP7NKGGJSWX3XQ" -// -// private const val ENCODED_EVENT = -// "BIYAUEDBZY6EIWF7QX6JOKSRPAGEB3H7CIIEGV2BEBGGC5LOMNUCAUDBOJ2" + -// "HSGGTQ6SACIHXQ6SACKA6CJEDARQCEEAPHGEZ5JI2K2T422L5U3SMZY5DGC" + -// "PUZ2RQACAYEJ3HQYMAFFBU2SQCEEAJAUCJSQJ7WDM675MCMOD3L2UL7ECJU" + -// "7TYERH23B746RQTABO3CTI=" -// } -//} diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationVerifierTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationVerifierTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..50a7c51e6e961f3b2a6d6c2d2a24861add6df099 --- /dev/null +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationVerifierTest.kt @@ -0,0 +1,243 @@ +package de.rki.coronawarnapp.eventregistration.checkins.qrcode + +import android.os.Bundle +import android.os.Parcel +import de.rki.coronawarnapp.environment.EnvironmentSetup +import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass +import de.rki.coronawarnapp.util.base32 +import de.rki.coronawarnapp.util.decodeBase32 +import de.rki.coronawarnapp.util.security.SignatureValidation +import io.kotest.assertions.throwables.shouldNotThrowAny +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.matchers.shouldBe +import io.mockk.MockKAnnotations +import io.mockk.every +import io.mockk.impl.annotations.MockK +import kotlinx.coroutines.test.runBlockingTest +import okio.ByteString.Companion.toByteString +import org.joda.time.Instant +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 TraceLocationVerifierTest : BaseTestInstrumentation() { + + @MockK lateinit var environmentSetup: EnvironmentSetup + private lateinit var traceLocationQRCodeVerifier: TraceLocationQRCodeVerifier + + @Before + fun setUp() { + MockKAnnotations.init(this) + every { environmentSetup.appConfigVerificationKey } returns PUB_KEY + traceLocationQRCodeVerifier = TraceLocationQRCodeVerifier(SignatureValidation(environmentSetup)) + } + + @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" + verifyResult.isBeforeStartTime(instant) shouldBe false + verifyResult.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, + signature = verifyResult.signedTraceLocation.signature.toByteArray().toByteString() + ) + + verifyResult.verifiedTraceLocation shouldBe expectedTraceLocation + + val bundle = Bundle().apply { + putParcelable("test", verifyResult.verifiedTraceLocation) + } + + 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" + } + verifyResult.isBeforeStartTime(instant) shouldBe true + verifyResult.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" + } + verifyResult.isBeforeStartTime(instant) shouldBe false + verifyResult.isAfterEndTime(instant) shouldBe true + } + } + + @Test + fun verifyEventWithInvalidKey() = runBlockingTest { + 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() + ) + } + } + + @Test + fun decodingTest1() = runBlockingTest { + val signedTraceLocation = TraceLocationOuterClass.SignedTraceLocation.parseFrom( + ENCODED_EVENT1.decodeBase32().toByteArray() + ) + val expectedSignature = + "MEQCIGVKfqPF2851IrEyDeVMazlRnIzLX16H6r1TB37PRzjbAiBGP13ADQcbQZsztKUCZMRcvnv5Mgdo0LY/v3qFMnrUkQ==" + + val base32 = signedTraceLocation.toByteArray().toByteString().base32() + + shouldNotThrowAny { + val verifyResult = traceLocationQRCodeVerifier.verify(base32.decodeBase32().toByteArray()) + + 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 base32 = signedTraceLocation.toByteArray().toByteString().base32() + + shouldNotThrowAny { + val verifyResult = traceLocationQRCodeVerifier.verify(base32.decodeBase32().toByteArray()) + + 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 = TraceLocationVerifyResult( + signedTraceLocation = signedTraceLocation, + traceLocation = traceLocation + ).verifiedTraceLocation + + 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, + signature = signedTraceLocation.signature.toByteArray().toByteString() + ) + } + } + + companion object { + + // "signedLocation": { + // "location": { + // "guid": "3055331c-2306-43f3-9742-6d8fab54e848", + // "version": 1, + // "type": 2, + // "description": "My Birthday Party", + // "address": "at my place", + // "startTimestamp": 2687955, + // "endTimestamp": 2687991, + // "defaultCheckInLengthInMinutes": 0 + // }, + // "signature": "MEQCIGVKfqPF2851IrEyDeVMazlRnIzLX16H6r1TB37PRzjbAiBGP13ADQcbQZsztKUCZMRcvnv5Mgdo0LY/v3qFMnrUkQ==" + private const val ENCODED_EVENT1 = + "BJLAUJBTGA2TKMZTGFRS2MRTGA3C2NBTMYZS2OJXGQZC2NTEHBTGCYRVGRSTQNBYCAARQARCCFGXSICCNFZHI2DEMF4SAUDBOJ2HSKQLMF2CA3LZEBYGYYLDMUYNHB5EAE4PPB5EAFAAAESGGBCAEIDFJJ7KHRO3ZZ2SFMJSBXSUY2ZZKGOIZS27L2D6VPKTA57M6RZY3MBCARR7LXAA2BY3IGNTHNFFAJSMIXF6PP4TEB3I2C3D7P32QUZHVVER" + private const val ENCODED_EVENT1_LOCATION = + "BISDGMBVGUZTGMLDFUZDGMBWFU2DGZRTFU4TONBSFU3GIODGMFRDKNDFHA2DQEABDABCEEKNPEQEE2LSORUGIYLZEBIGC4TUPEVAWYLUEBWXSIDQNRQWGZJQ2OD2IAJY66D2IAKAAA" + + // "signedLocation": { + // "location": { + // "guid": "fca84b37-61c0-4a7c-b2f8-825cadd506cf", + // "version": 1, + // "type": 1, + // "description": "Icecream Shop", + // "address": "Main Street 1", + // "startTimestamp": 0, + // "endTimestamp": 0, + // "defaultCheckInLengthInMinutes": 10 + // }, + // "signature": "MEQCIDWRTM4ujn1GFPuHlgpUnQIWwwzwI8abxSrF5Er2I5HaAiAbucxg+6d3nC/Iwzo7AXehJAS20TRX1S2rl0LO8kcYxA==" + private const val ENCODED_EVENT2 = + "BJHAUJDGMNQTQNDCGM3S2NRRMMYC2NDBG5RS2YRSMY4C2OBSGVRWCZDEGUYDMY3GCAARQAJCBVEWGZLDOJSWC3JAKNUG64BKBVGWC2LOEBJXI4TFMV2CAMJQAA4AAQAKCJDDARACEA2ZCTGOF2HH2RQU7ODZMCSUTUBBNQYM6AR4NG6FFLC6ISXWEOI5UARADO44YYH3U53ZYL6IYM5DWALXUESAJNWRGRL5KLNLS5BM54SHDDCA" + + private const val INVALID_ENCODED_EVENT = + "NB2HI4DTHIXS653XO4XHK4TCMFXGI2LDORUW63TBOJ4S4Y3PNUXWIZLGNFXGKLTQNBYD65DFOJWT2VDIMUSTEMCDN53GSZBFGIYDCOI=" + + private const val PUB_KEY = + "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEafIKZOiRPuJWjKOUmKv7OTJWTyii4oCQLcGn3FgYoLQaJIvAM3Pl7anFDPPY/jxfqqrLyGc0f6hWQ9JPR3QjBw==" + private const val INVALID_PUB_KEY = + "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEc7DEstcUIRcyk35OYDJ95/hTg3UVhsaDXKT0zK7NhHPXoyzipEnOp3GyNXDVpaPi3cAfQmxeuFMZAIX2+6A5Xg==" + } +} diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/storage/TraceLocationDatabaseData.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/storage/TraceLocationDatabaseData.kt index 8386bf1db927397aa9f0de44607d24edd63f8b7d..fe4fa4ee2f741b715303bd15ad8cb97eea3489d0 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/storage/TraceLocationDatabaseData.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/eventregistration/storage/TraceLocationDatabaseData.kt @@ -16,7 +16,7 @@ object TraceLocationDatabaseData { startDate = Instant.parse("2021-01-01T12:00:00.000Z"), endDate = Instant.parse("2021-01-01T18:00:00.000Z"), defaultCheckInLengthInMinutes = null, - signature = "signature1" + signatureBase64 = "signature1" ) val testTraceLocation2 = TraceLocationEntity( @@ -28,6 +28,6 @@ object TraceLocationDatabaseData { startDate = null, endDate = null, defaultCheckInLengthInMinutes = 15, - signature = "signature2" + signatureBase64 = "signature2" ) } diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/VerifiedTraceLocationKtTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/VerifiedTraceLocationKtTest.kt deleted file mode 100644 index 7484ff51ef4b6fa7b90741eb759a65d7486cce25..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/VerifiedTraceLocationKtTest.kt +++ /dev/null @@ -1,44 +0,0 @@ -package de.rki.coronawarnapp.ui.eventregistration.attendee.checkins - -import de.rki.coronawarnapp.eventregistration.checkins.qrcode.QRCodeVerifyResult -import de.rki.coronawarnapp.eventregistration.common.decodeBase32 -import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass -import io.kotest.assertions.throwables.shouldNotThrowAny -import io.kotest.matchers.shouldBe -import org.joda.time.Instant -import org.junit.Ignore -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 -import testhelpers.BaseTestInstrumentation - -@RunWith(JUnit4::class) -@Ignore("FIXME: Provide new encoded signed trace location samples") -class VerifiedTraceLocationKtTest : BaseTestInstrumentation() { - - @Test - fun testVerifiedTraceLocationMapping() { - shouldNotThrowAny { - val signedTraceLocation = - TraceLocationOuterClass.SignedTraceLocation.parseFrom( - DECODED_TRACE_LOCATION.decodeBase32().toByteArray() - ) - val verifiedTraceLocation = - QRCodeVerifyResult(singedTraceLocation = signedTraceLocation).toVerifiedTraceLocation() - verifiedTraceLocation shouldBe VerifiedTraceLocation( - guid = "Yc48RFi/hfyXKlF4DEDs/w==", - start = Instant.parse("1970-02-01T02:39:15.000Z"), - end = Instant.parse("1970-02-01T02:39:51.000Z"), - defaultCheckInLengthInMinutes = 30, - description = "CWA Launch Party" - ) - } - } - - companion object { - private const val DECODED_TRACE_LOCATION = - "BIYAUEDBZY6EIWF7QX6JOKSRPAGEB3H7CIIEGV2BEBGGC5LOMNUCAUDBOJ2HSGGTQ6SACIHXQ6SAC" + - "KA6CJEDARQCEEAPHGEZ5JI2K2T422L5U3SMZY5DGCPUZ2RQACAYEJ3HQYMAFFBU2SQCEEAJAUCJSQJ7WDM6" + - "75MCMOD3L2UL7ECJU7TYERH23B746RQTABO3CTI=" - } -} diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/createevent/CreateEventTestViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/createevent/CreateEventTestViewModel.kt index 69ad6c5879e0293b1f5b46ff85e67f8249e5b35f..dcce1bfc50029ece59c210e8694284f1ce62bb37 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/createevent/CreateEventTestViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/createevent/CreateEventTestViewModel.kt @@ -3,14 +3,14 @@ package de.rki.coronawarnapp.test.eventregistration.ui.createevent import androidx.lifecycle.MutableLiveData import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import de.rki.coronawarnapp.eventregistration.events.DefaultTraceLocation -import de.rki.coronawarnapp.eventregistration.events.TraceLocation +import de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocation import de.rki.coronawarnapp.eventregistration.storage.repo.TraceLocationRepository import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass import de.rki.coronawarnapp.util.TimeAndDateExtensions.seconds import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.viewmodel.CWAViewModel import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory +import okio.ByteString.Companion.toByteString import org.joda.time.DateTime import org.joda.time.format.DateTimeFormat import timber.log.Timber @@ -51,7 +51,7 @@ class CreateEventTestViewModel @AssistedInject constructor( if (type == "Event") TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_TEMPORARY_OTHER else TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_PERMANENT_OTHER - val traceLocation = DefaultTraceLocation( + val traceLocation = TraceLocation( UUID.randomUUID().toString(), // will be provided by the server when the endpoint is ready traceLocationType, description, @@ -59,7 +59,7 @@ class CreateEventTestViewModel @AssistedInject constructor( startDate?.toInstant(), endDate?.toInstant(), defaultCheckInLengthInMinutes.toInt(), - "ServerSignature" + "ServerSignature".toByteArray().toByteString() ) traceLocationRepository.addTraceLocation(traceLocation) diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/showevents/ShowStoredEventsTestFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/showevents/ShowStoredEventsTestFragment.kt index 62bd7b04808a57d947b01fc3693ff8b70acdbbf4..d32bb6736cb94c7055697a5f6c9a95beb83663d5 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/showevents/ShowStoredEventsTestFragment.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/eventregistration/ui/showevents/ShowStoredEventsTestFragment.kt @@ -5,7 +5,7 @@ import android.view.View import androidx.fragment.app.Fragment import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentTestShowstoredeventsBinding -import de.rki.coronawarnapp.eventregistration.events.TraceLocation +import de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocation import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.ui.observe2 import de.rki.coronawarnapp.util.ui.viewBindingLazy diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/EventRegistrationModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/EventRegistrationModule.kt index efc4455a3af8c92072bd357ee267ff86f4bdb7c0..9ee91b904419f724f56fca741f0eba9c361f8968 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/EventRegistrationModule.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/EventRegistrationModule.kt @@ -2,14 +2,12 @@ package de.rki.coronawarnapp.eventregistration import dagger.Binds import dagger.Module +import de.rki.coronawarnapp.eventregistration.checkins.CheckInsTransformer +import de.rki.coronawarnapp.eventregistration.checkins.DefaultCheckInsTransformer import de.rki.coronawarnapp.eventregistration.checkins.download.DownloadedCheckInsRepo import de.rki.coronawarnapp.eventregistration.checkins.download.FakeDownloadedCheckInsRepo -import de.rki.coronawarnapp.eventregistration.checkins.qrcode.DefaultQRCodeVerifier -import de.rki.coronawarnapp.eventregistration.checkins.qrcode.QRCodeVerifier import de.rki.coronawarnapp.eventregistration.storage.repo.DefaultTraceLocationRepository import de.rki.coronawarnapp.eventregistration.storage.repo.TraceLocationRepository -import de.rki.coronawarnapp.eventregistration.checkins.CheckInsTransformer -import de.rki.coronawarnapp.eventregistration.checkins.DefaultCheckInsTransformer @Module abstract class EventRegistrationModule { @@ -17,9 +15,6 @@ abstract class EventRegistrationModule { @Binds abstract fun checkInsTransformer(transformer: DefaultCheckInsTransformer): CheckInsTransformer - @Binds - abstract fun qrCodeVerifier(qrCodeVerifier: DefaultQRCodeVerifier): QRCodeVerifier - @Binds abstract fun traceLocationRepository(defaultTraceLocationRepo: DefaultTraceLocationRepository): TraceLocationRepository diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformer.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformer.kt index 84bd29c8f099175186e635ed6bcbf1df3ecd92bd..55d37d7e57dd0a35fb902ce42e57a2bde7adcc0b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformer.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformer.kt @@ -22,7 +22,7 @@ class DefaultCheckInsTransformer @Inject constructor() : .build() val signedTraceLocation = TraceLocationOuterClass.SignedTraceLocation.newBuilder() - .setLocation(traceLocation) + .setLocation(traceLocation.toByteString()) .setSignature(ByteString.copyFrom(checkIn.signature.toByteArray())) .build() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/QRCodeUriParser.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/QRCodeUriParser.kt index 094761cf245ffd2e5ed92b1daaf93ddcc6e8eae2..736e5f358bbb0e829203a44289a196a02c8fb0a7 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/QRCodeUriParser.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/QRCodeUriParser.kt @@ -1,7 +1,7 @@ package de.rki.coronawarnapp.eventregistration.checkins.qrcode import dagger.Reusable -import de.rki.coronawarnapp.eventregistration.common.decodeBase32 +import de.rki.coronawarnapp.util.decodeBase32 import okio.ByteString import timber.log.Timber import java.net.URI diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/QRCodeVerifier.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/QRCodeVerifier.kt deleted file mode 100644 index c4a1059e0089f06bb81bd6d27684da0cd6da4728..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/QRCodeVerifier.kt +++ /dev/null @@ -1,6 +0,0 @@ -package de.rki.coronawarnapp.eventregistration.checkins.qrcode - -interface QRCodeVerifier { - - suspend fun verify(rawTraceLocation: ByteArray): QRCodeVerifyResult -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/QRCodeVerifyResult.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/QRCodeVerifyResult.kt deleted file mode 100644 index 24b3a2430321fbcf9788b8cc5eea8556d2cfcc59..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/QRCodeVerifyResult.kt +++ /dev/null @@ -1,19 +0,0 @@ -package de.rki.coronawarnapp.eventregistration.checkins.qrcode - -import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass -import de.rki.coronawarnapp.util.TimeAndDateExtensions.seconds -import org.joda.time.Instant - -data class QRCodeVerifyResult( - val singedTraceLocation: TraceLocationOuterClass.SignedTraceLocation -) { - fun isBeforeStartTime(now: Instant): Boolean { - val startTimestamp = singedTraceLocation.location.startTimestamp - return startTimestamp != 0L && startTimestamp > now.seconds - } - - fun isAfterEndTime(now: Instant): Boolean { - val endTimestamp = singedTraceLocation.location.endTimestamp - return endTimestamp != 0L && endTimestamp < now.seconds - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocation.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocation.kt new file mode 100644 index 0000000000000000000000000000000000000000..2d2f867afe7895125d8b2393d588050d8887c669 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocation.kt @@ -0,0 +1,38 @@ +package de.rki.coronawarnapp.eventregistration.checkins.qrcode + +import android.os.Parcelable +import de.rki.coronawarnapp.eventregistration.storage.entity.TraceLocationEntity +import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass +import kotlinx.parcelize.Parcelize +import okio.ByteString +import okio.ByteString.Companion.decodeBase64 +import org.joda.time.Instant + +const val TRACE_LOCATION_VERSION = 1 + +@Parcelize +data class TraceLocation( + val guid: String, + val type: TraceLocationOuterClass.TraceLocationType, + val description: String, + val address: String, + val startDate: Instant?, + val endDate: Instant?, + val defaultCheckInLengthInMinutes: Int?, + val signature: ByteString, + val version: Int = TRACE_LOCATION_VERSION, +) : Parcelable + +fun List<TraceLocationEntity>.toTraceLocations() = this.map { it.toTraceLocation() } + +fun TraceLocationEntity.toTraceLocation() = TraceLocation( + guid = guid, + type = type, + description = description, + address = address, + startDate = startDate, + endDate = endDate, + defaultCheckInLengthInMinutes = defaultCheckInLengthInMinutes, + signature = signatureBase64.decodeBase64()!!, + version = version +) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/DefaultQRCodeVerifier.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationQRCodeVerifier.kt similarity index 62% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/DefaultQRCodeVerifier.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationQRCodeVerifier.kt index 3a18b4fdb774d9311a629df5b0337736842d4a3b..e31d906a77987f4c16430862ec1220142da17b1b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/DefaultQRCodeVerifier.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationQRCodeVerifier.kt @@ -2,28 +2,27 @@ package de.rki.coronawarnapp.eventregistration.checkins.qrcode import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass import de.rki.coronawarnapp.util.security.SignatureValidation -import okio.ByteString.Companion.decodeBase64 import timber.log.Timber import javax.inject.Inject -class DefaultQRCodeVerifier @Inject constructor( +class TraceLocationQRCodeVerifier @Inject constructor( private val signatureValidation: SignatureValidation -) : QRCodeVerifier { +) { - override suspend fun verify(rawTraceLocation: ByteArray): QRCodeVerifyResult { - Timber.tag(TAG).v("Verifying: %s", rawTraceLocation) + fun verify(rawTraceLocation: ByteArray): TraceLocationVerifyResult { + Timber.v("Verifying: %s", rawTraceLocation) val signedTraceLocation = try { TraceLocationOuterClass.SignedTraceLocation.parseFrom(rawTraceLocation) } catch (e: Exception) { throw InvalidQRCodeDataException(cause = e, message = "QR-code data could not be parsed.") } - Timber.tag(TAG).d("Parsed to signed location: %s", signedTraceLocation) + Timber.d("Parsed to signed location: %s", signedTraceLocation) val isValid = try { signatureValidation.hasValidSignature( signedTraceLocation.location.toByteArray(), - sequenceOf(signedTraceLocation.signature.toStringUtf8().decodeBase64()!!.toByteArray()) + sequenceOf(signedTraceLocation.signature.toByteArray()) ) } catch (e: Exception) { throw InvalidQRCodeDataException(cause = e, message = "Verification failed.") @@ -33,10 +32,13 @@ class DefaultQRCodeVerifier @Inject constructor( throw InvalidQRCodeSignatureException(message = "QR-code did not match signature.") } - return QRCodeVerifyResult(signedTraceLocation) - } + val traceLocation = TraceLocationOuterClass.TraceLocation.parseFrom( + signedTraceLocation.location + ) - companion object { - private const val TAG = "DefaultQRCodeVerifier" + return TraceLocationVerifyResult( + signedTraceLocation = signedTraceLocation, + traceLocation = traceLocation + ) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationVerifyResult.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationVerifyResult.kt new file mode 100644 index 0000000000000000000000000000000000000000..164ec045ad3946a783ab26b2752e87ca8a6f87c0 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/TraceLocationVerifyResult.kt @@ -0,0 +1,40 @@ +package de.rki.coronawarnapp.eventregistration.checkins.qrcode + +import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass +import de.rki.coronawarnapp.util.TimeAndDateExtensions.seconds +import okio.ByteString.Companion.toByteString +import org.joda.time.Instant +import java.util.concurrent.TimeUnit + +data class TraceLocationVerifyResult( + val signedTraceLocation: TraceLocationOuterClass.SignedTraceLocation, + val traceLocation: TraceLocationOuterClass.TraceLocation +) { + fun isBeforeStartTime(now: Instant): Boolean { + val startTimestamp = traceLocation.startTimestamp + return startTimestamp != 0L && startTimestamp > now.seconds + } + + fun isAfterEndTime(now: Instant): Boolean { + val endTimestamp = traceLocation.endTimestamp + return endTimestamp != 0L && endTimestamp < now.seconds + } + + val verifiedTraceLocation: TraceLocation = TraceLocation( + guid = traceLocation.guid, + version = traceLocation.version, + type = traceLocation.type, + description = traceLocation.description, + address = traceLocation.address, + startDate = traceLocation.startTimestamp.toInstant(), + endDate = traceLocation.endTimestamp.toInstant(), + defaultCheckInLengthInMinutes = traceLocation.defaultCheckInLengthInMinutes, + signature = signedTraceLocation.signature.toByteArray().toByteString() + ) + + /** + * Converts time in seconds into [Instant] + */ + private fun Long.toInstant() = + if (this == 0L) null else Instant.ofEpochMilli(TimeUnit.SECONDS.toMillis(this)) +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/events/DefaultTraceLocation.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/events/DefaultTraceLocation.kt deleted file mode 100644 index 53ef445b2c13687ce84671945100b8ce9320aad5..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/events/DefaultTraceLocation.kt +++ /dev/null @@ -1,46 +0,0 @@ -package de.rki.coronawarnapp.eventregistration.events - -import de.rki.coronawarnapp.eventregistration.storage.entity.TraceLocationEntity -import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass -import org.joda.time.Instant - -const val TRACE_LOCATION_VERSION = 1 - -data class DefaultTraceLocation( - override val guid: String, - override val type: TraceLocationOuterClass.TraceLocationType, - override val description: String, - override val address: String, - override val startDate: Instant?, - override val endDate: Instant?, - override val defaultCheckInLengthInMinutes: Int?, - override val signature: String, - override val version: Int = TRACE_LOCATION_VERSION, -) : TraceLocation - -fun List<TraceLocationEntity>.toTraceLocations() = this.map { it.toTraceLocation() } - -fun TraceLocationEntity.toTraceLocation() = DefaultTraceLocation( - guid = guid, - type = type, - description = description, - address = address, - startDate = startDate, - endDate = endDate, - defaultCheckInLengthInMinutes = defaultCheckInLengthInMinutes, - signature = signature, - version = version -) - -/*fun SignedEventOuterClass.SignedEvent.toHostedEvent(): TraceLocation = - DefaultTraceLocation( - guid = event.guid.toString(), - type = enumValues<TraceLocation.Type>()[type], - description = event.description, - address = "hardcodedLocation", // event.location, - // backend needs UNIX timestamp in seconds, so we have to multiply it by 1000 to get milliseconds - startDate = Instant.ofEpochMilli(event.start.toLong() * 1000), - endDate = Instant.ofEpochMilli(event.end.toLong() * 1000), - defaultCheckInLengthInMinutes = event.defaultCheckInLengthInMinutes, - signature = signature.toString() - )*/ diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/events/TraceLocation.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/events/TraceLocation.kt deleted file mode 100644 index 3eac8e92ce12020549651f9c1c39de050e020d17..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/events/TraceLocation.kt +++ /dev/null @@ -1,16 +0,0 @@ -package de.rki.coronawarnapp.eventregistration.events - -import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass -import org.joda.time.Instant - -interface TraceLocation { - val guid: String - val version: Int - val type: TraceLocationOuterClass.TraceLocationType - val description: String - val address: String - val startDate: Instant? - val endDate: Instant? - val defaultCheckInLengthInMinutes: Int? - val signature: String -} 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 052257f6bc75ebab5cccdb82ed8bd4d1f01b6de5..b6b1e032b0b8d796ee501eca1100f0b0c26cc293 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 @@ -3,7 +3,7 @@ package de.rki.coronawarnapp.eventregistration.storage.entity import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey -import de.rki.coronawarnapp.eventregistration.events.TraceLocation +import de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocation import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass import org.joda.time.Instant @@ -18,7 +18,7 @@ data class TraceLocationEntity( @ColumnInfo(name = "startDate") val startDate: Instant?, @ColumnInfo(name = "endDate") val endDate: Instant?, @ColumnInfo(name = "defaultCheckInLengthInMinutes") val defaultCheckInLengthInMinutes: Int?, - @ColumnInfo(name = "signature") val signature: String + @ColumnInfo(name = "signature") val signatureBase64: String ) @@ -31,6 +31,6 @@ fun TraceLocation.toTraceLocationEntity(): TraceLocationEntity = startDate = startDate, endDate = endDate, defaultCheckInLengthInMinutes = defaultCheckInLengthInMinutes, - signature = signature, + signatureBase64 = signature.base64(), version = version ) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/repo/DefaultTraceLocationRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/repo/DefaultTraceLocationRepository.kt index ab931ee3c3f22c898054b1e4391b34213c6a6eae..42e9b689de70d02c062d7ca00013023336ace753 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/repo/DefaultTraceLocationRepository.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/repo/DefaultTraceLocationRepository.kt @@ -1,7 +1,7 @@ package de.rki.coronawarnapp.eventregistration.storage.repo -import de.rki.coronawarnapp.eventregistration.events.TraceLocation -import de.rki.coronawarnapp.eventregistration.events.toTraceLocations +import de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocation +import de.rki.coronawarnapp.eventregistration.checkins.qrcode.toTraceLocations import de.rki.coronawarnapp.eventregistration.storage.TraceLocationDatabase import de.rki.coronawarnapp.eventregistration.storage.dao.TraceLocationDao import de.rki.coronawarnapp.eventregistration.storage.entity.toTraceLocationEntity diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/repo/TraceLocationRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/repo/TraceLocationRepository.kt index 88576a9cfc9eca4563f129d2f2820c7ab1e9ebee..17ab6fff55381a602b6809f809f15033e05bd72a 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/repo/TraceLocationRepository.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/storage/repo/TraceLocationRepository.kt @@ -1,6 +1,6 @@ package de.rki.coronawarnapp.eventregistration.storage.repo -import de.rki.coronawarnapp.eventregistration.events.TraceLocation +import de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocation import kotlinx.coroutines.flow.Flow interface TraceLocationRepository { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsFragment.kt index ccc7664277a19ee4eefb775365b2dbeb8f25e5bc..7256ee21bdde21644572519577029d79710579dc 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsFragment.kt @@ -65,7 +65,7 @@ class CheckInsFragment : Fragment(R.layout.trace_location_attendee_checkins_frag viewModel.verifyResult.observe2(this) { doNavigate( CheckInsFragmentDirections - .actionCheckInsFragmentToConfirmCheckInFragment(it.toVerifiedTraceLocation()) + .actionCheckInsFragmentToConfirmCheckInFragment(it.verifiedTraceLocation) ) } } @@ -92,7 +92,8 @@ class CheckInsFragment : Fragment(R.layout.trace_location_attendee_checkins_frag @Suppress("MaxLineLength") private val DEBUG_CHECKINS = listOf( - "https://e.coronawarn.app/c1/BJLAUJBTGA2TKMZTGFRS2MRTGA3C2NBTMYZS2OJXGQZC2NTEHBTGCYRVGRSTQNBYCAARQARCCFGXSICCNFZHI2DEMF4SAUDBOJ2HSKQLMF2CA3LZEBYGYYLDMUYNHB5EAE4PPB5EAFAAAESIGBDAEIIARVENF6QT6XZATJ5GSDHL77BCAGR6QKDEUJRP2RDCTKTS7QECWMFAEIIA47MT2EA7MQKGNQU2XCY3Y2ZOZXCILDPC65PBUO4JJHT5LQQWDQSA" + "https://e.coronawarn.app/c1/BJLAUJBTGA2TKMZTGFRS2MRTGA3C2NBTMYZS2OJXGQZC2NTEHBTGCYRVGRSTQNBYCAARQARCCFGXSICCNFZHI2DEMF4SAUDBOJ2HSKQLMF2CA3LZEBYGYYLDMUYNHB5EAE4PPB5EAFAAAESGGBCAEIDFJJ7KHRO3ZZ2SFMJSBXSUY2ZZKGOIZS27L2D6VPKTA57M6RZY3MBCARR7LXAA2BY3IGNTHNFFAJSMIXF6PP4TEB3I2C3D7P32QUZHVVER", + "https://e.coronawarn.app/c1/BJHAUJDGMNQTQNDCGM3S2NRRMMYC2NDBG5RS2YRSMY4C2OBSGVRWCZDEGUYDMY3GCAARQAJCBVEWGZLDOJSWC3JAKNUG64BKBVGWC2LOEBJXI4TFMV2CAMJQAA4AAQAKCJDDARACEA2ZCTGOF2HH2RQU7ODZMCSUTUBBNQYM6AR4NG6FFLC6ISXWEOI5UARADO44YYH3U53ZYL6IYM5DWALXUESAJNWRGRL5KLNLS5BM54SHDDCA", ) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsViewModel.kt index c14b531ffd10b38e67c777536b7bf6681e20792a..5752b9ed97dd2479c19baf0b4be2f8d7bf66d911 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/CheckInsViewModel.kt @@ -7,8 +7,8 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import de.rki.coronawarnapp.eventregistration.checkins.qrcode.QRCodeUriParser -import de.rki.coronawarnapp.eventregistration.checkins.qrcode.QRCodeVerifier -import de.rki.coronawarnapp.eventregistration.checkins.qrcode.QRCodeVerifyResult +import de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocationQRCodeVerifier +import de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocationVerifyResult import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.reporting.report import de.rki.coronawarnapp.util.coroutine.DispatcherProvider @@ -20,12 +20,12 @@ class CheckInsViewModel @AssistedInject constructor( @Assisted private val savedState: SavedStateHandle, @Assisted private val deepLink: String?, dispatcherProvider: DispatcherProvider, - private val qrCodeVerifier: QRCodeVerifier, + private val traceLocationQRCodeVerifier: TraceLocationQRCodeVerifier, private val qrCodeUriParser: QRCodeUriParser ) : CWAViewModel(dispatcherProvider) { - private val verifyResultData = MutableLiveData<QRCodeVerifyResult>() - val verifyResult: LiveData<QRCodeVerifyResult> = verifyResultData + private val verifyResultData = MutableLiveData<TraceLocationVerifyResult>() + val verifyResult: LiveData<TraceLocationVerifyResult> = verifyResultData init { deepLink?.let { @@ -45,7 +45,7 @@ class CheckInsViewModel @AssistedInject constructor( val signedTraceLocation = qrCodeUriParser.getSignedTraceLocation(uri) ?: throw IllegalArgumentException("Invalid uri: $uri") - val verifyResult = qrCodeVerifier.verify(signedTraceLocation.toByteArray()) + val verifyResult = traceLocationQRCodeVerifier.verify(signedTraceLocation.toByteArray()) Timber.i("verifyResult: $verifyResult") verifyResultData.postValue(verifyResult) } catch (e: Exception) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/VerifiedTraceLocation.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/VerifiedTraceLocation.kt deleted file mode 100644 index e0621dc572dcebfda0a0733e1f53e4e7f6680a98..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/checkins/VerifiedTraceLocation.kt +++ /dev/null @@ -1,35 +0,0 @@ -package de.rki.coronawarnapp.ui.eventregistration.attendee.checkins - -import android.os.Parcelable -import de.rki.coronawarnapp.eventregistration.checkins.qrcode.QRCodeVerifyResult -import kotlinx.parcelize.Parcelize -import okio.ByteString.Companion.toByteString -import org.joda.time.Instant -import java.util.concurrent.TimeUnit - -@Parcelize -data class VerifiedTraceLocation( - val guid: String, - val description: String?, - val start: Instant?, - val end: Instant?, - val defaultCheckInLengthInMinutes: Int, - // TODO add required properties to confirm check-in -) : Parcelable - -fun QRCodeVerifyResult.toVerifiedTraceLocation() = - with(singedTraceLocation.location) { - VerifiedTraceLocation( - guid = guid.toByteArray().toByteString().base64(), - start = startTimestamp.toInstant(), - end = endTimestamp.toInstant(), - description = description, - defaultCheckInLengthInMinutes = defaultCheckInLengthInMinutes - ) - } - -/** - * Converts time in seconds into [Instant] - */ -private fun Long.toInstant() = - if (this == 0L) null else Instant.ofEpochMilli(TimeUnit.SECONDS.toMillis(this)) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/confirm/ConfirmCheckInFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/confirm/ConfirmCheckInFragment.kt index 804b57eb9cb2ae9b46e8412356bced243ea9f228..bdc4bdc2ef5550db7442b1099b6ae6c66ecb3da9 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/confirm/ConfirmCheckInFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/confirm/ConfirmCheckInFragment.kt @@ -30,8 +30,8 @@ class ConfirmCheckInFragment : Fragment(R.layout.fragment_confirm_check_in), Aut confirmButton.setOnClickListener { viewModel.onConfirmTraceLocation() } // TODO bind final UI eventGuid.text = "GUID: %s".format(args.traceLocation.guid) - startTime.text = "Start time: %s".format(args.traceLocation.start) - endTime.text = "End time: %s".format(args.traceLocation.end) + startTime.text = "Start time: %s".format(args.traceLocation.startDate) + endTime.text = "End time: %s".format(args.traceLocation.endDate) description.text = "Description: %s".format(args.traceLocation.description) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/common/Base32.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/Base32.kt similarity index 94% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/common/Base32.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/Base32.kt index 21af3649a21a400ec221cc3c0b8a60733457e4d0..cee561c1e4e1713f25cf95fbee9bc3607f247fa0 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/common/Base32.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/Base32.kt @@ -1,4 +1,4 @@ -package de.rki.coronawarnapp.eventregistration.common +package de.rki.coronawarnapp.util import com.google.common.io.BaseEncoding import okio.ByteString diff --git a/Corona-Warn-App/src/main/res/navigation/trace_location_attendee_nav_graph.xml b/Corona-Warn-App/src/main/res/navigation/trace_location_attendee_nav_graph.xml index 05270f678f14ca9dfb0f59ffc55e5cbce2141dcc..c9f017644157053fe8acd3680b67bf22b38c21ca 100644 --- a/Corona-Warn-App/src/main/res/navigation/trace_location_attendee_nav_graph.xml +++ b/Corona-Warn-App/src/main/res/navigation/trace_location_attendee_nav_graph.xml @@ -11,7 +11,7 @@ tools:layout="@layout/fragment_confirm_check_in"> <argument android:name="traceLocation" - app:argType="de.rki.coronawarnapp.ui.eventregistration.attendee.checkins.VerifiedTraceLocation" /> + app:argType="de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocation" /> </fragment> <fragment android:id="@+id/scanCheckInQrCodeFragment" diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/Base32Test.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/Base32Test.kt index 674f4b7654f169f9c8ab7f44a74b914c9b958768..b6c534779aa7fa598647526f9d881935f6676143 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/Base32Test.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/Base32Test.kt @@ -1,7 +1,7 @@ package de.rki.coronawarnapp.eventregistration -import de.rki.coronawarnapp.eventregistration.common.base32 -import de.rki.coronawarnapp.eventregistration.common.decodeBase32 +import de.rki.coronawarnapp.util.base32 +import de.rki.coronawarnapp.util.decodeBase32 import io.kotest.matchers.shouldBe import okio.ByteString.Companion.toByteString import org.junit.jupiter.params.ParameterizedTest diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformerTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformerTest.kt index 7a7058e969a45f49f12eb985ccc3c07398c6a055..6b981947ccb766030e408867e469d532b7dde1c1 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformerTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformerTest.kt @@ -57,7 +57,7 @@ class DefaultCheckInsTransformerTest : BaseTest() { outCheckIns[0].apply { signedLocation.apply { - location.apply { + TraceLocationOuterClass.TraceLocation.parseFrom(location).apply { guid shouldBe "3055331c-2306-43f3-9742-6d8fab54e848" version shouldBe 1 type shouldBe TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_TEMPORARY_OTHER @@ -76,7 +76,7 @@ class DefaultCheckInsTransformerTest : BaseTest() { outCheckIns[1].apply { signedLocation.apply { - location.apply { + TraceLocationOuterClass.TraceLocation.parseFrom(location).apply { guid shouldBe "fca84b37-61c0-4a7c-b2f8-825cadd506cf" version shouldBe 1 type shouldBe TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_PERMANENT_OTHER @@ -93,4 +93,4 @@ class DefaultCheckInsTransformerTest : BaseTest() { // TODO transmissionRiskLevel shouldBe } } -} \ No newline at end of file +} diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/DefaultQRCodeVerifierTest2.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/DefaultQRCodeVerifierTest2.kt index 62e20f4784d817a7796079269db356fd5a7b57c6..ca6eecac1bb333a477a89d9166d1a7904652be40 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/DefaultQRCodeVerifierTest2.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/qrcode/DefaultQRCodeVerifierTest2.kt @@ -1,33 +1,24 @@ package de.rki.coronawarnapp.eventregistration.checkins.qrcode -import com.google.protobuf.ByteString -import de.rki.coronawarnapp.eventregistration.common.decodeBase32 import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass +import de.rki.coronawarnapp.util.decodeBase32 import io.kotest.matchers.shouldBe import okio.ByteString.Companion.toByteString -import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import testhelpers.BaseTest -@Disabled("Renable after encoding clarification") class DefaultQRCodeVerifierTest2 : BaseTest() { @Test fun `protobuf decoding 1`() { val signedTraceLocation = - TraceLocationOuterClass.SignedTraceLocation.newBuilder(TraceLocationOuterClass.SignedTraceLocation.getDefaultInstance()) - .apply { - signature = ByteString.copyFromUtf8( - "MEYCIQCNSNL6E/XyCaemkM6//CIBo+goZKJi/URimqcvwIKzCgIhAOfZPRAfZBRmwpq4sbxrLs3EhY3i914aO4lJ59XCFhwk" - ) - location = TraceLocationOuterClass.TraceLocation.parseFrom( - "BISDGMBVGUZTGMLDFUZDGMBWFU2DGZRTFU4TONBSFU3GIODGMFRDKNDFHA2DQEABDABCEEKNPEQEE2LSORUGIYLZEBIGC4TUPEVAWYLUEBWXSIDQNRQWGZJQ2OD2IAJY66D2IAKAAA".decodeBase32() - .toByteArray() - ) - }.build() + TraceLocationOuterClass.SignedTraceLocation.parseFrom( + "BJLAUJBTGA2TKMZTGFRS2MRTGA3C2NBTMYZS2OJXGQZC2NTEHBTGCYRVGRSTQNBYCAARQARCCFGXSICCNFZHI2DEMF4SAUDBOJ2HSKQLMF2CA3LZEBYGYYLDMUYNHB5EAE4PPB5EAFAAAESGGBCAEIDFJJ7KHRO3ZZ2SFMJSBXSUY2ZZKGOIZS27L2D6VPKTA57M6RZY3MBCARR7LXAA2BY3IGNTHNFFAJSMIXF6PP4TEB3I2C3D7P32QUZHVVER" + .decodeBase32().toByteArray() + ) signedTraceLocation.apply { - location.apply { + TraceLocationOuterClass.TraceLocation.parseFrom(location).apply { guid shouldBe "3055331c-2306-43f3-9742-6d8fab54e848" version shouldBe 1 typeValue shouldBe 2 @@ -37,7 +28,8 @@ class DefaultQRCodeVerifierTest2 : BaseTest() { endTimestamp shouldBe 2687991 defaultCheckInLengthInMinutes shouldBe 0 } - signature.toStringUtf8() shouldBe "MEYCIQCNSNL6E/XyCaemkM6//CIBo+goZKJi/URimqcvwIKzCgIhAOfZPRAfZBRmwpq4sbxrLs3EhY3i914aO4lJ59XCFhwk" + signature.toByteArray().toByteString() + .base64() shouldBe "MEQCIGVKfqPF2851IrEyDeVMazlRnIzLX16H6r1TB37PRzjbAiBGP13ADQcbQZsztKUCZMRcvnv5Mgdo0LY/v3qFMnrUkQ==" } signedTraceLocation.location.toByteArray().toByteString() @@ -46,18 +38,13 @@ class DefaultQRCodeVerifierTest2 : BaseTest() { @Test fun `protobuf decoding 2`() { - val signedTraceLocation = TraceLocationOuterClass.SignedTraceLocation.newBuilder().apply { - signature = ByteString.copyFromUtf8( - "MEUCIFpHvUqYAIP0Mq86R7kNO4EgRSvGJHbOlDraauKZvkgbAiEAh93bBDYviEtym4q5Oqzd7j6Dp1MLCP7YwCKlVcU2DHc=" - ) - location = TraceLocationOuterClass.TraceLocation.parseFrom( - "BISGMY3BHA2GEMZXFU3DCYZQFU2GCN3DFVRDEZRYFU4DENLDMFSGINJQGZRWMEABDAASEDKJMNSWG4TFMFWSAU3IN5YCUDKNMFUW4ICTORZGKZLUEAYTAABYABAAU".decodeBase32() - .toByteArray() - ) - }.build() + val signedTraceLocation = TraceLocationOuterClass.SignedTraceLocation.parseFrom( + "BJHAUJDGMNQTQNDCGM3S2NRRMMYC2NDBG5RS2YRSMY4C2OBSGVRWCZDEGUYDMY3GCAARQAJCBVEWGZLDOJSWC3JAKNUG64BKBVGWC2LOEBJXI4TFMV2CAMJQAA4AAQAKCJDDARACEA2ZCTGOF2HH2RQU7ODZMCSUTUBBNQYM6AR4NG6FFLC6ISXWEOI5UARADO44YYH3U53ZYL6IYM5DWALXUESAJNWRGRL5KLNLS5BM54SHDDCA" + .decodeBase32().toByteArray() + ) signedTraceLocation.apply { - location.apply { + TraceLocationOuterClass.TraceLocation.parseFrom(location).apply { guid shouldBe "fca84b37-61c0-4a7c-b2f8-825cadd506cf" version shouldBe 1 typeValue shouldBe 1 @@ -67,7 +54,8 @@ class DefaultQRCodeVerifierTest2 : BaseTest() { endTimestamp shouldBe 0 defaultCheckInLengthInMinutes shouldBe 10 } - signature.toStringUtf8() shouldBe "MEUCIFpHvUqYAIP0Mq86R7kNO4EgRSvGJHbOlDraauKZvkgbAiEAh93bBDYviEtym4q5Oqzd7j6Dp1MLCP7YwCKlVcU2DHc=" + signature.toByteArray().toByteString() + .base64() shouldBe "MEQCIDWRTM4ujn1GFPuHlgpUnQIWwwzwI8abxSrF5Er2I5HaAiAbucxg+6d3nC/Iwzo7AXehJAS20TRX1S2rl0LO8kcYxA==" } signedTraceLocation.location.toByteArray().toByteString() diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/events/DefaultTraceLocationKtTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/events/DefaultTraceLocationKtTest.kt index 9afe5214bd2b2105da2dc2ff5e00a5f4212293f2..b36cfeac9f26cf82d4fc75aa1439fad097549602 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/events/DefaultTraceLocationKtTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/events/DefaultTraceLocationKtTest.kt @@ -1,9 +1,13 @@ package de.rki.coronawarnapp.eventregistration.events +import de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocation +import de.rki.coronawarnapp.eventregistration.checkins.qrcode.toTraceLocation +import de.rki.coronawarnapp.eventregistration.checkins.qrcode.toTraceLocations import de.rki.coronawarnapp.eventregistration.storage.entity.TraceLocationEntity import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_PERMANENT_OTHER import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_TEMPORARY_OTHER import io.kotest.matchers.shouldBe +import okio.ByteString.Companion.toByteString import org.joda.time.Instant import org.junit.jupiter.api.Test import testhelpers.BaseTest @@ -21,8 +25,8 @@ internal class DefaultTraceLocationKtTest : BaseTest() { startDate = Instant.parse("2021-01-01T12:00:00.000Z"), endDate = Instant.parse("2021-01-01T18:00:00.000Z"), defaultCheckInLengthInMinutes = 15, - signature = "signature" - ).toTraceLocation() shouldBe DefaultTraceLocation( + signatureBase64 = "signature".toByteArray().toByteString().base64() + ).toTraceLocation() shouldBe TraceLocation( guid = "TestGuid", version = 1, type = LOCATION_TYPE_PERMANENT_OTHER, @@ -31,7 +35,7 @@ internal class DefaultTraceLocationKtTest : BaseTest() { startDate = Instant.parse("2021-01-01T12:00:00.000Z"), endDate = Instant.parse("2021-01-01T18:00:00.000Z"), defaultCheckInLengthInMinutes = 15, - signature = "signature" + signature = "signature".toByteArray().toByteString() ) } @@ -46,8 +50,8 @@ internal class DefaultTraceLocationKtTest : BaseTest() { startDate = null, endDate = null, defaultCheckInLengthInMinutes = null, - signature = "signature" - ).toTraceLocation() shouldBe DefaultTraceLocation( + signatureBase64 = "signature".toByteArray().toByteString().base64() + ).toTraceLocation() shouldBe TraceLocation( guid = "TestGuid", version = 1, type = LOCATION_TYPE_PERMANENT_OTHER, @@ -56,7 +60,7 @@ internal class DefaultTraceLocationKtTest : BaseTest() { startDate = null, endDate = null, defaultCheckInLengthInMinutes = null, - signature = "signature" + signature = "signature".toByteArray().toByteString() ) } @@ -72,7 +76,7 @@ internal class DefaultTraceLocationKtTest : BaseTest() { startDate = Instant.parse("2021-01-01T12:00:00.000Z"), endDate = Instant.parse("2021-01-01T18:00:00.000Z"), defaultCheckInLengthInMinutes = 15, - signature = "signature" + signatureBase64 = "signature".toByteArray().toByteString().base64() ), TraceLocationEntity( guid = "TestGuid2", @@ -83,10 +87,10 @@ internal class DefaultTraceLocationKtTest : BaseTest() { startDate = null, endDate = null, defaultCheckInLengthInMinutes = null, - signature = "signature" + signatureBase64 = "signature".toByteArray().toByteString().base64() ) ).toTraceLocations() shouldBe listOf( - DefaultTraceLocation( + TraceLocation( guid = "TestGuid1", version = 1, type = LOCATION_TYPE_TEMPORARY_OTHER, @@ -95,9 +99,9 @@ internal class DefaultTraceLocationKtTest : BaseTest() { startDate = Instant.parse("2021-01-01T12:00:00.000Z"), endDate = Instant.parse("2021-01-01T18:00:00.000Z"), defaultCheckInLengthInMinutes = 15, - signature = "signature" + signature = "signature".toByteArray().toByteString() ), - DefaultTraceLocation( + TraceLocation( guid = "TestGuid2", version = 1, type = LOCATION_TYPE_PERMANENT_OTHER, @@ -106,7 +110,7 @@ internal class DefaultTraceLocationKtTest : BaseTest() { startDate = null, endDate = null, defaultCheckInLengthInMinutes = null, - signature = "signature" + signature = "signature".toByteArray().toByteString() ) ) } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationEntityTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationEntityTest.kt index 6ab4817ec29e9e95ca0cc85cd0c59186f2265448..5a0b6ad5231c54a386b6d751d448162e8bbf55cb 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationEntityTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/storage/entity/TraceLocationEntityTest.kt @@ -1,9 +1,10 @@ package de.rki.coronawarnapp.eventregistration.storage.entity -import de.rki.coronawarnapp.eventregistration.events.DefaultTraceLocation +import de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocation import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_PERMANENT_OTHER import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_TEMPORARY_OTHER import io.kotest.matchers.shouldBe +import okio.ByteString.Companion.toByteString import org.joda.time.Instant import org.junit.jupiter.api.Test import testhelpers.BaseTest @@ -12,7 +13,7 @@ internal class TraceLocationEntityTest : BaseTest() { @Test fun `toTraceLocationEntity() should map to TraceLocationEntity correctly with all arguments`() { - DefaultTraceLocation( + TraceLocation( guid = "TestGuid", version = 1, type = LOCATION_TYPE_TEMPORARY_OTHER, @@ -21,7 +22,7 @@ internal class TraceLocationEntityTest : BaseTest() { startDate = Instant.parse("2021-01-01T12:00:00.000Z"), endDate = Instant.parse("2021-01-01T18:00:00.000Z"), defaultCheckInLengthInMinutes = 15, - signature = "signature" + signature = "signature".toByteArray().toByteString() ).toTraceLocationEntity() shouldBe TraceLocationEntity( guid = "TestGuid", version = 1, @@ -31,13 +32,13 @@ internal class TraceLocationEntityTest : BaseTest() { startDate = Instant.parse("2021-01-01T12:00:00.000Z"), endDate = Instant.parse("2021-01-01T18:00:00.000Z"), defaultCheckInLengthInMinutes = 15, - signature = "signature" + signatureBase64 = "signature".toByteArray().toByteString().base64() ) } @Test fun `toTraceLocationEntity() should map to TraceLocationEntity correctly with some arguments as null`() { - DefaultTraceLocation( + TraceLocation( guid = "TestGuid", version = 1, type = LOCATION_TYPE_PERMANENT_OTHER, @@ -46,7 +47,7 @@ internal class TraceLocationEntityTest : BaseTest() { startDate = null, endDate = null, defaultCheckInLengthInMinutes = null, - signature = "signature" + signature = "signature".toByteArray().toByteString() ).toTraceLocationEntity() shouldBe TraceLocationEntity( guid = "TestGuid", version = 1, @@ -56,7 +57,7 @@ internal class TraceLocationEntityTest : BaseTest() { startDate = null, endDate = null, defaultCheckInLengthInMinutes = null, - signature = "signature" + signatureBase64 = "signature".toByteArray().toByteString().base64() ) } } diff --git a/Server-Protocol-Buffer/src/main/proto/internal/pt/trace_location.proto b/Server-Protocol-Buffer/src/main/proto/internal/pt/trace_location.proto index 3785e9a83aecd850a22b502e125a197d3d06bd1c..b0c1dd5088de6c90869661e041a6b20de425366c 100644 --- a/Server-Protocol-Buffer/src/main/proto/internal/pt/trace_location.proto +++ b/Server-Protocol-Buffer/src/main/proto/internal/pt/trace_location.proto @@ -20,7 +20,7 @@ message TraceLocation { } message SignedTraceLocation { - TraceLocation location = 1; + bytes location = 1; bytes signature = 2; }