mirror of https://github.com/MISP/misp-bump
rewrite and rename SyncActivity -> ExchangeActivity
parent
be88d0e3a5
commit
a9498f45f1
|
@ -38,7 +38,7 @@
|
|||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="lu.circl.mispbump">
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
|
@ -16,47 +15,43 @@
|
|||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
tools:ignore="GoogleAppIndexingWarning">
|
||||
|
||||
<activity android:name=".activities.ExchangeActivity"></activity>
|
||||
<activity android:name=".activities.SyncActivity2" />
|
||||
<activity android:name=".activities.StartUpActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activities.LoginActivity"
|
||||
android:label="@string/login"/>
|
||||
|
||||
android:label="@string/login" />
|
||||
<activity
|
||||
android:name=".activities.HomeActivity"
|
||||
android:label="@string/app_name"/>
|
||||
|
||||
android:label="@string/app_name" />
|
||||
<activity
|
||||
android:name=".activities.SyncActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:parentActivityName=".activities.HomeActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.Translucent"/>
|
||||
|
||||
android:theme="@style/AppTheme.Translucent" />
|
||||
<activity
|
||||
android:name=".activities.UploadInfoActivity"
|
||||
android:parentActivityName=".activities.HomeActivity"/>
|
||||
|
||||
android:parentActivityName=".activities.HomeActivity" />
|
||||
<activity
|
||||
android:name=".activities.UploadActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="Upload"
|
||||
android:parentActivityName=".activities.HomeActivity"/>
|
||||
android:parentActivityName=".activities.HomeActivity" />
|
||||
<activity
|
||||
android:name=".activities.PreferenceActivity"
|
||||
android:parentActivityName=".activities.HomeActivity"/>
|
||||
android:parentActivityName=".activities.HomeActivity" />
|
||||
<activity
|
||||
android:name=".activities.ProfileActivity"
|
||||
android:label="Profile"
|
||||
android:parentActivityName=".activities.HomeActivity"
|
||||
android:theme="@style/AppTheme.Translucent"/>
|
||||
android:theme="@style/AppTheme.Translucent" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,352 @@
|
|||
package lu.circl.mispbump.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.List;
|
||||
|
||||
import lu.circl.mispbump.R;
|
||||
import lu.circl.mispbump.auxiliary.DialogManager;
|
||||
import lu.circl.mispbump.auxiliary.PreferenceManager;
|
||||
import lu.circl.mispbump.auxiliary.QrCodeGenerator;
|
||||
import lu.circl.mispbump.auxiliary.RandomString;
|
||||
import lu.circl.mispbump.fragments.CameraFragment;
|
||||
import lu.circl.mispbump.models.SyncInformation;
|
||||
import lu.circl.mispbump.models.UploadInformation;
|
||||
import lu.circl.mispbump.security.DiffieHellman;
|
||||
|
||||
public class ExchangeActivity extends AppCompatActivity {
|
||||
|
||||
private PreferenceManager preferenceManager;
|
||||
private QrCodeGenerator qrCodeGenerator;
|
||||
private DiffieHellman diffieHellman;
|
||||
private UploadInformation uploadInformation;
|
||||
|
||||
private CameraFragment cameraFragment;
|
||||
|
||||
private CoordinatorLayout rootLayout;
|
||||
private View qrFrame;
|
||||
private TextView qrInfo;
|
||||
private ImageView qrCode;
|
||||
private ImageButton prevButton, nextButton;
|
||||
|
||||
private Bitmap publicKeyQr, dataQr;
|
||||
|
||||
private SyncState currentSyncState;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_sync);
|
||||
|
||||
preferenceManager = PreferenceManager.getInstance(ExchangeActivity.this);
|
||||
qrCodeGenerator = new QrCodeGenerator(ExchangeActivity.this);
|
||||
diffieHellman = DiffieHellman.getInstance();
|
||||
|
||||
initViews();
|
||||
initCamera();
|
||||
|
||||
uploadInformation = new UploadInformation();
|
||||
publicKeyQr = generatePublicKeyBitmap();
|
||||
dataQr = generateLocalSyncInfoBitmap();
|
||||
|
||||
setSyncState(SyncState.KEY_EXCHANGE);
|
||||
}
|
||||
|
||||
|
||||
private void initViews() {
|
||||
rootLayout = findViewById(R.id.rootLayout);
|
||||
|
||||
qrFrame = findViewById(R.id.qrFrame);
|
||||
qrCode = findViewById(R.id.qrCode);
|
||||
qrInfo = findViewById(R.id.qrInfo);
|
||||
|
||||
prevButton = findViewById(R.id.prevButton);
|
||||
prevButton.setOnClickListener(onPrevClicked());
|
||||
|
||||
nextButton = findViewById(R.id.nextButton);
|
||||
nextButton.setOnClickListener(onNextClicked());
|
||||
}
|
||||
|
||||
private void initCamera() {
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
|
||||
cameraFragment = new CameraFragment();
|
||||
cameraFragment.setOnQrAvailableListener(onQrScanned());
|
||||
|
||||
String fragmentTag = cameraFragment.getClass().getSimpleName();
|
||||
fragmentTransaction.add(R.id.fragmentContainer, cameraFragment, fragmentTag);
|
||||
fragmentTransaction.commit();
|
||||
}
|
||||
|
||||
|
||||
private Bitmap generatePublicKeyBitmap() {
|
||||
return qrCodeGenerator.generateQrCode(DiffieHellman.publicKeyToString(diffieHellman.getPublicKey()));
|
||||
}
|
||||
|
||||
private Bitmap generateLocalSyncInfoBitmap() {
|
||||
uploadInformation.setLocal(generateLocalSyncInfo());
|
||||
return qrCodeGenerator.generateQrCode(new Gson().toJson(uploadInformation.getLocal()));
|
||||
}
|
||||
|
||||
private SyncInformation generateLocalSyncInfo() {
|
||||
SyncInformation syncInformation = new SyncInformation();
|
||||
syncInformation.organisation = preferenceManager.getUserOrganisation().toSyncOrganisation();
|
||||
syncInformation.syncUserAuthkey = new RandomString(40).nextString();
|
||||
syncInformation.baseUrl = preferenceManager.getServerUrl();
|
||||
syncInformation.syncUserPassword = new RandomString(16).nextString();
|
||||
syncInformation.syncUserEmail = preferenceManager.getUserInfo().email;
|
||||
return syncInformation;
|
||||
}
|
||||
|
||||
|
||||
private void showQrCode(final Bitmap bitmap) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
qrCode.setImageBitmap(bitmap);
|
||||
qrFrame.setVisibility(View.VISIBLE); // TODO animate
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setSyncState(SyncState state) {
|
||||
|
||||
Log.d("DEBUG", "current sync state: " + state);
|
||||
|
||||
currentSyncState = state;
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
switch (currentSyncState) {
|
||||
case KEY_EXCHANGE:
|
||||
prevButton.setImageDrawable(getDrawable(R.drawable.ic_close));
|
||||
prevButton.setVisibility(View.VISIBLE);
|
||||
nextButton.setVisibility(View.GONE);
|
||||
|
||||
setCameraPreviewEnabled(true);
|
||||
setReadQrStatus(ReadQrStatus.PENDING);
|
||||
showQrCode(publicKeyQr);
|
||||
break;
|
||||
case KEY_EXCHANGE_DONE:
|
||||
prevButton.setImageDrawable(getDrawable(R.drawable.ic_close));
|
||||
prevButton.setVisibility(View.VISIBLE);
|
||||
nextButton.setImageDrawable(getDrawable(R.drawable.ic_arrow_forward));
|
||||
nextButton.setVisibility(View.VISIBLE);
|
||||
|
||||
setCameraPreviewEnabled(false);
|
||||
setReadQrStatus(ReadQrStatus.SUCCESS);
|
||||
showQrCode(publicKeyQr);
|
||||
break;
|
||||
case DATA_EXCHANGE:
|
||||
prevButton.setImageDrawable(getDrawable(R.drawable.ic_arrow_back));
|
||||
prevButton.setVisibility(View.VISIBLE);
|
||||
nextButton.setVisibility(View.GONE);
|
||||
|
||||
setCameraPreviewEnabled(true);
|
||||
setReadQrStatus(ReadQrStatus.PENDING);
|
||||
showQrCode(dataQr);
|
||||
break;
|
||||
case DATA_EXCHANGE_DONE:
|
||||
prevButton.setImageDrawable(getDrawable(R.drawable.ic_arrow_back));
|
||||
prevButton.setVisibility(View.VISIBLE);
|
||||
nextButton.setImageDrawable(getDrawable(R.drawable.ic_check));
|
||||
nextButton.setVisibility(View.VISIBLE);
|
||||
|
||||
setCameraPreviewEnabled(false);
|
||||
setReadQrStatus(ReadQrStatus.SUCCESS);
|
||||
showQrCode(dataQr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setReadQrStatus(ReadQrStatus status) {
|
||||
|
||||
Log.d("DEBUG", "QR STATUS: " + status);
|
||||
|
||||
final Drawable drawable;
|
||||
final int color;
|
||||
|
||||
switch (status) {
|
||||
case PENDING:
|
||||
drawable = getDrawable(R.drawable.ic_info_outline);
|
||||
color = getColor(R.color.status_amber);
|
||||
break;
|
||||
case SUCCESS:
|
||||
drawable = getDrawable(R.drawable.ic_check_outline);
|
||||
color = getColor(R.color.status_green);
|
||||
break;
|
||||
case FAILURE:
|
||||
drawable = getDrawable(R.drawable.ic_error_outline);
|
||||
color = getColor(R.color.status_red);
|
||||
break;
|
||||
default:
|
||||
drawable = getDrawable(R.drawable.ic_info_outline);
|
||||
color = getColor(R.color.status_green);
|
||||
break;
|
||||
}
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
qrInfo.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
|
||||
qrInfo.setCompoundDrawableTintList(ColorStateList.valueOf(color));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setCameraPreviewEnabled(boolean enabled) {
|
||||
View view = findViewById(R.id.fragmentContainer);
|
||||
|
||||
if (enabled) {
|
||||
Log.d("DEBUG", "cameraPreview enabled");
|
||||
view.animate()
|
||||
.alpha(1f)
|
||||
.setDuration(250)
|
||||
.start();
|
||||
cameraFragment.setReadQrEnabled(true);
|
||||
} else {
|
||||
Log.d("DEBUG", "cameraPreview disabled");
|
||||
view.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(250)
|
||||
.start();
|
||||
cameraFragment.setReadQrEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private CameraFragment.QrScanCallback onQrScanned() {
|
||||
return new CameraFragment.QrScanCallback() {
|
||||
@Override
|
||||
public void qrScanResult(String qrData) {
|
||||
cameraFragment.setReadQrEnabled(false);
|
||||
|
||||
switch (currentSyncState) {
|
||||
case KEY_EXCHANGE:
|
||||
try {
|
||||
diffieHellman.setForeignPublicKey(DiffieHellman.publicKeyFromString(qrData));
|
||||
setSyncState(SyncState.KEY_EXCHANGE_DONE);
|
||||
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
|
||||
setReadQrStatus(ReadQrStatus.FAILURE);
|
||||
cameraFragment.setReadQrEnabled(true);
|
||||
Snackbar.make(rootLayout, "Public key not parsable", Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
break;
|
||||
case DATA_EXCHANGE:
|
||||
try {
|
||||
final SyncInformation remoteSyncInfo = new Gson().fromJson(diffieHellman.decrypt(qrData), SyncInformation.class);
|
||||
List<UploadInformation> uploadInformationList = preferenceManager.getUploadInformationList();
|
||||
|
||||
for (final UploadInformation ui : uploadInformationList) {
|
||||
if (ui.getRemote().organisation.uuid.equals(remoteSyncInfo.organisation.uuid)) {
|
||||
DialogManager.syncAlreadyExistsDialog(ui.getRemote(), remoteSyncInfo, ExchangeActivity.this, new DialogManager.IDialogFeedback() {
|
||||
@Override
|
||||
public void positive() {
|
||||
// update remote info only
|
||||
uploadInformation.setUuid(ui.getUuid());
|
||||
uploadInformation.setDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void negative() {
|
||||
// replace credentials too
|
||||
preferenceManager.removeUploadInformation(ui.getUuid());
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uploadInformation.setRemote(remoteSyncInfo);
|
||||
preferenceManager.addUploadInformation(uploadInformation);
|
||||
setSyncState(SyncState.DATA_EXCHANGE_DONE);
|
||||
} catch (JsonSyntaxException e) {
|
||||
setReadQrStatus(ReadQrStatus.FAILURE);
|
||||
cameraFragment.setReadQrEnabled(true);
|
||||
Snackbar.make(rootLayout, "Sync information not parsable", Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View.OnClickListener onPrevClicked() {
|
||||
return new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (currentSyncState) {
|
||||
case KEY_EXCHANGE:
|
||||
case KEY_EXCHANGE_DONE:
|
||||
// TODO warning that sync will be lost
|
||||
finish();
|
||||
break;
|
||||
case DATA_EXCHANGE:
|
||||
case DATA_EXCHANGE_DONE:
|
||||
setSyncState(SyncState.KEY_EXCHANGE_DONE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View.OnClickListener onNextClicked() {
|
||||
return new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (currentSyncState) {
|
||||
case KEY_EXCHANGE_DONE:
|
||||
setSyncState(SyncState.DATA_EXCHANGE);
|
||||
break;
|
||||
case DATA_EXCHANGE_DONE:
|
||||
uploadInformation.setCurrentSyncStatus(UploadInformation.SyncStatus.PENDING);
|
||||
preferenceManager.addUploadInformation(uploadInformation);
|
||||
Intent i = new Intent(ExchangeActivity.this, UploadInfoActivity.class);
|
||||
i.putExtra(UploadInfoActivity.EXTRA_UPLOAD_INFO_UUID, uploadInformation.getUuid());
|
||||
startActivity(i);
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private enum SyncState {
|
||||
KEY_EXCHANGE,
|
||||
KEY_EXCHANGE_DONE,
|
||||
DATA_EXCHANGE,
|
||||
DATA_EXCHANGE_DONE
|
||||
}
|
||||
|
||||
private enum ReadQrStatus {
|
||||
PENDING,
|
||||
SUCCESS,
|
||||
FAILURE
|
||||
}
|
||||
}
|
|
@ -87,7 +87,7 @@ public class HomeActivity extends AppCompatActivity {
|
|||
syncFab.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
startActivity(new Intent(HomeActivity.this, SyncActivity.class));
|
||||
startActivity(new Intent(HomeActivity.this, ExchangeActivity.class));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -113,6 +113,7 @@ public class HomeActivity extends AppCompatActivity {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private OnRecyclerItemClickListener<Integer> onRecyclerItemClickListener() {
|
||||
return new OnRecyclerItemClickListener<Integer>() {
|
||||
@Override
|
||||
|
|
|
@ -30,7 +30,6 @@ import lu.circl.mispbump.auxiliary.PreferenceManager;
|
|||
import lu.circl.mispbump.auxiliary.QrCodeGenerator;
|
||||
import lu.circl.mispbump.auxiliary.RandomString;
|
||||
import lu.circl.mispbump.fragments.CameraFragment;
|
||||
import lu.circl.mispbump.fragments.UploadSettingsFragment;
|
||||
import lu.circl.mispbump.models.SyncInformation;
|
||||
import lu.circl.mispbump.models.UploadInformation;
|
||||
import lu.circl.mispbump.security.DiffieHellman;
|
||||
|
@ -101,6 +100,7 @@ public class SyncActivity extends AppCompatActivity {
|
|||
diffieHellman = DiffieHellman.getInstance();
|
||||
|
||||
qrCodeGenerator = new QrCodeGenerator(SyncActivity.this);
|
||||
|
||||
publicKeyQrCode = qrCodeGenerator.generateQrCode(DiffieHellman.publicKeyToString(diffieHellman.getPublicKey()));
|
||||
|
||||
uploadInformation = new UploadInformation();
|
||||
|
@ -111,7 +111,7 @@ public class SyncActivity extends AppCompatActivity {
|
|||
|
||||
qrFrame = findViewById(R.id.qrFrame);
|
||||
qrCode = findViewById(R.id.qrCode);
|
||||
qrHint = findViewById(R.id.qrHint);
|
||||
qrHint = findViewById(R.id.qrInfo);
|
||||
|
||||
prevButton = findViewById(R.id.prevButton);
|
||||
prevButton.setOnClickListener(onPrevClicked);
|
||||
|
@ -153,7 +153,6 @@ public class SyncActivity extends AppCompatActivity {
|
|||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
|
||||
String camTag = CameraFragment.class.getSimpleName();
|
||||
String settingsTag = UploadSettingsFragment.class.getSimpleName();
|
||||
|
||||
switch (state) {
|
||||
case PUBLIC_KEY:
|
||||
|
@ -167,11 +166,6 @@ public class SyncActivity extends AppCompatActivity {
|
|||
fragmentTransaction.add(R.id.fragmentContainer, cameraFragment, camTag);
|
||||
}
|
||||
|
||||
UploadSettingsFragment uploadSettingsFragment = (UploadSettingsFragment) fragmentManager.findFragmentByTag(settingsTag);
|
||||
if (uploadSettingsFragment != null) {
|
||||
fragmentTransaction.hide(uploadSettingsFragment);
|
||||
}
|
||||
|
||||
fragmentTransaction.commit();
|
||||
break;
|
||||
}
|
||||
|
@ -206,7 +200,7 @@ public class SyncActivity extends AppCompatActivity {
|
|||
nextButton.setImageDrawable(getDrawable(R.drawable.ic_arrow_forward));
|
||||
prevButton.setVisibility(View.VISIBLE);
|
||||
nextButton.setVisibility(View.VISIBLE);
|
||||
cameraFragment.disablePreview();
|
||||
// cameraFragment.disablePreview();
|
||||
qrReceivedFeedback(true);
|
||||
break;
|
||||
case SYNC_INFO_SHOW:
|
||||
|
@ -214,7 +208,7 @@ public class SyncActivity extends AppCompatActivity {
|
|||
nextButton.setImageDrawable(getDrawable(R.drawable.ic_arrow_forward));
|
||||
nextButton.setVisibility(View.INVISIBLE);
|
||||
prevButton.setVisibility(View.VISIBLE);
|
||||
cameraFragment.enablePreview();
|
||||
// cameraFragment.enablePreview();
|
||||
qrReceivedFeedback(false);
|
||||
break;
|
||||
case SYNC_INFO_SHOW_AND_RECEIVED:
|
||||
|
@ -222,7 +216,7 @@ public class SyncActivity extends AppCompatActivity {
|
|||
nextButton.setImageDrawable(getDrawable(R.drawable.ic_check));
|
||||
nextButton.setVisibility(View.VISIBLE);
|
||||
prevButton.setVisibility(View.VISIBLE);
|
||||
cameraFragment.disablePreview();
|
||||
// cameraFragment.disablePreview();
|
||||
qrReceivedFeedback(true);
|
||||
break;
|
||||
}
|
||||
|
@ -294,17 +288,17 @@ public class SyncActivity extends AppCompatActivity {
|
|||
if (uploadInformationList != null) {
|
||||
for (final UploadInformation ui : uploadInformationList) {
|
||||
if (ui.getRemote().organisation.uuid.equals(remoteSyncInfo.organisation.uuid)) {
|
||||
DialogManager.syncAlreadyExistsDialog(SyncActivity.this, new DialogManager.IDialogFeedback() {
|
||||
@Override
|
||||
public void positive() {
|
||||
uploadInformation.setUuid(ui.getUuid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void negative() {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
// DialogManager.syncAlreadyExistsDialog(SyncActivity.this, new DialogManager.IDialogFeedback() {
|
||||
// @Override
|
||||
// public void positive() {
|
||||
// uploadInformation.setUuid(ui.getUuid());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void negative() {
|
||||
// finish();
|
||||
// }
|
||||
// });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,13 +20,21 @@ import lu.circl.mispbump.security.DiffieHellman;
|
|||
public class DialogManager {
|
||||
|
||||
|
||||
public static void syncAlreadyExistsDialog(Context context, final IDialogFeedback callback) {
|
||||
public static void syncAlreadyExistsDialog(SyncInformation oldSync, SyncInformation newSync, Context context, final IDialogFeedback callback) {
|
||||
final AlertDialog.Builder adb = new AlertDialog.Builder(context);
|
||||
|
||||
adb.setTitle("Sync information already exists");
|
||||
adb.setMessage("You already synced with this organisation, would you like to update the information?" +
|
||||
"\nUpdating the information will reset the current authkey!");
|
||||
adb.setPositiveButton("Update", new DialogInterface.OnClickListener() {
|
||||
// this dialog needs definite user feedback
|
||||
adb.setCancelable(false);
|
||||
|
||||
if (oldSync.organisation.name.equals(newSync.organisation.name)) {
|
||||
adb.setTitle("Already Synced with " + oldSync.organisation.name);
|
||||
} else {
|
||||
adb.setTitle("Already Synced with " + oldSync.organisation.name + "(Now:" + newSync.organisation.name + ")");
|
||||
}
|
||||
|
||||
adb.setMessage("");
|
||||
|
||||
adb.setPositiveButton("Override Credentials", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (callback != null) {
|
||||
|
@ -35,7 +43,7 @@ public class DialogManager {
|
|||
}
|
||||
});
|
||||
|
||||
adb.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
|
||||
adb.setNegativeButton("Just Update Content", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (callback != null) {
|
||||
|
@ -298,4 +306,6 @@ public class DialogManager {
|
|||
void positive();
|
||||
void negative();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -407,6 +407,7 @@ public class PreferenceManager {
|
|||
|
||||
for (UploadInformation ui : cachedUploadInformationList) {
|
||||
if (ui.getUuid().compareTo(uuid) == 0) {
|
||||
// if is last element, then clear everything including IV and key in KeyStore
|
||||
if (cachedUploadInformationList.size() == 1) {
|
||||
clearUploadInformation();
|
||||
} else {
|
||||
|
|
|
@ -22,10 +22,14 @@ public class QrCodeGenerator {
|
|||
}
|
||||
|
||||
public Bitmap generateQrCode(String content) {
|
||||
int size = getDisplaySize().x;
|
||||
|
||||
if (size > getDisplaySize().y) {
|
||||
size = getDisplaySize().y;
|
||||
Point displaySize = new Point();
|
||||
callingActivity.getWindowManager().getDefaultDisplay().getSize(displaySize);
|
||||
|
||||
int size = displaySize.x;
|
||||
|
||||
if (size > displaySize.y) {
|
||||
size = displaySize.y;
|
||||
}
|
||||
|
||||
size = (int)(size * 0.8);
|
||||
|
@ -45,13 +49,6 @@ public class QrCodeGenerator {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Point getDisplaySize() {
|
||||
Point displaySize = new Point();
|
||||
callingActivity.getWindowManager().getDefaultDisplay().getSize(displaySize);
|
||||
|
||||
return displaySize;
|
||||
}
|
||||
|
||||
private Bitmap createBitmap(BitMatrix matrix) {
|
||||
int width = matrix.getWidth();
|
||||
int height = matrix.getHeight();
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package lu.circl.mispbump.fragments;
|
||||
|
||||
import android.Manifest;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
|
@ -33,7 +31,6 @@ import android.renderscript.Element;
|
|||
import android.renderscript.RenderScript;
|
||||
import android.renderscript.ScriptIntrinsicYuvToRGB;
|
||||
import android.renderscript.Type;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
|
@ -121,8 +118,6 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
|
|||
}
|
||||
}
|
||||
|
||||
private static final String TAG = "CAMERA";
|
||||
|
||||
private View hideCamView;
|
||||
|
||||
private QrScanCallback qrResultCallback;
|
||||
|
@ -374,19 +369,30 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
|
|||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
enablePreview();
|
||||
|
||||
hideCamView.setVisibility(View.GONE);
|
||||
startBackgroundThread();
|
||||
|
||||
imageProcessingThread = new ImageProcessingThread();
|
||||
imageProcessingThread.start();
|
||||
|
||||
if (autoFitTextureView.isAvailable()) {
|
||||
openCamera(autoFitTextureView.getWidth(), autoFitTextureView.getHeight());
|
||||
} else {
|
||||
autoFitTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
closeCamera();
|
||||
stopBackgroundThread();
|
||||
|
||||
if (imageProcessingThread.isAlive()) {
|
||||
imageProcessingThread.isRunning = false;
|
||||
}
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
private void requestCameraPermission() {
|
||||
|
@ -463,7 +469,7 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
|
|||
}
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Display rotation is invalid: " + displayRotation);
|
||||
return;
|
||||
}
|
||||
|
||||
Point displaySize = new Point();
|
||||
|
@ -778,6 +784,7 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
|
|||
public interface QrScanCallback {
|
||||
void qrScanResult(String qrData);
|
||||
}
|
||||
|
||||
private boolean readQrEnabled = true;
|
||||
private BarcodeDetector barcodeDetector;
|
||||
private RenderScript renderScript;
|
||||
|
@ -834,62 +841,62 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
|
|||
readQrEnabled = enabled;
|
||||
}
|
||||
|
||||
public void disablePreview() {
|
||||
|
||||
if (hideCamView.getAlpha() == 1 && hideCamView.getVisibility() == View.VISIBLE) {
|
||||
closeCamera();
|
||||
stopBackgroundThread();
|
||||
|
||||
if (imageProcessingThread.isAlive()) {
|
||||
imageProcessingThread.isRunning = false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
hideCamView.setAlpha(0f);
|
||||
hideCamView.setVisibility(View.VISIBLE);
|
||||
hideCamView.animate()
|
||||
.alpha(1f)
|
||||
.setDuration(250)
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
closeCamera();
|
||||
stopBackgroundThread();
|
||||
|
||||
if (imageProcessingThread.isAlive()) {
|
||||
imageProcessingThread.isRunning = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void enablePreview() {
|
||||
|
||||
startBackgroundThread();
|
||||
|
||||
imageProcessingThread = new ImageProcessingThread();
|
||||
imageProcessingThread.start();
|
||||
|
||||
if (autoFitTextureView.isAvailable()) {
|
||||
openCamera(autoFitTextureView.getWidth(), autoFitTextureView.getHeight());
|
||||
} else {
|
||||
autoFitTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
|
||||
}
|
||||
|
||||
hideCamView.setVisibility(View.VISIBLE);
|
||||
hideCamView.setAlpha(1f);
|
||||
hideCamView.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(1000)
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
hideCamView.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
// public void disablePreview() {
|
||||
//
|
||||
// if (hideCamView.getAlpha() == 1 && hideCamView.getVisibility() == View.VISIBLE) {
|
||||
// closeCamera();
|
||||
// stopBackgroundThread();
|
||||
//
|
||||
// if (imageProcessingThread.isAlive()) {
|
||||
// imageProcessingThread.isRunning = false;
|
||||
// }
|
||||
//
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// hideCamView.setAlpha(0f);
|
||||
// hideCamView.setVisibility(View.VISIBLE);
|
||||
// hideCamView.animate()
|
||||
// .alpha(1f)
|
||||
// .setDuration(250)
|
||||
// .setListener(new AnimatorListenerAdapter() {
|
||||
// @Override
|
||||
// public void onAnimationEnd(Animator animation) {
|
||||
// closeCamera();
|
||||
// stopBackgroundThread();
|
||||
//
|
||||
// if (imageProcessingThread.isAlive()) {
|
||||
// imageProcessingThread.isRunning = false;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// public void enablePreview() {
|
||||
//
|
||||
// startBackgroundThread();
|
||||
//
|
||||
// imageProcessingThread = new ImageProcessingThread();
|
||||
// imageProcessingThread.start();
|
||||
//
|
||||
// if (autoFitTextureView.isAvailable()) {
|
||||
// openCamera(autoFitTextureView.getWidth(), autoFitTextureView.getHeight());
|
||||
// } else {
|
||||
// autoFitTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
|
||||
// }
|
||||
//
|
||||
// hideCamView.setVisibility(View.VISIBLE);
|
||||
// hideCamView.setAlpha(1f);
|
||||
// hideCamView.animate()
|
||||
// .alpha(0f)
|
||||
// .setDuration(1000)
|
||||
// .setListener(new AnimatorListenerAdapter() {
|
||||
// @Override
|
||||
// public void onAnimationEnd(Animator animation) {
|
||||
// hideCamView.setVisibility(View.GONE);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
private void setUpBarcodeDetector() {
|
||||
barcodeDetector = new BarcodeDetector.Builder(getActivity())
|
||||
|
|
|
@ -60,11 +60,11 @@ public class SyncFragmentAdapter extends FragmentPagerAdapter {
|
|||
|
||||
public void disableCameraPreview() {
|
||||
if (cameraFragment_1 != null) {
|
||||
cameraFragment_1.disablePreview();
|
||||
// cameraFragment_1.disablePreview();
|
||||
}
|
||||
|
||||
if (cameraFragment_2 != null) {
|
||||
cameraFragment_2.disablePreview();
|
||||
// cameraFragment_2.disablePreview();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,13 +3,11 @@ package lu.circl.mispbump.security;
|
|||
import android.security.keystore.KeyGenParameterSpec;
|
||||
import android.security.keystore.KeyProperties;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
@ -29,8 +27,6 @@ import javax.crypto.spec.GCMParameterSpec;
|
|||
|
||||
public class KeyStoreWrapper {
|
||||
|
||||
private static final String TAG = "KeyStoreWrapper";
|
||||
|
||||
public static final String USER_INFO_ALIAS = "ALIAS_USER_INFO";
|
||||
public static final String USER_ORGANISATION_INFO_ALIAS = "ALIAS_USER_ORGANISATION_INFO";
|
||||
public static final String AUTOMATION_ALIAS = "ALIAS_AUTOMATION_KEY";
|
||||
|
@ -44,6 +40,7 @@ public class KeyStoreWrapper {
|
|||
|
||||
/**
|
||||
* Wraps the android key store to easily encrypt and decrypt sensitive data.
|
||||
*
|
||||
* @param alias identifies a key store entry (see public static ALIAS variables).
|
||||
*/
|
||||
public KeyStoreWrapper(String alias) {
|
||||
|
@ -75,7 +72,6 @@ public class KeyStoreWrapper {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return SecretKey associated with the given alias.
|
||||
*/
|
||||
private SecretKey getStoredKey() {
|
||||
|
@ -102,6 +98,7 @@ public class KeyStoreWrapper {
|
|||
|
||||
/**
|
||||
* Generates a new key.
|
||||
*
|
||||
* @return the newly generated key.
|
||||
*/
|
||||
private SecretKey generateKey() {
|
||||
|
@ -154,12 +151,13 @@ public class KeyStoreWrapper {
|
|||
|
||||
/**
|
||||
* Encrypt data with given algorithm and key associated with alias.
|
||||
*
|
||||
* @param data data to encrypt.
|
||||
* @return encrypted data as String.
|
||||
* @throws NoSuchPaddingException padding not found
|
||||
* @throws NoSuchAlgorithmException algorithm not found
|
||||
* @throws InvalidKeyException invalid key
|
||||
* @throws BadPaddingException bad padding
|
||||
* @throws NoSuchPaddingException padding not found
|
||||
* @throws NoSuchAlgorithmException algorithm not found
|
||||
* @throws InvalidKeyException invalid key
|
||||
* @throws BadPaddingException bad padding
|
||||
* @throws IllegalBlockSizeException illegal block size
|
||||
*/
|
||||
public String encrypt(String data) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
|
||||
|
@ -181,22 +179,17 @@ public class KeyStoreWrapper {
|
|||
|
||||
/**
|
||||
* Decrypts data with given algorithm and key associated with alias.
|
||||
*
|
||||
* @param input encrypted data.
|
||||
* @return decrypted data as String.
|
||||
* @throws NoSuchPaddingException padding not found
|
||||
* @throws NoSuchAlgorithmException algorithm not found
|
||||
* @throws NoSuchPaddingException padding not found
|
||||
* @throws NoSuchAlgorithmException algorithm not found
|
||||
* @throws InvalidAlgorithmParameterException invalid algorithm parameters
|
||||
* @throws InvalidKeyException invalid key
|
||||
* @throws BadPaddingException bad padding
|
||||
* @throws IllegalBlockSizeException illegal block size
|
||||
* @throws InvalidKeyException invalid key
|
||||
* @throws BadPaddingException bad padding
|
||||
* @throws IllegalBlockSizeException illegal block size
|
||||
*/
|
||||
public String decrypt(String input) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
|
||||
|
||||
// extract iv from save data
|
||||
// String[] parts = input.split(":::");
|
||||
// byte[] iv = Base64.decode(parts[0], Base64.DEFAULT);
|
||||
// byte[] data = Base64.decode(parts[1], Base64.DEFAULT);
|
||||
|
||||
byte[] in = Base64.decode(input, Base64.NO_WRAP);
|
||||
IvAndData ivAndData = splitCombinedArray(in, 12);
|
||||
|
||||
|
@ -217,9 +210,6 @@ public class KeyStoreWrapper {
|
|||
|
||||
KeyStore ks = KeyStore.getInstance(KEYSTORE_PROVIDER);
|
||||
ks.load(null);
|
||||
|
||||
Log.i(TAG, "Size: " + ks.size());
|
||||
|
||||
Enumeration<String> aliases = ks.aliases();
|
||||
|
||||
while (aliases.hasMoreElements()) {
|
||||
|
@ -240,14 +230,12 @@ public class KeyStoreWrapper {
|
|||
|
||||
/**
|
||||
* Combine IV and encrypted data.
|
||||
* @param iv initialisation vector
|
||||
*
|
||||
* @param iv initialisation vector
|
||||
* @param encryptedData encrypted data
|
||||
* @return combination of iv and encrypted data
|
||||
*/
|
||||
private byte[] getCombinedArray(byte[] iv, byte[] encryptedData) {
|
||||
|
||||
Log.i(TAG, "iv length = " + iv.length);
|
||||
|
||||
byte[] combined = new byte[iv.length + encryptedData.length];
|
||||
for (int i = 0; i < combined.length; ++i) {
|
||||
combined[i] = i < iv.length ? iv[i] : encryptedData[i - iv.length];
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/qrHint"
|
||||
android:id="@+id/qrInfo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableStart="@drawable/ic_info_outline"
|
||||
|
@ -47,7 +47,7 @@
|
|||
android:textColor="@color/colorPrimaryDark"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/qrHint2"
|
||||
android:id="@+id/qrInfoStatic"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableStart="@drawable/ic_info_outline"
|
||||
|
@ -98,62 +98,4 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<!--<LinearLayout-->
|
||||
<!--app:layout_behavior=".customViews.ExtendedBottomSheetBehavior"-->
|
||||
<!--android:id="@+id/bottomSheet"-->
|
||||
<!--android:layout_width="match_parent"-->
|
||||
<!--android:layout_height="wrap_content"-->
|
||||
<!--android:orientation="vertical"-->
|
||||
<!--android:background="@drawable/rect_rounded_top"-->
|
||||
<!--android:backgroundTint="@color/colorPrimary"-->
|
||||
<!--app:behavior_peekHeight="64dp">-->
|
||||
|
||||
<!--<LinearLayout-->
|
||||
<!--android:orientation="horizontal"-->
|
||||
<!--android:layout_width="match_parent"-->
|
||||
<!--android:layout_height="wrap_content">-->
|
||||
|
||||
<!--<ImageButton-->
|
||||
<!--android:id="@+id/prevButton"-->
|
||||
<!--android:layout_width="64dp"-->
|
||||
<!--android:layout_height="64dp"-->
|
||||
<!--android:background="?attr/selectableItemBackground"-->
|
||||
<!--android:padding="8dp"-->
|
||||
<!--app:layout_constraintStart_toStartOf="parent"-->
|
||||
<!--app:layout_constraintTop_toTopOf="parent"-->
|
||||
<!--app:srcCompat="@drawable/ic_arrow_back" />-->
|
||||
|
||||
<!--<ImageView-->
|
||||
<!--android:visibility="invisible"-->
|
||||
<!--android:id="@+id/bottomSheetIcon"-->
|
||||
<!--android:layout_weight="1"-->
|
||||
<!--android:layout_width="0dp"-->
|
||||
<!--android:layout_height="32dp"-->
|
||||
<!--android:layout_gravity="center_vertical"-->
|
||||
<!--android:src="@drawable/ic_check_outline" />-->
|
||||
|
||||
<!--<ImageButton-->
|
||||
<!--android:id="@+id/nextButton"-->
|
||||
<!--android:layout_width="64dp"-->
|
||||
<!--android:layout_height="64dp"-->
|
||||
<!--android:background="?attr/selectableItemBackground"-->
|
||||
<!--android:padding="8dp"-->
|
||||
<!--app:layout_constraintEnd_toEndOf="parent"-->
|
||||
<!--app:layout_constraintTop_toTopOf="parent"-->
|
||||
<!--app:srcCompat="@drawable/ic_arrow_forward" />-->
|
||||
<!--</LinearLayout>-->
|
||||
|
||||
<!--<TextView-->
|
||||
<!--android:id="@+id/bottomSheetText"-->
|
||||
<!--android:layout_width="wrap_content"-->
|
||||
<!--android:layout_height="wrap_content"-->
|
||||
<!--android:paddingStart="16dp"-->
|
||||
<!--android:paddingEnd="16dp"-->
|
||||
<!--android:paddingBottom="16dp"-->
|
||||
<!--android:gravity="top"-->
|
||||
<!--android:layout_gravity="center"-->
|
||||
<!--android:text="Received public key from partner"-->
|
||||
<!--android:textColor="@color/white" />-->
|
||||
<!--</LinearLayout>-->
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
Loading…
Reference in New Issue