diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8d40ef8..9369329 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -15,6 +15,7 @@
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
+
@@ -22,6 +23,7 @@
+
@@ -30,9 +32,7 @@
android:label="@string/login" />
-
diff --git a/app/src/main/java/lu/circl/mispbump/AESActivity.java b/app/src/main/java/lu/circl/mispbump/AESActivity.java
deleted file mode 100644
index c4836a0..0000000
--- a/app/src/main/java/lu/circl/mispbump/AESActivity.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package lu.circl.mispbump;
-
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
-import android.os.Bundle;
-import android.support.v7.widget.Toolbar;
-import android.view.View;
-import android.widget.Button;
-import android.widget.TextView;
-
-import lu.circl.mispbump.security.AESSecurity;
-
-public class AESActivity extends AppCompatActivity {
-
- private TextView info;
- private Button button;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_aes);
-
- // populate Toolbar (Actionbar)
- Toolbar myToolbar = findViewById(R.id.toolbar);
- setSupportActionBar(myToolbar);
-
- ActionBar ab = getSupportActionBar();
- if (ab != null) {
- ab.setDisplayHomeAsUpEnabled(true);
- }
-
- info = findViewById(R.id.aes_info);
- button = findViewById(R.id.aes_button);
-
- button.setOnClickListener(onButtonClick);
- }
-
- private View.OnClickListener onButtonClick = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- AESSecurity sec1 = new AESSecurity();
- AESSecurity sec2 = new AESSecurity();
-
- String message = "Geheimer Text von A als auch von B ...";
-
- String pub1 = sec1.getPublicKey().toString();
- info.setText("A PK: " + pub1 + "\n");
-
- String pub2 = sec2.getPublicKey().toString();
- info.append("B PK: " + pub2 + "\n");
-
- sec1.setForeignPublicKey(sec2.getPublicKey());
- sec2.setForeignPublicKey(sec1.getPublicKey());
- info.append("\n-- public keys wurden ausgetauscht --\n\n");
-
- String enc1 = sec1.encrypt(message);
- info.append("A encrypted: " + enc1 + "\n");
- String enc2 = sec2.encrypt(message);
- info.append("B encrypted: " + enc2 + "\n\n");
-
- info.append("A entschlüsselt B's Nachricht: " + sec1.decrypt(enc2) + "\n");
- info.append("B entschlüsselt A's Nachricht: " + sec2.decrypt(enc1) + "\n");
- }
- };
-}
diff --git a/app/src/main/java/lu/circl/mispbump/HomeActivity.java b/app/src/main/java/lu/circl/mispbump/HomeActivity.java
index 1f5666e..f406916 100644
--- a/app/src/main/java/lu/circl/mispbump/HomeActivity.java
+++ b/app/src/main/java/lu/circl/mispbump/HomeActivity.java
@@ -57,12 +57,6 @@ public class HomeActivity extends AppCompatActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
-
- case R.id.aes:
- Intent i = new Intent(getApplicationContext(), AESActivity.class);
- startActivity(i);
- return true;
-
case R.id.main_menu_clear_and_logout:
clearDeviceAndLogOut();
return true;
diff --git a/app/src/main/java/lu/circl/mispbump/SyncActivity.java b/app/src/main/java/lu/circl/mispbump/SyncActivity.java
index 8469adc..e91a192 100644
--- a/app/src/main/java/lu/circl/mispbump/SyncActivity.java
+++ b/app/src/main/java/lu/circl/mispbump/SyncActivity.java
@@ -1,62 +1,150 @@
package lu.circl.mispbump;
-import android.app.Activity;
import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.Point;
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
+import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
-import android.os.Bundle;
+import android.support.v7.widget.Toolbar;
+import android.util.Log;
import android.view.View;
import android.widget.ImageView;
-import android.widget.TextView;
import android.widget.Toast;
-import com.google.zxing.BarcodeFormat;
-import com.google.zxing.EncodeHintType;
-import com.google.zxing.MultiFormatWriter;
-import com.google.zxing.WriterException;
-import com.google.zxing.common.BitMatrix;
-import com.google.zxing.qrcode.QRCodeWriter;
-import com.journeyapps.barcodescanner.BarcodeEncoder;
+import com.google.gson.Gson;
-import java.nio.IntBuffer;
-import java.nio.ShortBuffer;
-import java.util.HashMap;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
import java.util.List;
-import java.util.Map;
+import lu.circl.mispbump.auxiliary.PreferenceManager;
+import lu.circl.mispbump.auxiliary.QrCodeGenerator;
+import lu.circl.mispbump.auxiliary.RandomString;
import lu.circl.mispbump.cam.CameraFragment;
import lu.circl.mispbump.restful_client.MispRestClient;
import lu.circl.mispbump.restful_client.MispServer;
+import lu.circl.mispbump.restful_client.MispUser;
import lu.circl.mispbump.restful_client.Organisation;
import lu.circl.mispbump.restful_client.Server;
import lu.circl.mispbump.restful_client.User;
import lu.circl.mispbump.security.AESSecurity;
+/**
+ * Step 1: Add partner org as local org (uuid must be the same)
+ * Step 2: Add SyncUser to local partner org
+ * Step 3: Add SyncServer with SyncUser's authkey
+ *
+ * What do we need to transmit?
+ * 1. Own organisation details
+ * 2. Authkey of SyncUser
+ * 3. Server url
+ */
public class SyncActivity extends AppCompatActivity {
private static final String TAG = "SyncActivity";
- private CameraFragment cameraFragment;
-
- private MispRestClient restClient;
- private ImageView qrCodeView;
private AESSecurity aesSecurity;
+ private MispRestClient restClient;
+ private CameraFragment cameraFragment;
+ private ImageView qrCodeView;
+ private FloatingActionButton continueButton;
+
+ private SyncState currentSyncState = SyncState.publicKeyExchange;
+
+ private enum SyncState {
+ publicKeyExchange,
+ dataExchange
+ }
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sync);
- qrCodeView = findViewById(R.id.qrcode);
- aesSecurity = AESSecurity.getInstance();
+ Toolbar myToolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(myToolbar);
- showPublicKeyQr();
- enableCameraFragment();
+ ActionBar ab = getSupportActionBar();
+ if (ab != null) {
+ ab.setDisplayHomeAsUpEnabled(true);
+ }
+
+ qrCodeView = findViewById(R.id.qrcode);
+ continueButton = findViewById(R.id.continue_fab);
+ continueButton.setOnClickListener(onContinueClicked);
+ continueButton.hide();
+
+ aesSecurity = AESSecurity.getInstance();
+ restClient = new MispRestClient(this);
+
+ enableSyncOptionsFragment();
}
+ private View.OnClickListener onContinueClicked = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ switch (currentSyncState) {
+ case publicKeyExchange:
+ currentSyncState = SyncState.dataExchange;
+ showInformationQr();
+ continueButton.hide();
+ cameraFragment.setReadQrEnabled(true);
+ break;
+
+ case dataExchange:
+ // TODO upload
+ break;
+ }
+ }
+ };
+
+ /**
+ * Callback for the camera fragment.
+ * Delivers the content of a scanned QR code.
+ */
+ private CameraFragment.QrScanCallback onQrCodeScanned = new CameraFragment.QrScanCallback() {
+ @Override
+ public void qrScanResult(String qrData) {
+ switch (currentSyncState) {
+ case publicKeyExchange:
+ try {
+ aesSecurity.setForeignPublicKey(AESSecurity.publicKeyFromString(qrData));
+ cameraFragment.setReadQrEnabled(false);
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ continueButton.show();
+ }
+ });
+ } catch (NoSuchAlgorithmException e) {
+ MakeToast("Something gone wrong while parsing the key (no such algorithm)");
+ } catch (InvalidKeySpecException e) {
+ MakeToast("Something gone wrong while parsing the key (invalid key spec)");
+ }
+
+ break;
+
+ case dataExchange:
+ // disable qr read
+ cameraFragment.setReadQrEnabled(false);
+
+ String data = aesSecurity.decrypt(qrData);
+ SyncInformation info = new Gson().fromJson(data, SyncInformation.class);
+
+ Log.i(TAG, info.organisation.toString());
+ Log.i(TAG, info.user.toString());
+
+ break;
+ }
+ }
+ };
+
+ /**
+ * Creates the camera fragment used to scan the QR codes.
+ */
private void enableCameraFragment() {
cameraFragment = new CameraFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
@@ -65,23 +153,121 @@ public class SyncActivity extends AppCompatActivity {
transaction.commit();
cameraFragment.setReadQrEnabled(true);
- cameraFragment.setOnQrAvailableListener(resultCallback);
+ cameraFragment.setOnQrAvailableListener(onQrCodeScanned);
}
+ /**
+ * options for this particular sync
+ */
+ private void enableSyncOptionsFragment() {
+ SyncOptionsFragment syncOptionsFragment = new SyncOptionsFragment();
+
+ syncOptionsFragment.setOnOptionsReadyCallback(new SyncOptionsFragment.OptionsReadyCallback() {
+ @Override
+ public void ready(boolean share_events, boolean push, boolean pull, boolean caching) {
+ showPublicKeyQr();
+ enableCameraFragment();
+ }
+ });
+
+ FragmentManager fragmentManager = getSupportFragmentManager();
+ FragmentTransaction transaction = fragmentManager.beginTransaction();
+ transaction.replace(R.id.sync_fragment_container, syncOptionsFragment, syncOptionsFragment.getClass().getSimpleName());
+ transaction.commit();
+ }
+
+ /**
+ * Display public key QR code.
+ */
private void showPublicKeyQr() {
- Bitmap bm = generateQrCodeFromString(aesSecurity.getPublicKey().toString());
+ QrCodeGenerator qrCodeGenerator = new QrCodeGenerator(this);
+ Bitmap bm = qrCodeGenerator.generateQrCode(AESSecurity.publicKeyToString(aesSecurity.getPublicKey()));
qrCodeView.setImageBitmap(bm);
qrCodeView.setVisibility(View.VISIBLE);
}
- private CameraFragment.QrResultCallback resultCallback = new CameraFragment.QrResultCallback() {
- @Override
- public void qrDataResult(String qrData) {
- // TODO validate data
- cameraFragment.setReadQrEnabled(false);
- MakeToast(qrData);
- }
- };
+ /**
+ * Display sync info QR code.
+ */
+ private void showInformationQr() {
+ PreferenceManager preferenceManager = PreferenceManager.getInstance(this);
+ QrCodeGenerator qrCodeGenerator = new QrCodeGenerator(this);
+ Gson gson = new Gson();
+
+ // my organisation
+ Organisation org = preferenceManager.getUserOrganisation();
+ User user = preferenceManager.getUserInfo();
+ MispUser mispUser = new MispUser(user);
+
+ Server server = new Server(
+ "SyncServer for " + org.name,
+ preferenceManager.getServerUrl(),
+ new RandomString(40).nextString(),
+ -1
+ );
+
+ MispServer mispServer = new MispServer(server, org, null);
+
+ SyncInformation syncInformation = new SyncInformation(user, org, server);
+ String encrypted = aesSecurity.encrypt(gson.toJson(syncInformation));
+
+ final Bitmap bm = qrCodeGenerator.generateQrCode(encrypted);
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ qrCodeView.setImageBitmap(bm);
+ qrCodeView.setVisibility(View.VISIBLE);
+ }
+ });
+ }
+
+ private void addPartnerOrg(Organisation organisation) {
+ restClient.addOrganisation(organisation, new MispRestClient.OrganisationCallback() {
+ @Override
+ public void success(Organisation organisation) {
+
+ }
+
+ @Override
+ public void failure(String error) {
+
+ }
+ });
+ }
+
+ private void addSyncUser(User user) {
+ restClient.addUser(user, new MispRestClient.UserCallback() {
+ @Override
+ public void success(User user) {
+
+ }
+
+ @Override
+ public void failure(String error) {
+
+ }
+ });
+ }
+
+ private void addServer(MispServer server) {
+ restClient.addServer(server, new MispRestClient.ServerCallback() {
+ @Override
+ public void success(List servers) {
+
+ }
+
+ @Override
+ public void success(MispServer server) {
+
+ }
+
+ @Override
+ public void failure(String error) {
+
+ }
+ });
+ }
private void MakeToast(final String message) {
this.runOnUiThread(new Runnable() {
@@ -92,120 +278,6 @@ public class SyncActivity extends AppCompatActivity {
});
}
- private Bitmap generateQrCodeFromString(String content) {
-
- Point displaySize = new Point();
- this.getWindowManager().getDefaultDisplay().getSize(displaySize);
-
- int size = displaySize.x;
-
- if (displaySize.x > displaySize.y) {
- size = displaySize.y;
- }
-
- size = (int)(size * 0.8);
-
- try {
- MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
-
- Map hints = new HashMap<>();
- hints.put(EncodeHintType.MARGIN, 0);
-
- BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, size, size, hints);
- return createBitmap(bitMatrix);
- } catch (WriterException e) {
- e.printStackTrace();
- }
-
- return null;
- }
-
- private Bitmap createBitmap(BitMatrix matrix) {
- int width = matrix.getWidth();
- int height = matrix.getHeight();
- int[] pixels = new int[width * height];
- for (int y = 0; y < height; y++) {
- int offset = y * width;
- for (int x = 0; x < width; x++) {
- pixels[offset + x] = matrix.get(x, y) ? 0xFF000000 : 0x55FFFFFF;
- }
- }
-
- Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
- return bitmap;
- }
-
-// private View.OnClickListener onAddUser = new View.OnClickListener() {
-// @Override
-// public void onClick(View v) {
-//
-// User user = new User(1, "felixpk@outlook.de", MispRestClient.roleId.SYNC_USER.value());
-//
-// restClient.addUser(user, new MispRestClient.UserCallback() {
-// @Override
-// public void success(User user) {
-// resultView.setText(user.toString());
-// }
-//
-// @Override
-// public void failure(String error) {
-// resultView.setText(error);
-// }
-// });
-// }
-// };
-//
-// private View.OnClickListener onAddOrganisation = new View.OnClickListener() {
-// @Override
-// public void onClick(View v) {
-// Organisation organisation = new Organisation("API Organisation 2", "API Generated Organisation");
-// organisation.local = true;
-// organisation.nationality = "Buxdehude";
-//
-// restClient.addOrganisation(organisation, new MispRestClient.OrganisationCallback() {
-// @Override
-// public void success(Organisation organisation) {
-// resultView.setText(organisation.toString());
-// }
-//
-// @Override
-// public void failure(String error) {
-// resultView.setText(error);
-// }
-// });
-// }
-// };
-//
-// private View.OnClickListener onAddServer = new View.OnClickListener() {
-// @Override
-// public void onClick(View v) {
-//
-// Organisation organisation = new Organisation("", "");
-// Server server = new Server("API Remote Server", "https://127.0.0.1", "0000000000000000000000000000000000000000", 1);
-//
-// MispServer mispServer = new MispServer(server, organisation, organisation);
-//
-//
-// restClient.addServer(mispServer, new MispRestClient.ServerCallback() {
-// @Override
-// public void success(List servers) {
-//
-// }
-//
-// @Override
-// public void success(MispServer server) {
-//
-// }
-//
-// @Override
-// public void failure(String error) {
-//
-// }
-// });
-// }
-// };
-//
// private View.OnClickListener onGetServers = new View.OnClickListener() {
// @Override
// public void onClick(View v) {
diff --git a/app/src/main/java/lu/circl/mispbump/SyncOptionsFragment.java b/app/src/main/java/lu/circl/mispbump/SyncOptionsFragment.java
new file mode 100644
index 0000000..d192f76
--- /dev/null
+++ b/app/src/main/java/lu/circl/mispbump/SyncOptionsFragment.java
@@ -0,0 +1,46 @@
+package lu.circl.mispbump;
+
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Switch;
+
+public class SyncOptionsFragment extends Fragment {
+
+ private Switch share, push, pull, cache;
+ private OptionsReadyCallback readyCallback;
+
+ public interface OptionsReadyCallback {
+ void ready(boolean share_events, boolean push, boolean pull, boolean caching);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.fragment_sync_options, container, false);
+
+ share = v.findViewById(R.id.share_events_switch);
+ push = v.findViewById(R.id.push_switch);
+ pull = v.findViewById(R.id.pull_switch);
+ cache = v.findViewById(R.id.cache_switch);
+
+ FloatingActionButton fab = v.findViewById(R.id.sync_options_fab);
+ fab.setOnClickListener(fabListener);
+
+ return v;
+ }
+
+ private View.OnClickListener fabListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ readyCallback.ready(share.isChecked(), push.isChecked(), pull.isChecked(), cache.isChecked());
+ }
+ };
+
+ public void setOnOptionsReadyCallback(OptionsReadyCallback callback) {
+ readyCallback = callback;
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/lu/circl/mispbump/auxiliary/QrCodeGenerator.java b/app/src/main/java/lu/circl/mispbump/auxiliary/QrCodeGenerator.java
new file mode 100644
index 0000000..b8a58c6
--- /dev/null
+++ b/app/src/main/java/lu/circl/mispbump/auxiliary/QrCodeGenerator.java
@@ -0,0 +1,66 @@
+package lu.circl.mispbump.auxiliary;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.Point;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.MultiFormatWriter;
+import com.google.zxing.WriterException;
+import com.google.zxing.common.BitMatrix;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class QrCodeGenerator {
+
+ private Activity callingActivity;
+
+ public QrCodeGenerator(Activity callingActivity) {
+ this.callingActivity = callingActivity;
+ }
+
+ public Bitmap generateQrCode(String content) {
+ Point displaySize = new Point();
+ callingActivity.getWindowManager().getDefaultDisplay().getSize(displaySize);
+
+ int size = displaySize.x;
+
+ if (displaySize.x > displaySize.y) {
+ size = displaySize.y;
+ }
+
+ size = (int)(size * 0.8);
+
+ try {
+ MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
+
+ Map hints = new HashMap<>();
+ hints.put(EncodeHintType.MARGIN, 0);
+
+ BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, size, size, hints);
+ return createBitmap(bitMatrix);
+ } catch (WriterException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ private Bitmap createBitmap(BitMatrix matrix) {
+ int width = matrix.getWidth();
+ int height = matrix.getHeight();
+ int[] pixels = new int[width * height];
+ for (int y = 0; y < height; y++) {
+ int offset = y * width;
+ for (int x = 0; x < width; x++) {
+ pixels[offset + x] = matrix.get(x, y) ? 0xFF000000 : 0x99FFFFFF;
+ }
+ }
+
+ Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
+ return bitmap;
+ }
+}
diff --git a/app/src/main/java/lu/circl/mispbump/cam/CameraFragment.java b/app/src/main/java/lu/circl/mispbump/cam/CameraFragment.java
index c36f236..5979a57 100644
--- a/app/src/main/java/lu/circl/mispbump/cam/CameraFragment.java
+++ b/app/src/main/java/lu/circl/mispbump/cam/CameraFragment.java
@@ -18,7 +18,6 @@ import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@@ -94,7 +93,7 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
if (barcodes.size() > 0) {
if (qrResultCallback != null) {
- qrResultCallback.qrDataResult(barcodes.valueAt(0).rawValue);
+ qrResultCallback.qrScanResult(barcodes.valueAt(0).rawValue);
try {
sleep(100);
@@ -103,7 +102,7 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
}
} else {
- Log.i(TAG, "QrResultCallback not attached");
+ Log.i(TAG, "QrScanCallback not attached");
}
}
@@ -121,7 +120,7 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
}
}
- private QrResultCallback qrResultCallback;
+ private QrScanCallback qrResultCallback;
@Override
public void onAttach(Context context) {
@@ -783,8 +782,8 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
}
- public interface QrResultCallback {
- void qrDataResult(String qrData);
+ public interface QrScanCallback {
+ void qrScanResult(String qrData);
}
private boolean readQrEnabled = true;
@@ -854,7 +853,7 @@ public class CameraFragment extends Fragment implements ActivityCompat.OnRequest
}
}
- public void setOnQrAvailableListener(QrResultCallback callback) {
+ public void setOnQrAvailableListener(QrScanCallback callback) {
qrResultCallback = callback;
}
}
diff --git a/app/src/main/java/lu/circl/mispbump/restful_client/MispRestClient.java b/app/src/main/java/lu/circl/mispbump/restful_client/MispRestClient.java
index 92ec224..7c781e1 100644
--- a/app/src/main/java/lu/circl/mispbump/restful_client/MispRestClient.java
+++ b/app/src/main/java/lu/circl/mispbump/restful_client/MispRestClient.java
@@ -31,18 +31,6 @@ import retrofit2.converter.gson.GsonConverterFactory;
*/
public class MispRestClient {
- // callbacks and interfaces
-
- public enum roleId {
- ADMIN(1), ORG_ADMIN(2), USER(3), PUBLISHER(4), SYNC_USER(5), READ_ONLY(6);
-
- private final int id;
-
- roleId(int id) { this.id = id; }
-
- public int value() { return id; }
- }
-
public interface UserCallback {
void success(User user);
void failure(String error);
@@ -59,7 +47,6 @@ public class MispRestClient {
void failure(String error);
}
- // fields
private PreferenceManager preferenceManager;
private MispRestService mispRestService;
diff --git a/app/src/main/java/lu/circl/mispbump/restful_client/MispUser.java b/app/src/main/java/lu/circl/mispbump/restful_client/MispUser.java
index 0c278a1..4bcb275 100644
--- a/app/src/main/java/lu/circl/mispbump/restful_client/MispUser.java
+++ b/app/src/main/java/lu/circl/mispbump/restful_client/MispUser.java
@@ -9,4 +9,7 @@ public class MispUser {
@Expose
public User user;
+ public MispUser(User user) {
+ this.user = user;
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/lu/circl/mispbump/restful_client/User.java b/app/src/main/java/lu/circl/mispbump/restful_client/User.java
index 43873fd..1458bc1 100644
--- a/app/src/main/java/lu/circl/mispbump/restful_client/User.java
+++ b/app/src/main/java/lu/circl/mispbump/restful_client/User.java
@@ -5,6 +5,13 @@ import com.google.gson.annotations.SerializedName;
public class User {
+ public static final int ROLE_ADMIN = 1;
+ public static final int ROLE_ORG_ADMIN = 2;
+ public static final int ROLE_USER = 3;
+ public static final int ROLE_PUBLISHER = 4;
+ public static final int ROLE_SYNC_USER = 5;
+ public static final int ROLE_READ_ONLY = 6;
+
public User(Integer org_id, String email, Integer role_id) {
this.org_id = org_id;
this.email = email;
diff --git a/app/src/main/java/lu/circl/mispbump/security/AESSecurity.java b/app/src/main/java/lu/circl/mispbump/security/AESSecurity.java
index 052b599..32b7b8e 100644
--- a/app/src/main/java/lu/circl/mispbump/security/AESSecurity.java
+++ b/app/src/main/java/lu/circl/mispbump/security/AESSecurity.java
@@ -5,6 +5,8 @@ import android.util.Base64;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
+
+import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
@@ -14,7 +16,7 @@ public class AESSecurity {
private static final String TAG = "MISP_LOGGING";
- private static final String ENCRYPT_ALGORITHM = "AES/CBC/PKCS5Padding";
+ private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
private static final String KEY_PAIR_ALGORITHM = "EC";
private static final int KEY_SIZE = 521; // 224 | 256 | 384 | 521
private static final String KEY_AGREEMENT_ALGORITHM = "ECDH";
@@ -28,16 +30,22 @@ public class AESSecurity {
private byte[] sharedSecret;
private IvParameterSpec ivParameterSpec;
- public AESSecurity() {
+ private AESSecurity() {
initialize();
}
+ public static AESSecurity getInstance() {
+ if(instance == null) {
+ instance = new AESSecurity();
+ }
+ return instance;
+ }
+
/**
* Generates a public and a private key using an elliptic curve algorithm.
* The private key is fed into the key agreement instance.
*/
private void initialize() {
-
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_PAIR_ALGORITHM);
kpg.initialize(KEY_SIZE);
@@ -58,7 +66,6 @@ public class AESSecurity {
* @param publickey public key of the sync partner
*/
public void setForeignPublicKey(PublicKey publickey) {
-
try {
keyAgreement.doPhase(publickey, true);
@@ -74,53 +81,43 @@ public class AESSecurity {
}
/**
- *
- * @param data
- * @return
+ * Encrypts data.
+ * @param data data to encrypt
+ * @return To String converted and encrypted data
*/
public String encrypt(String data) {
try {
+ Cipher c = Cipher.getInstance(CIPHER_ALGORITHM);
+ c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sharedSecret, CIPHER_ALGORITHM), ivParameterSpec);
- Key key = generateKey();
- Cipher c = Cipher.getInstance(ENCRYPT_ALGORITHM);
-
- try {
- c.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
- } catch (InvalidAlgorithmParameterException e) {
- e.printStackTrace();
- }
-
- byte[] encVal = c.doFinal(data.getBytes());
- return Base64.encodeToString(encVal, 0);
+ byte[] cipherText = c.doFinal(data.getBytes(StandardCharsets.UTF_8));
+ return Base64.encodeToString(cipherText, Base64.NO_WRAP);
} catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException e) {
e.printStackTrace();
+ } catch (InvalidAlgorithmParameterException e) {
+ e.printStackTrace();
}
return data;
}
/**
- *
- * @param data
- * @return
+ * Decrypts data.
+ * @param data data to decrypt
+ * @return To String converted and decrypted data
*/
public String decrypt(String data) {
try {
- Key key = generateKey();
+ Cipher c = Cipher.getInstance(CIPHER_ALGORITHM);
+ c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sharedSecret, CIPHER_ALGORITHM), ivParameterSpec);
- Cipher c = Cipher.getInstance(ENCRYPT_ALGORITHM);
+ byte[] cipherText = Base64.decode(data, Base64.NO_WRAP);
+ return new String(c.doFinal(cipherText), StandardCharsets.UTF_8);
- try {
- c.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
- } catch (InvalidAlgorithmParameterException e) {
- e.printStackTrace();
- }
-
- byte[] decoded = Base64.decode(data, 0);
- byte[] decValue = c.doFinal(decoded);
- return new String(decValue);
} catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException e) {
e.printStackTrace();
+ } catch (InvalidAlgorithmParameterException e) {
+ e.printStackTrace();
}
return data;
}
@@ -129,31 +126,12 @@ public class AESSecurity {
return publickey;
}
- private Key generateKey() {
- return new SecretKeySpec(sharedSecret, ENCRYPT_ALGORITHM);
- }
-
public static String publicKeyToString(PublicKey key) {
return Base64.encodeToString(key.getEncoded(), Base64.DEFAULT);
}
- public static PublicKey publicKeyFromString(String key) {
- try {
-
- byte[] input = Base64.decode(key, Base64.DEFAULT);
- return KeyFactory.getInstance(KEY_FACTORY_ALGORITHM).generatePublic(new X509EncodedKeySpec(input));
-
- } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
- e.printStackTrace();
- }
-
- return null;
- }
-
- public static AESSecurity getInstance() {
- if(instance == null) {
- instance = new AESSecurity();
- }
- return instance;
+ public static PublicKey publicKeyFromString(String key) throws NoSuchAlgorithmException, InvalidKeySpecException {
+ byte[] input = Base64.decode(key, Base64.DEFAULT);
+ return KeyFactory.getInstance(KEY_FACTORY_ALGORITHM).generatePublic(new X509EncodedKeySpec(input));
}
}
diff --git a/app/src/main/java/lu/circl/mispbump/security/KeyStoreWrapper.java b/app/src/main/java/lu/circl/mispbump/security/KeyStoreWrapper.java
index 2af8db5..01e5d67 100644
--- a/app/src/main/java/lu/circl/mispbump/security/KeyStoreWrapper.java
+++ b/app/src/main/java/lu/circl/mispbump/security/KeyStoreWrapper.java
@@ -72,7 +72,6 @@ public class KeyStoreWrapper {
return false;
}
-
/**
*
* @return SecretKey associated with the given alias.
@@ -155,11 +154,11 @@ 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
- * @throws NoSuchAlgorithmException
- * @throws InvalidKeyException
- * @throws BadPaddingException
- * @throws IllegalBlockSizeException
+ * @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 {
SecretKey secretKey;
@@ -184,12 +183,12 @@ public class KeyStoreWrapper {
* Decrypts data with given algorithm and key associated with alias.
* @param input encrypted data.
* @return decrypted data as String.
- * @throws NoSuchPaddingException
- * @throws NoSuchAlgorithmException
- * @throws InvalidAlgorithmParameterException
- * @throws InvalidKeyException
- * @throws BadPaddingException
- * @throws IllegalBlockSizeException
+ * @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
*/
public String decrypt(String input) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
@@ -236,4 +235,18 @@ public class KeyStoreWrapper {
e.printStackTrace();
}
}
+
+ /**
+ * Combine IV and encrypted data.
+ * @param iv initialisation vector
+ * @param encryptedData encrypted data
+ * @return combination of iv and encrypted data
+ */
+ private static byte[] getCombinedArray(byte[] iv, byte[] encryptedData) {
+ 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];
+ }
+ return combined;
+ }
}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_check.xml b/app/src/main/res/drawable/ic_check.xml
new file mode 100644
index 0000000..17aca2a
--- /dev/null
+++ b/app/src/main/res/drawable/ic_check.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_aes.xml b/app/src/main/res/layout/activity_aes.xml
deleted file mode 100644
index 798d209..0000000
--- a/app/src/main/res/layout/activity_aes.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_sync.xml b/app/src/main/res/layout/activity_sync.xml
index 7fff089..4bdcdfc 100644
--- a/app/src/main/res/layout/activity_sync.xml
+++ b/app/src/main/res/layout/activity_sync.xml
@@ -14,10 +14,22 @@
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
- app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
- app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
- app:layout_constraintLeft_toLeftOf="parent"/>
+ app:layout_constraintTop_toTopOf="parent"
+ app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
+
+
-
-
-
+ app:layout_constraintTop_toTopOf="parent" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_sync_options.xml b/app/src/main/res/layout/fragment_sync_options.xml
new file mode 100644
index 0000000..3b77564
--- /dev/null
+++ b/app/src/main/res/layout/fragment_sync_options.xml
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5ec10be..3370816 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -9,4 +9,7 @@
Save Automation Key
Home
Help
+
+ // Sync options preferences
+ Share events\nThis will generate a sync server on your instance