Commit 2524e4ac authored by Lukas Gehrke's avatar Lukas Gehrke
Browse files

Make Fake In work on click.

parent e207f075
......@@ -154,6 +154,11 @@ public class CheckInManager extends Manager {
.flatMapCompletable(this::processCheckIn);
}
public Completable checkInLean(@NonNull UUID scannerId, @NonNull QrCodeData qrCodeData) {
return generateCheckInData(qrCodeData, scannerId)
.flatMapCompletable(checkInRequestData -> networkManager.getLucaEndpoints().checkIn(checkInRequestData));
}
/**
* Should be called after a check-in occurred (either triggered by the user or in the backend)
*/
......
package de.culture4life.luca.fake;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Pair;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.zxing.EncodeHintType;
import com.nexenio.rxkeystore.util.ByteLoggingUtil;
import de.culture4life.luca.BuildConfig;
import de.culture4life.luca.Manager;
import de.culture4life.luca.checkin.CheckInManager;
import de.culture4life.luca.crypto.AsymmetricCipherProvider;
import de.culture4life.luca.crypto.CryptoManager;
import de.culture4life.luca.crypto.DailyKeyPairPublicKeyWrapper;
import de.culture4life.luca.crypto.SymmetricCipherProvider;
import de.culture4life.luca.network.NetworkManager;
import de.culture4life.luca.network.pojo.CheckInRequestData;
......@@ -18,11 +22,17 @@ import de.culture4life.luca.network.pojo.ContactData;
import de.culture4life.luca.network.pojo.UserRegistrationRequestData;
import de.culture4life.luca.registration.RegistrationData;
import de.culture4life.luca.registration.RegistrationManager;
import de.culture4life.luca.ui.qrcode.QrCodeData;
import de.culture4life.luca.util.SerializationUtil;
import de.culture4life.luca.util.TimeUtil;
import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import net.glxn.qrgen.android.QRCode;
import okhttp3.*;
import okhttp3.logging.HttpLoggingInterceptor;
import timber.log.Timber;
import javax.crypto.SecretKey;
import java.io.IOException;
......@@ -39,6 +49,8 @@ import static java.lang.String.valueOf;
public class FakeManager extends Manager {
protected final CompositeDisposable modelDisposable = new CompositeDisposable();
RegistrationManager registrationManager;
CryptoManager cryptoManager;
NetworkManager networkManager;
......@@ -56,7 +68,7 @@ public class FakeManager extends Manager {
}
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
= MediaType.parse("application/json");
@Override
protected Completable doInitialize(@NonNull Context context) {
......@@ -121,8 +133,8 @@ public class FakeManager extends Manager {
public void doFakeCheckin() {
// TODO: Scanner ID aus QR-Code einlesen
// Watch out to use a scanner ID of one of your local venues
UUID scannerId = UUID.fromString("1fe5f46d-2025-4d82-a10c-569f6fe0127e");
//https://localhost/webapp/1fe5f46d-2025-4d82-a10c-569f6fe0127e#e30
DeviceData deviceData = new DeviceData();
VenueData venueData = new VenueData(cryptoManager, checkInManager, scannerId, deviceData);
......@@ -130,12 +142,82 @@ public class FakeManager extends Manager {
CheckInRequestData checkInRequestData = CheckinData.map(checkinData);
String json = serializeToJson(checkInRequestData).blockingGet();
JsonObject obj = new JsonParser().parse(json).getAsJsonObject();
//networkManager.getLucaEndpointsV3().blockingGet().checkIn(checkInRequestData);
UUID userId = doFakeRegistration();
handleCheckin(scannerId, userId);
}
private void handleCheckin(UUID scannerId, UUID userId) {
modelDisposable.add(performSelfCheckIn(scannerId, userId)
.subscribe(
() -> Timber.d("Successfully checked in"),
throwable -> Timber.w("Unable to check in: %s", throwable.toString())
));
}
private Completable performSelfCheckIn(UUID scannerId, UUID userId) {
return generateQrCodeData(userId)
.flatMapCompletable(qrCodeData -> checkInManager.checkInLean(scannerId, qrCodeData));
}
// What the heck do these people write terrible code
public Single<QrCodeData> generateQrCodeData(UUID userId) {
return Single.just(new QrCodeData())
.flatMap(qrCodeData -> cryptoManager.getTraceIdWrapper(userId)
.flatMapCompletable(userTraceIdWrapper -> Completable.mergeArray(
cryptoManager.getDailyKeyPairPublicKeyWrapper()
.map(DailyKeyPairPublicKeyWrapper::getId)
.doOnSuccess(qrCodeData::setKeyId)
.ignoreElement(),
cryptoManager.getUserEphemeralKeyPair(userTraceIdWrapper.getTraceId())
.observeOn(Schedulers.computation())
.flatMapCompletable(keyPair -> Completable.mergeArray(
encryptUserIdAndSecret(userId, keyPair)
.doOnSuccess(encryptedDataAndIv -> qrCodeData.setEncryptedData(encryptedDataAndIv.first))
.flatMap(encryptedDataAndIv -> generateVerificationTag(encryptedDataAndIv.first, userTraceIdWrapper.getTimestamp())
.doOnSuccess(qrCodeData::setVerificationTag))
.ignoreElement(),
Single.just(keyPair.getPublic())
.cast(ECPublicKey.class)
.flatMap(publicKey -> AsymmetricCipherProvider.encode(publicKey, true))
.doOnSuccess(qrCodeData::setUserEphemeralPublicKey)
.ignoreElement()
)),
TimeUtil.encodeUnixTimestamp(userTraceIdWrapper.getTimestamp())
.doOnSuccess(qrCodeData::setTimestamp)
.ignoreElement(),
Completable.fromAction(() -> qrCodeData.setTraceId(userTraceIdWrapper.getTraceId()))))
.andThen(Single.just(qrCodeData)));
}
// OkHttpClient client = createOkHttpClient();
private Single<android.util.Pair<byte[], byte[]>> encryptUserIdAndSecret(@NonNull UUID userId, @NonNull KeyPair userEphemeralKeyPair) {
return Single.just(userEphemeralKeyPair.getPublic())
.cast(ECPublicKey.class)
.flatMap(publicKey -> AsymmetricCipherProvider.encode(publicKey, true))
.flatMap(encodedPublicKey -> CryptoManager.trim(encodedPublicKey, 16))
.flatMap(iv -> encryptUserIdAndSecret(userId, userEphemeralKeyPair.getPrivate(), iv)
.map(bytes -> new android.util.Pair<>(bytes, iv)));
}
postCheckIn(json);
private Single<byte[]> encryptUserIdAndSecret(@NonNull UUID userId, @NonNull PrivateKey userEphemeralPrivateKey, @NonNull byte[] iv) {
return cryptoManager.getDataSecret()
.flatMap(userDataSecret -> CryptoManager.encode(userId)
.flatMap(encodedUserId -> CryptoManager.concatenate(encodedUserId, userDataSecret)))
.flatMap(encodedData -> cryptoManager.generateEphemeralDiffieHellmanSecret(userEphemeralPrivateKey)
.flatMap(cryptoManager::generateDataEncryptionSecret)
.flatMap(CryptoManager::createKeyFromSecret)
.flatMap(encodingKey -> cryptoManager.getSymmetricCipherProvider().encrypt(encodedData, iv, encodingKey)));
}
private Single<byte[]> generateVerificationTag(@NonNull byte[] encryptedUserIdAndSecret, long roundedUnixTimestamp) {
return TimeUtil.encodeUnixTimestamp(roundedUnixTimestamp)
.flatMap(encodedTimestamp -> CryptoManager.concatenate(encodedTimestamp, encryptedUserIdAndSecret))
.flatMap(encodedData -> cryptoManager.getDataSecret()
.flatMap(cryptoManager::generateDataAuthenticationSecret)
.flatMap(CryptoManager::createKeyFromSecret)
.flatMap(dataAuthenticationKey -> cryptoManager.getMacProvider().sign(encodedData, dataAuthenticationKey)))
.flatMap(verificationTag -> CryptoManager.trim(verificationTag, 8))
.doOnSuccess(verificationTag -> Timber.d("Generated new verification tag: %s", SerializationUtil.serializeToBase64(verificationTag).blockingGet()));
}
public static byte[] generateRandomData(Integer length) {
......@@ -161,18 +243,21 @@ public class FakeManager extends Manager {
return registrationData;
}
private void postCheckIn(String json) {
// Not working, may delete later
private void postCheckIn(String json) throws IOException {
OkHttpClient client = new OkHttpClient();
try {
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(json, JSON);
RequestBody body = RequestBody.create(json, JSON);
Request request = new Request.Builder()
.url("https://10.0.2.2/api/v3/traces/checkin")
.post(body)
.build();
Request request = new Request.Builder()
.url("https://10.0.2.2/api/v3/traces/checkin")
.post(body)
.build();
try {
System.out.println("Request Body:");
System.out.println(request.body().toString());
Call call = client.newCall(request);
Response response = call.execute();
} catch (IOException e) {
......
......@@ -10,6 +10,8 @@ import android.widget.TextView;
import de.culture4life.luca.R;
import de.culture4life.luca.fake.FakeManager;
import java.io.IOException;
public class FakeCheckinActivity extends BaseActivity {
private final CustomOnSeekBarChangeListener seekBarListener = new CustomOnSeekBarChangeListener();
......@@ -57,7 +59,6 @@ public class FakeCheckinActivity extends BaseActivity {
System.out.println("FakeManager: Do fake registration");
System.out.println("FakeManager: Do fake checkin");
// fakeManager.doFakeRegistration();
fakeManager.doFakeCheckin();
}
}
......
......@@ -210,7 +210,7 @@ public class QrCodeViewModel extends BaseViewModel implements ImageAnalysis.Anal
.doFinally(() -> updateAsSideEffect(isLoading, false)));
}
private Single<QrCodeData> generateQrCodeData() {
public Single<QrCodeData> generateQrCodeData() {
return Single.just(new QrCodeData())
.flatMap(qrCodeData -> cryptoManager.getTraceIdWrapper(userId)
.flatMapCompletable(userTraceIdWrapper -> Completable.mergeArray(
......@@ -549,7 +549,7 @@ public class QrCodeViewModel extends BaseViewModel implements ImageAnalysis.Anal
}
private static boolean isDeepLink(@NonNull String data) {
return URLUtil.isHttpsUrl(data) && data.contains("10.0.2.2");
return URLUtil.isHttpsUrl(data) && data.contains("localhost");
}
public LiveData<Bitmap> getQrCode() {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment