Merge branch '2167-decode-qr-code-for-pairing-with-mailbox' into 'master'

Create initial MailboxPairViewModel that decodes QR code

Closes #2167

See merge request briar/briar!1544
This commit is contained in:
akwizgran
2021-11-16 12:15:26 +00:00
19 changed files with 191 additions and 44 deletions

View File

@@ -3,6 +3,7 @@ package org.briarproject.bramble.plugin.tor;
import android.app.Application; import android.app.Application;
import org.briarproject.bramble.api.battery.BatteryManager; import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
@@ -60,6 +61,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
private final File torDirectory; private final File torDirectory;
private int torSocksPort; private int torSocksPort;
private int torControlPort; private int torControlPort;
private final CryptoComponent crypto;
@Inject @Inject
AndroidTorPluginFactory(@IoExecutor Executor ioExecutor, AndroidTorPluginFactory(@IoExecutor Executor ioExecutor,
@@ -77,7 +79,8 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
Clock clock, Clock clock,
@TorDirectory File torDirectory, @TorDirectory File torDirectory,
@TorSocksPort int torSocksPort, @TorSocksPort int torSocksPort,
@TorControlPort int torControlPort) { @TorControlPort int torControlPort,
CryptoComponent crypto) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.wakefulIoExecutor = wakefulIoExecutor; this.wakefulIoExecutor = wakefulIoExecutor;
this.app = app; this.app = app;
@@ -94,6 +97,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
this.torDirectory = torDirectory; this.torDirectory = torDirectory;
this.torSocksPort = torSocksPort; this.torSocksPort = torSocksPort;
this.torControlPort = torControlPort; this.torControlPort = torControlPort;
this.crypto = crypto;
} }
@Override @Override
@@ -135,7 +139,8 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorRendezvousCrypto torRendezvousCrypto = new TorRendezvousCryptoImpl(); TorRendezvousCrypto torRendezvousCrypto =
new TorRendezvousCryptoImpl(crypto);
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor,
wakefulIoExecutor, app, networkManager, locationUtils, wakefulIoExecutor, app, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider, torSocketFactory, clock, resourceProvider,

View File

@@ -170,4 +170,11 @@ public interface CryptoComponent {
* length. The line terminator is CRLF. * length. The line terminator is CRLF.
*/ */
String asciiArmour(byte[] b, int lineLength); String asciiArmour(byte[] b, int lineLength);
/**
* Encode the onion/hidden service address given its public key. As
* specified here: https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt?id=29245fd5#n2135
*/
String encodeOnionAddress(byte[] publicKey);
} }

View File

@@ -7,6 +7,7 @@ import net.i2p.crypto.eddsa.KeyPairGenerator;
import org.bouncycastle.crypto.CryptoException; import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.Blake2bDigest; import org.bouncycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.digests.SHA3Digest;
import org.briarproject.bramble.api.crypto.AgreementPrivateKey; import org.briarproject.bramble.api.crypto.AgreementPrivateKey;
import org.briarproject.bramble.api.crypto.AgreementPublicKey; import org.briarproject.bramble.api.crypto.AgreementPublicKey;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
@@ -21,11 +22,13 @@ import org.briarproject.bramble.api.crypto.SignaturePrivateKey;
import org.briarproject.bramble.api.crypto.SignaturePublicKey; import org.briarproject.bramble.api.crypto.SignaturePublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.SecureRandomProvider; import org.briarproject.bramble.api.system.SecureRandomProvider;
import org.briarproject.bramble.util.Base32;
import org.briarproject.bramble.util.ByteUtils; import org.briarproject.bramble.util.ByteUtils;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.whispersystems.curve25519.Curve25519; import org.whispersystems.curve25519.Curve25519;
import org.whispersystems.curve25519.Curve25519KeyPair; import org.whispersystems.curve25519.Curve25519KeyPair;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.Provider; import java.security.Provider;
@@ -58,6 +61,8 @@ class CryptoComponentImpl implements CryptoComponent {
private static final int PBKDF_SALT_BYTES = 32; // 256 bits private static final int PBKDF_SALT_BYTES = 32; // 256 bits
private static final byte PBKDF_FORMAT_SCRYPT = 0; private static final byte PBKDF_FORMAT_SCRYPT = 0;
private static final byte PBKDF_FORMAT_SCRYPT_STRENGTHENED = 1; private static final byte PBKDF_FORMAT_SCRYPT_STRENGTHENED = 1;
private static final byte ONION_HS_PROTOCOL_VERSION = 3;
private static final int ONION_CHECKSUM_BYTES = 2;
private final SecureRandom secureRandom; private final SecureRandom secureRandom;
private final PasswordBasedKdf passwordBasedKdf; private final PasswordBasedKdf passwordBasedKdf;
@@ -442,4 +447,21 @@ class CryptoComponentImpl implements CryptoComponent {
public String asciiArmour(byte[] b, int lineLength) { public String asciiArmour(byte[] b, int lineLength) {
return AsciiArmour.wrap(b, lineLength); return AsciiArmour.wrap(b, lineLength);
} }
@Override
public String encodeOnionAddress(byte[] publicKey) {
Digest digest = new SHA3Digest(256);
byte[] label = ".onion checksum".getBytes(Charset.forName("US-ASCII"));
digest.update(label, 0, label.length);
digest.update(publicKey, 0, publicKey.length);
digest.update(ONION_HS_PROTOCOL_VERSION);
byte[] checksum = new byte[digest.getDigestSize()];
digest.doFinal(checksum, 0);
byte[] address = new byte[publicKey.length + ONION_CHECKSUM_BYTES + 1];
arraycopy(publicKey, 0, address, 0, publicKey.length);
arraycopy(checksum, 0, address, publicKey.length, ONION_CHECKSUM_BYTES);
address[address.length - 1] = ONION_HS_PROTOCOL_VERSION;
return Base32.encode(address).toLowerCase();
}
} }

View File

@@ -4,39 +4,26 @@ import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec; import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA3Digest;
import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Base64;
import org.briarproject.bramble.util.Base32; import org.briarproject.bramble.api.crypto.CryptoComponent;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import static java.lang.System.arraycopy; class TorRendezvousCryptoImpl implements TorRendezvousCrypto {
public class TorRendezvousCryptoImpl implements TorRendezvousCrypto {
private static final EdDSANamedCurveSpec CURVE_SPEC = private static final EdDSANamedCurveSpec CURVE_SPEC =
EdDSANamedCurveTable.getByName("Ed25519"); EdDSANamedCurveTable.getByName("Ed25519");
private static final byte HS_PROTOCOL_VERSION = 3; private final CryptoComponent crypto;
private static final int CHECKSUM_BYTES = 2;
TorRendezvousCryptoImpl(CryptoComponent crypto) {
this.crypto = crypto;
}
@Override @Override
public String getOnionAddress(byte[] seed) { public String getOnionAddress(byte[] seed) {
EdDSAPrivateKeySpec spec = new EdDSAPrivateKeySpec(seed, CURVE_SPEC); EdDSAPrivateKeySpec spec = new EdDSAPrivateKeySpec(seed, CURVE_SPEC);
byte[] publicKey = spec.getA().toByteArray(); return crypto.encodeOnionAddress(spec.getA().toByteArray());
Digest digest = new SHA3Digest(256);
byte[] label = ".onion checksum".getBytes(Charset.forName("US-ASCII"));
digest.update(label, 0, label.length);
digest.update(publicKey, 0, publicKey.length);
digest.update(HS_PROTOCOL_VERSION);
byte[] checksum = new byte[digest.getDigestSize()];
digest.doFinal(checksum, 0);
byte[] address = new byte[publicKey.length + CHECKSUM_BYTES + 1];
arraycopy(publicKey, 0, address, 0, publicKey.length);
arraycopy(checksum, 0, address, publicKey.length, CHECKSUM_BYTES);
address[address.length - 1] = HS_PROTOCOL_VERSION;
return Base32.encode(address).toLowerCase();
} }
@Override @Override

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.plugin.tor; package org.briarproject.bramble.plugin.tor;
import org.briarproject.bramble.api.battery.BatteryManager; import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
@@ -58,6 +59,7 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
private final File torDirectory; private final File torDirectory;
private int torSocksPort; private int torSocksPort;
private int torControlPort; private int torControlPort;
private final CryptoComponent crypto;
@Inject @Inject
UnixTorPluginFactory(@IoExecutor Executor ioExecutor, UnixTorPluginFactory(@IoExecutor Executor ioExecutor,
@@ -73,7 +75,8 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
Clock clock, Clock clock,
@TorDirectory File torDirectory, @TorDirectory File torDirectory,
@TorSocksPort int torSocksPort, @TorSocksPort int torSocksPort,
@TorControlPort int torControlPort) { @TorControlPort int torControlPort,
CryptoComponent crypto) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.wakefulIoExecutor = wakefulIoExecutor; this.wakefulIoExecutor = wakefulIoExecutor;
this.networkManager = networkManager; this.networkManager = networkManager;
@@ -88,6 +91,7 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
this.torDirectory = torDirectory; this.torDirectory = torDirectory;
this.torSocksPort = torSocksPort; this.torSocksPort = torSocksPort;
this.torControlPort = torControlPort; this.torControlPort = torControlPort;
this.crypto = crypto;
} }
@Override @Override
@@ -128,7 +132,8 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorRendezvousCrypto torRendezvousCrypto = new TorRendezvousCryptoImpl(); TorRendezvousCrypto torRendezvousCrypto =
new TorRendezvousCryptoImpl(crypto);
UnixTorPlugin plugin = new UnixTorPlugin(ioExecutor, wakefulIoExecutor, UnixTorPlugin plugin = new UnixTorPlugin(ioExecutor, wakefulIoExecutor,
networkManager, locationUtils, torSocketFactory, clock, networkManager, locationUtils, torSocketFactory, clock,
resourceProvider, circumventionProvider, batteryManager, resourceProvider, circumventionProvider, batteryManager,

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.plugin.tor;
import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons; import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
import org.briarproject.bramble.api.battery.BatteryManager; import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
@@ -88,6 +89,8 @@ public class BridgeTest extends BrambleTestCase {
BackoffFactory backoffFactory; BackoffFactory backoffFactory;
@Inject @Inject
Clock clock; Clock clock;
@Inject
CryptoComponent crypto;
private final File torDir = getTestDirectory(); private final File torDir = getTestDirectory();
private final String bridge; private final String bridge;
@@ -142,7 +145,7 @@ public class BridgeTest extends BrambleTestCase {
networkManager, locationUtils, eventBus, torSocketFactory, networkManager, locationUtils, eventBus, torSocketFactory,
backoffFactory, resourceProvider, bridgeProvider, backoffFactory, resourceProvider, bridgeProvider,
batteryManager, clock, torDir, DEFAULT_SOCKS_PORT, batteryManager, clock, torDir, DEFAULT_SOCKS_PORT,
DEFAULT_CONTROL_PORT); DEFAULT_CONTROL_PORT, crypto);
} }
@After @After

View File

@@ -43,6 +43,7 @@ import org.briarproject.briar.android.hotspot.HotspotModule;
import org.briarproject.briar.android.introduction.IntroductionModule; import org.briarproject.briar.android.introduction.IntroductionModule;
import org.briarproject.briar.android.logging.LoggingModule; import org.briarproject.briar.android.logging.LoggingModule;
import org.briarproject.briar.android.login.LoginModule; import org.briarproject.briar.android.login.LoginModule;
import org.briarproject.briar.android.mailbox.MailboxModule;
import org.briarproject.briar.android.navdrawer.NavDrawerModule; import org.briarproject.briar.android.navdrawer.NavDrawerModule;
import org.briarproject.briar.android.privategroup.conversation.GroupConversationModule; import org.briarproject.briar.android.privategroup.conversation.GroupConversationModule;
import org.briarproject.briar.android.privategroup.list.GroupListModule; import org.briarproject.briar.android.privategroup.list.GroupListModule;
@@ -103,6 +104,7 @@ import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
SharingModule.class, SharingModule.class,
HotspotModule.class, HotspotModule.class,
TransferDataModule.class, TransferDataModule.class,
MailboxModule.class,
}) })
public class AppModule { public class AppModule {

View File

@@ -20,6 +20,8 @@ import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgre
import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementWaiting; import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementWaiting;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.QrCodeScanned; import org.briarproject.briar.android.contact.add.nearby.AddContactState.QrCodeScanned;
import org.briarproject.briar.android.fragment.BaseFragment; import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.qrcode.CameraException;
import org.briarproject.briar.android.qrcode.CameraView;
import org.briarproject.briar.android.view.QrCodeView; import org.briarproject.briar.android.view.QrCodeView;
import java.util.logging.Logger; import java.util.logging.Logger;

View File

@@ -53,7 +53,8 @@ import org.briarproject.briar.android.contact.add.nearby.AddContactState.Contact
import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementListening; import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementListening;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementStarted; import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementStarted;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementWaiting; import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementWaiting;
import org.briarproject.briar.android.util.QrCodeUtils; import org.briarproject.briar.android.qrcode.QrCodeDecoder;
import org.briarproject.briar.android.qrcode.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;

View File

@@ -24,7 +24,7 @@ import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.hotspot.HotspotState.NetworkConfig; import org.briarproject.briar.android.hotspot.HotspotState.NetworkConfig;
import org.briarproject.briar.android.util.QrCodeUtils; import org.briarproject.briar.android.qrcode.QrCodeUtils;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -52,7 +52,7 @@ 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;
import static org.briarproject.briar.android.util.QrCodeUtils.HOTSPOT_QRCODE_FACTOR; import static org.briarproject.briar.android.qrcode.QrCodeUtils.HOTSPOT_QRCODE_FACTOR;
import static org.briarproject.briar.android.util.UiUtils.handleException; import static org.briarproject.briar.android.util.UiUtils.handleException;
@MethodsNotNullByDefault @MethodsNotNullByDefault

View File

@@ -8,7 +8,7 @@ import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.android.hotspot.HotspotState.WebsiteConfig; import org.briarproject.briar.android.hotspot.HotspotState.WebsiteConfig;
import org.briarproject.briar.android.util.QrCodeUtils; import org.briarproject.briar.android.qrcode.QrCodeUtils;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
@@ -27,7 +27,7 @@ import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.NetworkUtils.getNetworkInterfaces; import static org.briarproject.bramble.util.NetworkUtils.getNetworkInterfaces;
import static org.briarproject.briar.android.hotspot.WebServer.PORT; import static org.briarproject.briar.android.hotspot.WebServer.PORT;
import static org.briarproject.briar.android.util.QrCodeUtils.HOTSPOT_QRCODE_FACTOR; import static org.briarproject.briar.android.qrcode.QrCodeUtils.HOTSPOT_QRCODE_FACTOR;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault

View File

@@ -0,0 +1,19 @@
package org.briarproject.briar.android.mailbox;
import org.briarproject.briar.android.viewmodel.ViewModelKey;
import androidx.lifecycle.ViewModel;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoMap;
@Module
public interface MailboxModule {
@Binds
@IntoMap
@ViewModelKey(MailboxPairViewModel.class)
ViewModel bindMailboxViewModel(
MailboxPairViewModel mailboxPairViewModel);
}

View File

@@ -0,0 +1,95 @@
package org.briarproject.briar.android.mailbox;
import android.app.Application;
import com.google.zxing.Result;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.TransactionManager;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.android.qrcode.QrCodeDecoder;
import org.briarproject.briar.android.viewmodel.DbViewModel;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.inject.Inject;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
@UiThread
@NotNullByDefault
class MailboxPairViewModel extends DbViewModel
implements QrCodeDecoder.ResultCallback {
private static final Logger LOG =
getLogger(MailboxPairViewModel.class.getName());
private static final int VERSION_REQUIRED = 32;
@SuppressWarnings("CharsetObjectCanBeUsed") // Requires minSdkVersion >= 19
private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
private final CryptoComponent crypto;
private final QrCodeDecoder qrCodeDecoder;
@Nullable
private String onionAddress = null;
@Nullable
private String setupToken = null;
@Inject
MailboxPairViewModel(
Application app,
@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager,
TransactionManager db,
AndroidExecutor androidExecutor,
@IoExecutor Executor ioExecutor,
CryptoComponent crypto) {
super(app, dbExecutor, lifecycleManager, db, androidExecutor);
this.crypto = crypto;
qrCodeDecoder = new QrCodeDecoder(androidExecutor, ioExecutor, this);
}
@Override
public void onQrCodeDecoded(Result result) {
LOG.info("Got result from decoder");
byte[] bytes = result.getText().getBytes(ISO_8859_1);
if (LOG.isLoggable(INFO))
LOG.info("QR code length in bytes: " + bytes.length);
if (bytes.length != 65) {
LOG.info("QR code has wrong length");
return;
}
if (LOG.isLoggable(INFO))
LOG.info("QR code version: " + bytes[0]);
if (bytes[0] != VERSION_REQUIRED) {
LOG.info("QR code has wrong version");
return;
}
byte[] onionPubKey = Arrays.copyOfRange(bytes, 1, 33);
onionAddress = crypto.encodeOnionAddress(onionPubKey);
setupToken = StringUtils.toHexString(Arrays.copyOfRange(bytes, 33, 65))
.toLowerCase();
LOG.info("QR code is valid");
}
QrCodeDecoder getQrCodeDecoder() {
return qrCodeDecoder;
}
}

View File

@@ -1,8 +1,8 @@
package org.briarproject.briar.android.contact.add.nearby; package org.briarproject.briar.android.qrcode;
import java.io.IOException; import java.io.IOException;
class CameraException extends IOException { public class CameraException extends IOException {
CameraException(String message) { CameraException(String message) {
super(message); super(message);

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.contact.add.nearby; package org.briarproject.briar.android.qrcode;
import android.content.Context; import android.content.Context;
import android.hardware.Camera; import android.hardware.Camera;

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.contact.add.nearby; package org.briarproject.briar.android.qrcode;
import android.hardware.Camera; import android.hardware.Camera;
@@ -7,7 +7,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import androidx.annotation.UiThread; import androidx.annotation.UiThread;
@NotNullByDefault @NotNullByDefault
interface PreviewConsumer { public interface PreviewConsumer {
@UiThread @UiThread
void start(Camera camera, int cameraIndex); void start(Camera camera, int cameraIndex);

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.contact.add.nearby; package org.briarproject.briar.android.qrcode;
import android.hardware.Camera; import android.hardware.Camera;
import android.hardware.Camera.CameraInfo; import android.hardware.Camera.CameraInfo;
@@ -32,7 +32,7 @@ import static java.util.logging.Logger.getLogger;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
class QrCodeDecoder implements PreviewConsumer, PreviewCallback { public class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
private static final Logger LOG = getLogger(QrCodeDecoder.class.getName()); private static final Logger LOG = getLogger(QrCodeDecoder.class.getName());
@@ -44,7 +44,7 @@ class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
private Camera camera = null; private Camera camera = null;
private int cameraIndex = 0; private int cameraIndex = 0;
QrCodeDecoder(AndroidExecutor androidExecutor, public QrCodeDecoder(AndroidExecutor androidExecutor,
@IoExecutor Executor ioExecutor, ResultCallback callback) { @IoExecutor Executor ioExecutor, ResultCallback callback) {
this.androidExecutor = androidExecutor; this.androidExecutor = androidExecutor;
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
@@ -127,7 +127,7 @@ class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
} }
@NotNullByDefault @NotNullByDefault
interface ResultCallback { public interface ResultCallback {
@IoExecutor @IoExecutor
void onQrCodeDecoded(Result result); void onQrCodeDecoded(Result result);
} }

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.util; package org.briarproject.briar.android.qrcode;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
@@ -23,11 +23,10 @@ import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault @NotNullByDefault
public class QrCodeUtils { public class QrCodeUtils {
public static final double HOTSPOT_QRCODE_FACTOR = 0.35;
private static final Logger LOG = getLogger(QrCodeUtils.class.getName()); private static final Logger LOG = getLogger(QrCodeUtils.class.getName());
public static final double HOTSPOT_QRCODE_FACTOR = 0.35;
@Nullable @Nullable
public static Bitmap createQrCode(DisplayMetrics dm, String input) { public static Bitmap createQrCode(DisplayMetrics dm, String input) {
return createQrCode(Math.min(dm.widthPixels, dm.heightPixels), input); return createQrCode(Math.min(dm.widthPixels, dm.heightPixels), input);

View File

@@ -5,7 +5,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:keepScreenOn="true"> android:keepScreenOn="true">
<org.briarproject.briar.android.contact.add.nearby.CameraView <org.briarproject.briar.android.qrcode.CameraView
android:id="@+id/camera_view" android:id="@+id/camera_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />