mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-20 14:49:53 +01:00
Recovery UI
This commit is contained in:
@@ -1,8 +1,9 @@
|
|||||||
package org.briarproject.briar.android.socialbackup;
|
package org.briarproject.briar.android.socialbackup;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.briar.api.socialbackup.Shard;
|
|
||||||
import org.briarproject.briar.api.socialbackup.DarkCrystal;
|
import org.briarproject.briar.api.socialbackup.DarkCrystal;
|
||||||
|
import org.briarproject.briar.api.socialbackup.Shard;
|
||||||
import org.magmacollective.darkcrystal.secretsharingwrapper.SecretSharingWrapper;
|
import org.magmacollective.darkcrystal.secretsharingwrapper.SecretSharingWrapper;
|
||||||
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
@@ -13,14 +14,12 @@ import java.util.Random;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import dagger.Provides;
|
|
||||||
|
|
||||||
import static org.briarproject.briar.socialbackup.SocialBackupConstants.SECRET_ID_BYTES;
|
import static org.briarproject.briar.socialbackup.SocialBackupConstants.SECRET_ID_BYTES;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class DarkCrystalImpl implements DarkCrystal {
|
public class DarkCrystalImpl implements DarkCrystal {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
DarkCrystalImpl() {
|
DarkCrystalImpl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +29,8 @@ public class DarkCrystalImpl implements DarkCrystal {
|
|||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
byte[] secretId = new byte[SECRET_ID_BYTES];
|
byte[] secretId = new byte[SECRET_ID_BYTES];
|
||||||
random.nextBytes(secretId);
|
random.nextBytes(secretId);
|
||||||
List<byte[]> shardsBytes = SecretSharingWrapper.share(secret.getBytes(), numShards, threshold);
|
List<byte[]> shardsBytes = SecretSharingWrapper
|
||||||
|
.share(secret.getBytes(), numShards, threshold);
|
||||||
List<Shard> shards = new ArrayList<>(numShards);
|
List<Shard> shards = new ArrayList<>(numShards);
|
||||||
for (byte[] shardBytes : shardsBytes) {
|
for (byte[] shardBytes : shardsBytes) {
|
||||||
shards.add(new Shard(secretId, shardBytes));
|
shards.add(new Shard(secretId, shardBytes));
|
||||||
@@ -44,9 +44,10 @@ public class DarkCrystalImpl implements DarkCrystal {
|
|||||||
// Check each shard has the same secret Id
|
// Check each shard has the same secret Id
|
||||||
byte[] secretId = shards.get(0).getSecretId();
|
byte[] secretId = shards.get(0).getSecretId();
|
||||||
for (Shard shard : shards) {
|
for (Shard shard : shards) {
|
||||||
if (!Arrays.equals(shard.getSecretId(), secretId)) throw new GeneralSecurityException();
|
if (!Arrays.equals(shard.getSecretId(), secretId))
|
||||||
|
throw new GeneralSecurityException();
|
||||||
}
|
}
|
||||||
List<byte[]> shardsBytes = new ArrayList<>(shards.size());
|
List<byte[]> shardsBytes = new ArrayList<>(shards.size());
|
||||||
for (Shard shard : shards) {
|
for (Shard shard : shards) {
|
||||||
shardsBytes.add(shard.getShard());
|
shardsBytes.add(shard.getShard());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.briarproject.briar.android.activity.BriarActivity;
|
|||||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
import org.briarproject.briar.api.socialbackup.recovery.CustodianTask;
|
import org.briarproject.briar.api.socialbackup.recovery.CustodianTask;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -53,6 +54,11 @@ public class CustodianReturnShardActivity extends BriarActivity
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
viewModel.start(contactId);
|
viewModel.start(contactId);
|
||||||
|
} catch (IOException e) {
|
||||||
|
// TODO improve this
|
||||||
|
Toast.makeText(this,
|
||||||
|
"It looks like you are not connected to a Wifi network",
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
Toast.makeText(this,
|
Toast.makeText(this,
|
||||||
"You do not hold a backup piece for this contact",
|
"You do not hold a backup piece for this contact",
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package org.briarproject.briar.android.socialbackup.recover;
|
package org.briarproject.briar.android.socialbackup.recover;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.net.wifi.WifiInfo;
|
||||||
|
import android.net.wifi.WifiManager;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
@@ -17,6 +19,9 @@ import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
|
|||||||
import org.briarproject.briar.api.socialbackup.SocialBackupManager;
|
import org.briarproject.briar.api.socialbackup.SocialBackupManager;
|
||||||
import org.briarproject.briar.api.socialbackup.recovery.CustodianTask;
|
import org.briarproject.briar.api.socialbackup.recovery.CustodianTask;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -29,8 +34,8 @@ import androidx.lifecycle.AndroidViewModel;
|
|||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import static android.content.Context.WIFI_SERVICE;
|
||||||
import static android.widget.Toast.LENGTH_LONG;
|
import static android.widget.Toast.LENGTH_LONG;
|
||||||
import static java.util.Objects.requireNonNull;
|
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
@@ -48,6 +53,7 @@ public class CustodianReturnShardViewModel extends AndroidViewModel
|
|||||||
final QrCodeDecoder qrCodeDecoder;
|
final QrCodeDecoder qrCodeDecoder;
|
||||||
private boolean wasContinueClicked = false;
|
private boolean wasContinueClicked = false;
|
||||||
private boolean qrCodeRead = false;
|
private boolean qrCodeRead = false;
|
||||||
|
private WifiManager wifiManager;
|
||||||
private final MutableLiveEvent<Boolean> showCameraFragment =
|
private final MutableLiveEvent<Boolean> showCameraFragment =
|
||||||
new MutableLiveEvent<>();
|
new MutableLiveEvent<>();
|
||||||
private final MutableLiveEvent<Boolean> successDismissed =
|
private final MutableLiveEvent<Boolean> successDismissed =
|
||||||
@@ -62,13 +68,13 @@ public class CustodianReturnShardViewModel extends AndroidViewModel
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CustodianReturnShardViewModel(
|
public CustodianReturnShardViewModel(
|
||||||
@NonNull Application application,
|
@NonNull Application app,
|
||||||
@IoExecutor Executor ioExecutor,
|
@IoExecutor Executor ioExecutor,
|
||||||
SocialBackupManager socialBackupManager,
|
SocialBackupManager socialBackupManager,
|
||||||
DatabaseComponent db,
|
DatabaseComponent db,
|
||||||
CustodianTask task,
|
CustodianTask task,
|
||||||
AndroidExecutor androidExecutor) {
|
AndroidExecutor androidExecutor) {
|
||||||
super(application);
|
super(app);
|
||||||
|
|
||||||
this.androidExecutor = androidExecutor;
|
this.androidExecutor = androidExecutor;
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
@@ -76,19 +82,50 @@ public class CustodianReturnShardViewModel extends AndroidViewModel
|
|||||||
this.db = db;
|
this.db = db;
|
||||||
this.task = task;
|
this.task = task;
|
||||||
qrCodeDecoder = new QrCodeDecoder(androidExecutor, ioExecutor, this);
|
qrCodeDecoder = new QrCodeDecoder(androidExecutor, ioExecutor, this);
|
||||||
|
wifiManager = (WifiManager) app.getSystemService(WIFI_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(ContactId contactId) throws DbException {
|
private InetAddress getWifiIpv4Address() {
|
||||||
db.transaction(false, txn -> {
|
if (wifiManager == null) return null;
|
||||||
if (!socialBackupManager.amCustodian(txn, contactId)) {
|
// If we're connected to a wifi network, return its address
|
||||||
throw new DbException();
|
WifiInfo info = wifiManager.getConnectionInfo();
|
||||||
}
|
if (info != null && info.getIpAddress() != 0) {
|
||||||
returnShardPayloadBytes = socialBackupManager
|
return intToInetAddress(info.getIpAddress());
|
||||||
.getReturnShardPayloadBytes(txn, contactId);
|
}
|
||||||
});
|
return null;
|
||||||
task.cancel();
|
}
|
||||||
task.start(this, returnShardPayloadBytes);
|
|
||||||
}
|
// TODO this is not the right place for this
|
||||||
|
private InetAddress intToInetAddress(int ip) {
|
||||||
|
byte[] ipBytes = new byte[4];
|
||||||
|
ipBytes[0] = (byte) (ip & 0xFF);
|
||||||
|
ipBytes[1] = (byte) ((ip >> 8) & 0xFF);
|
||||||
|
ipBytes[2] = (byte) ((ip >> 16) & 0xFF);
|
||||||
|
ipBytes[3] = (byte) ((ip >> 24) & 0xFF);
|
||||||
|
try {
|
||||||
|
return InetAddress.getByAddress(ipBytes);
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
// Should only be thrown if address has illegal length
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start(ContactId contactId) throws DbException, IOException {
|
||||||
|
InetAddress inetAddress = getWifiIpv4Address();
|
||||||
|
LOG.info("Client InetAddress: " + inetAddress);
|
||||||
|
if (inetAddress == null)
|
||||||
|
throw new IOException("Cannot get IP on local wifi");
|
||||||
|
|
||||||
|
db.transaction(false, txn -> {
|
||||||
|
if (!socialBackupManager.amCustodian(txn, contactId)) {
|
||||||
|
throw new DbException();
|
||||||
|
}
|
||||||
|
returnShardPayloadBytes = socialBackupManager
|
||||||
|
.getReturnShardPayloadBytes(txn, contactId);
|
||||||
|
});
|
||||||
|
task.cancel();
|
||||||
|
task.start(this, returnShardPayloadBytes);
|
||||||
|
}
|
||||||
|
|
||||||
@IoExecutor
|
@IoExecutor
|
||||||
@Override
|
@Override
|
||||||
@@ -121,7 +158,7 @@ public class CustodianReturnShardViewModel extends AndroidViewModel
|
|||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public void onSuccessDismissed() {
|
public void onSuccessDismissed() {
|
||||||
successDismissed.setEvent(true);
|
successDismissed.setEvent(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -136,6 +173,7 @@ public class CustodianReturnShardViewModel extends AndroidViewModel
|
|||||||
LiveEvent<Boolean> getSuccessDismissed() {
|
LiveEvent<Boolean> getSuccessDismissed() {
|
||||||
return successDismissed;
|
return successDismissed;
|
||||||
}
|
}
|
||||||
|
|
||||||
LiveData<CustodianTask.State> getState() {
|
LiveData<CustodianTask.State> getState() {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@@ -144,8 +182,8 @@ public class CustodianReturnShardViewModel extends AndroidViewModel
|
|||||||
public void onStateChanged(CustodianTask.State state) {
|
public void onStateChanged(CustodianTask.State state) {
|
||||||
this.state.postValue(state);
|
this.state.postValue(state);
|
||||||
// Connecting, SendingShard, ReceivingAck, Success, Failure
|
// Connecting, SendingShard, ReceivingAck, Success, Failure
|
||||||
if (state instanceof CustodianTask.State.SendingShard) {
|
if (state instanceof CustodianTask.State.SendingShard) {
|
||||||
qrCodeRead = true;
|
qrCodeRead = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,10 @@ public class OwnerReturnShardActivity extends BaseActivity
|
|||||||
showInitialFragment(new OwnerRecoveryModeExplainerFragment());
|
showInitialFragment(new OwnerRecoveryModeExplainerFragment());
|
||||||
}
|
}
|
||||||
viewModel.getShowQrCodeFragment().observeEvent(this, show -> {
|
viewModel.getShowQrCodeFragment().observeEvent(this, show -> {
|
||||||
if (show) showQrCodeFragment();
|
if (show) {
|
||||||
|
viewModel.startListening();
|
||||||
|
showQrCodeFragment();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
viewModel.getStartClicked().observeEvent(this, start -> {
|
viewModel.getStartClicked().observeEvent(this, start -> {
|
||||||
if (start) {
|
if (start) {
|
||||||
@@ -132,6 +135,10 @@ public class OwnerReturnShardActivity extends BaseActivity
|
|||||||
Toast.makeText(this,
|
Toast.makeText(this,
|
||||||
"Success - got shard" + (added ? "" : " duplicate"),
|
"Success - got shard" + (added ? "" : " duplicate"),
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
|
if (added && viewModel.canRecover()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
onBackPressed();
|
||||||
// finish();
|
// finish();
|
||||||
} else if (state instanceof SecretOwnerTask.State.Failure) {
|
} else if (state instanceof SecretOwnerTask.State.Failure) {
|
||||||
// TODO error screen, handle reason
|
// TODO error screen, handle reason
|
||||||
|
|||||||
@@ -6,18 +6,22 @@ import android.net.wifi.WifiInfo;
|
|||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||||
import org.briarproject.briar.android.contact.add.nearby.QrCodeUtils;
|
import org.briarproject.briar.android.contact.add.nearby.QrCodeUtils;
|
||||||
import org.briarproject.briar.android.viewmodel.LiveEvent;
|
import org.briarproject.briar.android.viewmodel.LiveEvent;
|
||||||
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
|
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
|
||||||
|
import org.briarproject.briar.api.socialbackup.DarkCrystal;
|
||||||
import org.briarproject.briar.api.socialbackup.ReturnShardPayload;
|
import org.briarproject.briar.api.socialbackup.ReturnShardPayload;
|
||||||
|
import org.briarproject.briar.api.socialbackup.Shard;
|
||||||
import org.briarproject.briar.api.socialbackup.recovery.SecretOwnerTask;
|
import org.briarproject.briar.api.socialbackup.recovery.SecretOwnerTask;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -48,6 +52,7 @@ class OwnerReturnShardViewModel extends AndroidViewModel
|
|||||||
private final AndroidExecutor androidExecutor;
|
private final AndroidExecutor androidExecutor;
|
||||||
private final Executor ioExecutor;
|
private final Executor ioExecutor;
|
||||||
private final SecretOwnerTask task;
|
private final SecretOwnerTask task;
|
||||||
|
private final DarkCrystal darkCrystal;
|
||||||
|
|
||||||
private final MutableLiveEvent<Boolean> showQrCodeFragment =
|
private final MutableLiveEvent<Boolean> showQrCodeFragment =
|
||||||
new MutableLiveEvent<>();
|
new MutableLiveEvent<>();
|
||||||
@@ -65,15 +70,16 @@ class OwnerReturnShardViewModel extends AndroidViewModel
|
|||||||
OwnerReturnShardViewModel(Application app,
|
OwnerReturnShardViewModel(Application app,
|
||||||
AndroidExecutor androidExecutor,
|
AndroidExecutor androidExecutor,
|
||||||
SecretOwnerTask task,
|
SecretOwnerTask task,
|
||||||
|
DarkCrystal darkCrystal,
|
||||||
@IoExecutor Executor ioExecutor) {
|
@IoExecutor Executor ioExecutor) {
|
||||||
super(app);
|
super(app);
|
||||||
this.androidExecutor = androidExecutor;
|
this.androidExecutor = androidExecutor;
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
|
this.darkCrystal = darkCrystal;
|
||||||
this.task = task;
|
this.task = task;
|
||||||
wifiManager = (WifiManager) app.getSystemService(WIFI_SERVICE);
|
wifiManager = (WifiManager) app.getSystemService(WIFI_SERVICE);
|
||||||
|
|
||||||
// IntentFilter filter = new IntentFilter(ACTION_SCAN_MODE_CHANGED);
|
// IntentFilter filter = new IntentFilter(ACTION_SCAN_MODE_CHANGED);
|
||||||
startListening();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private InetAddress getWifiIpv4Address() {
|
private InetAddress getWifiIpv4Address() {
|
||||||
@@ -86,6 +92,7 @@ class OwnerReturnShardViewModel extends AndroidViewModel
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO this is not the right place for this
|
||||||
private InetAddress intToInetAddress(int ip) {
|
private InetAddress intToInetAddress(int ip) {
|
||||||
byte[] ipBytes = new byte[4];
|
byte[] ipBytes = new byte[4];
|
||||||
ipBytes[0] = (byte) (ip & 0xFF);
|
ipBytes[0] = (byte) (ip & 0xFF);
|
||||||
@@ -128,7 +135,7 @@ class OwnerReturnShardViewModel extends AndroidViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private void startListening() {
|
public void startListening() {
|
||||||
ioExecutor.execute(() -> {
|
ioExecutor.execute(() -> {
|
||||||
task.cancel();
|
task.cancel();
|
||||||
// wait until really cancelled
|
// wait until really cancelled
|
||||||
@@ -188,7 +195,6 @@ class OwnerReturnShardViewModel extends AndroidViewModel
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStateChanged(SecretOwnerTask.State state) {
|
public void onStateChanged(SecretOwnerTask.State state) {
|
||||||
this.state.postValue(state);
|
|
||||||
if (state instanceof SecretOwnerTask.State.Listening) {
|
if (state instanceof SecretOwnerTask.State.Listening) {
|
||||||
DisplayMetrics dm =
|
DisplayMetrics dm =
|
||||||
getApplication().getResources().getDisplayMetrics();
|
getApplication().getResources().getDisplayMetrics();
|
||||||
@@ -196,13 +202,16 @@ class OwnerReturnShardViewModel extends AndroidViewModel
|
|||||||
byte[] payloadBytes = ((SecretOwnerTask.State.Listening) state)
|
byte[] payloadBytes = ((SecretOwnerTask.State.Listening) state)
|
||||||
.getLocalPayload();
|
.getLocalPayload();
|
||||||
if (LOG.isLoggable(INFO)) {
|
if (LOG.isLoggable(INFO)) {
|
||||||
LOG.info("Local payload is " + payloadBytes.length
|
LOG.info("Local QR code payload is " + payloadBytes.length
|
||||||
+ " bytes");
|
+ " bytes");
|
||||||
}
|
}
|
||||||
// Use ISO 8859-1 to encode bytes directly as a string
|
// Use ISO 8859-1 to encode bytes directly as a string
|
||||||
String content = new String(payloadBytes, ISO_8859_1);
|
String content = new String(payloadBytes, ISO_8859_1);
|
||||||
qrCodeBitmap = QrCodeUtils.createQrCode(dm, content);
|
qrCodeBitmap = QrCodeUtils.createQrCode(dm, content);
|
||||||
|
this.state.postValue(state);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
this.state.postValue(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +229,20 @@ class OwnerReturnShardViewModel extends AndroidViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean canRecover() {
|
public boolean canRecover() {
|
||||||
// TODO
|
ArrayList<Shard> shards = new ArrayList();
|
||||||
return false;
|
for (ReturnShardPayload returnShardPayload : recoveredShards) {
|
||||||
|
// TODO check shards all have same secret id
|
||||||
|
shards.add(returnShardPayload.getShard());
|
||||||
|
}
|
||||||
|
SecretKey secretKey;
|
||||||
|
try {
|
||||||
|
secretKey = darkCrystal.combineShards(shards);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
// TODO handle error message
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// TODO find backup with highest version number
|
||||||
|
// recoveredShards.get(0).getBackupPayload();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user