mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-20 14:49:53 +01:00
Factor out recognition of QR code format.
This commit is contained in:
@@ -1,18 +1,26 @@
|
|||||||
package org.briarproject.bramble.api.keyagreement;
|
package org.briarproject.bramble.api.keyagreement;
|
||||||
|
|
||||||
public interface KeyAgreementConstants {
|
import org.briarproject.bramble.api.mailbox.MailboxConstants;
|
||||||
|
|
||||||
/**
|
public interface KeyAgreementConstants {
|
||||||
* The version of the BQP protocol used in beta releases. This version
|
|
||||||
* number is reserved.
|
|
||||||
*/
|
|
||||||
byte BETA_PROTOCOL_VERSION = 89;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current version of the BQP protocol.
|
* The current version of the BQP protocol.
|
||||||
*/
|
*/
|
||||||
byte PROTOCOL_VERSION = 4;
|
byte PROTOCOL_VERSION = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The QR code format identifier, used to distinguish BQP QR codes from
|
||||||
|
* QR codes used for other purposes. See
|
||||||
|
* {@link MailboxConstants#QR_FORMAT_ID}.
|
||||||
|
*/
|
||||||
|
byte QR_FORMAT_ID = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The QR code format version.
|
||||||
|
*/
|
||||||
|
byte QR_FORMAT_VERSION = PROTOCOL_VERSION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The length of the BQP key commitment in bytes.
|
* The length of the BQP key commitment in bytes.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -7,5 +7,5 @@ import java.io.IOException;
|
|||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public interface PayloadParser {
|
public interface PayloadParser {
|
||||||
|
|
||||||
Payload parse(byte[] raw) throws IOException;
|
Payload parse(String payload) throws IOException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.bramble.api.mailbox;
|
package org.briarproject.bramble.api.mailbox;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.keyagreement.KeyAgreementConstants;
|
||||||
import org.briarproject.bramble.api.plugin.TransportId;
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -19,6 +20,18 @@ public interface MailboxConstants {
|
|||||||
*/
|
*/
|
||||||
TransportId ID = new TransportId("org.briarproject.bramble.mailbox");
|
TransportId ID = new TransportId("org.briarproject.bramble.mailbox");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The QR code format identifier, used to distinguish mailbox QR codes
|
||||||
|
* from QR codes used for other purposes. See
|
||||||
|
* {@link KeyAgreementConstants#QR_FORMAT_ID};
|
||||||
|
*/
|
||||||
|
byte QR_FORMAT_ID = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The QR code format version.
|
||||||
|
*/
|
||||||
|
byte QR_FORMAT_VERSION = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mailbox API versions that we support as a client. This is reported to our
|
* Mailbox API versions that we support as a client. This is reported to our
|
||||||
* contacts by {@link MailboxUpdateManager}.
|
* contacts by {@link MailboxUpdateManager}.
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.briarproject.bramble.api.mailbox;
|
package org.briarproject.bramble.api.mailbox;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType;
|
||||||
|
|
||||||
public abstract class MailboxPairingState {
|
public abstract class MailboxPairingState {
|
||||||
|
|
||||||
public abstract static class Pending extends MailboxPairingState {
|
public abstract static class Pending extends MailboxPairingState {
|
||||||
@@ -29,6 +31,14 @@ public abstract class MailboxPairingState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class InvalidQrCode extends MailboxPairingState {
|
public static class InvalidQrCode extends MailboxPairingState {
|
||||||
|
|
||||||
|
public final QrCodeType qrCodeType;
|
||||||
|
public final int formatVersion;
|
||||||
|
|
||||||
|
public InvalidQrCode(QrCodeType qrCodeType, int formatVersion) {
|
||||||
|
this.qrCodeType = qrCodeType;
|
||||||
|
this.formatVersion = formatVersion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MailboxAlreadyPaired extends MailboxPairingState {
|
public static class MailboxAlreadyPaired extends MailboxPairingState {
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package org.briarproject.bramble.api.qrcode;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.Pair;
|
||||||
|
import org.briarproject.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
public interface QrCodeClassifier {
|
||||||
|
|
||||||
|
enum QrCodeType {
|
||||||
|
BQP,
|
||||||
|
MAILBOX,
|
||||||
|
UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair<QrCodeType, Integer> classifyQrCode(String payload);
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ package org.briarproject.bramble.util;
|
|||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.FormatException;
|
||||||
import org.briarproject.nullsafety.NotNullByDefault;
|
import org.briarproject.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.CharacterCodingException;
|
import java.nio.charset.CharacterCodingException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
@@ -17,13 +16,18 @@ import javax.annotation.Nullable;
|
|||||||
import static java.nio.charset.CodingErrorAction.IGNORE;
|
import static java.nio.charset.CodingErrorAction.IGNORE;
|
||||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||||
|
|
||||||
|
@SuppressWarnings("CharsetObjectCanBeUsed")
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class StringUtils {
|
public class StringUtils {
|
||||||
|
|
||||||
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
public static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||||
private static Pattern MAC = Pattern.compile("[0-9a-f]{2}:[0-9a-f]{2}:" +
|
public static final Charset US_ASCII = Charset.forName("US-ASCII");
|
||||||
"[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}",
|
public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
|
||||||
CASE_INSENSITIVE);
|
|
||||||
|
private static final Pattern MAC =
|
||||||
|
Pattern.compile("[0-9a-f]{2}:[0-9a-f]{2}:" +
|
||||||
|
"[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}",
|
||||||
|
CASE_INSENSITIVE);
|
||||||
|
|
||||||
private static final char[] HEX = new char[] {
|
private static final char[] HEX = new char[] {
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
@@ -45,11 +49,7 @@ public class StringUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] toUtf8(String s) {
|
public static byte[] toUtf8(String s) {
|
||||||
try {
|
return s.getBytes(UTF_8);
|
||||||
return s.getBytes("UTF-8");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String fromUtf8(byte[] bytes) {
|
public static String fromUtf8(byte[] bytes) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import org.briarproject.bramble.lifecycle.LifecycleModule;
|
|||||||
import org.briarproject.bramble.mailbox.MailboxModule;
|
import org.briarproject.bramble.mailbox.MailboxModule;
|
||||||
import org.briarproject.bramble.plugin.PluginModule;
|
import org.briarproject.bramble.plugin.PluginModule;
|
||||||
import org.briarproject.bramble.properties.PropertiesModule;
|
import org.briarproject.bramble.properties.PropertiesModule;
|
||||||
|
import org.briarproject.bramble.qrcode.QrCodeModule;
|
||||||
import org.briarproject.bramble.record.RecordModule;
|
import org.briarproject.bramble.record.RecordModule;
|
||||||
import org.briarproject.bramble.reliability.ReliabilityModule;
|
import org.briarproject.bramble.reliability.ReliabilityModule;
|
||||||
import org.briarproject.bramble.rendezvous.RendezvousModule;
|
import org.briarproject.bramble.rendezvous.RendezvousModule;
|
||||||
@@ -47,6 +48,7 @@ import dagger.Module;
|
|||||||
MailboxModule.class,
|
MailboxModule.class,
|
||||||
PluginModule.class,
|
PluginModule.class,
|
||||||
PropertiesModule.class,
|
PropertiesModule.class,
|
||||||
|
QrCodeModule.class,
|
||||||
RecordModule.class,
|
RecordModule.class,
|
||||||
ReliabilityModule.class,
|
ReliabilityModule.class,
|
||||||
RendezvousModule.class,
|
RendezvousModule.class,
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import java.io.FileInputStream;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -29,6 +28,7 @@ import javax.inject.Inject;
|
|||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.api.crypto.DecryptionResult.INVALID_CIPHERTEXT;
|
import static org.briarproject.bramble.api.crypto.DecryptionResult.INVALID_CIPHERTEXT;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.UTF_8;
|
||||||
import static org.briarproject.bramble.util.StringUtils.fromHexString;
|
import static org.briarproject.bramble.util.StringUtils.fromHexString;
|
||||||
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ class AccountManagerImpl implements AccountManager {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||||
new FileInputStream(f), Charset.forName("UTF-8")));
|
new FileInputStream(f), UTF_8));
|
||||||
String key = reader.readLine();
|
String key = reader.readLine();
|
||||||
reader.close();
|
reader.close();
|
||||||
return key;
|
return key;
|
||||||
@@ -151,7 +151,7 @@ class AccountManagerImpl implements AccountManager {
|
|||||||
@GuardedBy("stateChangeLock")
|
@GuardedBy("stateChangeLock")
|
||||||
private void writeDbKeyToFile(String key, File f) throws IOException {
|
private void writeDbKeyToFile(String key, File f) throws IOException {
|
||||||
FileOutputStream out = new FileOutputStream(f);
|
FileOutputStream out = new FileOutputStream(f);
|
||||||
out.write(key.getBytes(Charset.forName("UTF-8")));
|
out.write(key.getBytes(UTF_8));
|
||||||
out.flush();
|
out.flush();
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import org.briarproject.nullsafety.NotNullByDefault;
|
|||||||
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;
|
||||||
@@ -51,6 +50,7 @@ import static org.briarproject.bramble.api.crypto.DecryptionResult.KEY_STRENGTHE
|
|||||||
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
|
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
import static org.briarproject.bramble.util.LogUtils.now;
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.US_ASCII;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class CryptoComponentImpl implements CryptoComponent {
|
class CryptoComponentImpl implements CryptoComponent {
|
||||||
@@ -460,7 +460,7 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
@Override
|
@Override
|
||||||
public String encodeOnion(byte[] publicKey) {
|
public String encodeOnion(byte[] publicKey) {
|
||||||
Digest digest = new SHA3Digest(256);
|
Digest digest = new SHA3Digest(256);
|
||||||
byte[] label = ".onion checksum".getBytes(Charset.forName("US-ASCII"));
|
byte[] label = ".onion checksum".getBytes(US_ASCII);
|
||||||
digest.update(label, 0, label.length);
|
digest.update(label, 0, label.length);
|
||||||
digest.update(publicKey, 0, publicKey.length);
|
digest.update(publicKey, 0, publicKey.length);
|
||||||
digest.update(ONION_HS_PROTOCOL_VERSION);
|
digest.update(ONION_HS_PROTOCOL_VERSION);
|
||||||
|
|||||||
@@ -39,12 +39,13 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.UTF_8;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class MessageEncrypter {
|
public class MessageEncrypter {
|
||||||
@@ -228,7 +229,7 @@ public class MessageEncrypter {
|
|||||||
PublicKey publicKey =
|
PublicKey publicKey =
|
||||||
encrypter.getKeyParser().parsePublicKey(keyBytes);
|
encrypter.getKeyParser().parsePublicKey(keyBytes);
|
||||||
String message = readFully(System.in);
|
String message = readFully(System.in);
|
||||||
byte[] plaintext = message.getBytes(Charset.forName("UTF-8"));
|
byte[] plaintext = message.getBytes(UTF_8);
|
||||||
byte[] ciphertext = encrypter.encrypt(publicKey, plaintext);
|
byte[] ciphertext = encrypter.encrypt(publicKey, plaintext);
|
||||||
System.out.println(AsciiArmour.wrap(ciphertext, LINE_LENGTH));
|
System.out.println(AsciiArmour.wrap(ciphertext, LINE_LENGTH));
|
||||||
}
|
}
|
||||||
@@ -242,7 +243,7 @@ public class MessageEncrypter {
|
|||||||
encrypter.getKeyParser().parsePrivateKey(keyBytes);
|
encrypter.getKeyParser().parsePrivateKey(keyBytes);
|
||||||
byte[] ciphertext = AsciiArmour.unwrap(readFully(System.in));
|
byte[] ciphertext = AsciiArmour.unwrap(readFully(System.in));
|
||||||
byte[] plaintext = encrypter.decrypt(privateKey, ciphertext);
|
byte[] plaintext = encrypter.decrypt(privateKey, ciphertext);
|
||||||
System.out.println(new String(plaintext, Charset.forName("UTF-8")));
|
System.out.println(new String(plaintext, UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String readFully(InputStream in) throws IOException {
|
private static String readFully(InputStream in) throws IOException {
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package org.briarproject.bramble.keyagreement;
|
package org.briarproject.bramble.keyagreement;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.data.BdfReaderFactory;
|
|
||||||
import org.briarproject.bramble.api.data.BdfWriterFactory;
|
|
||||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
|
import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
|
||||||
import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
|
import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
|
||||||
import org.briarproject.bramble.api.keyagreement.PayloadParser;
|
import org.briarproject.bramble.api.keyagreement.PayloadParser;
|
||||||
@@ -19,13 +17,13 @@ public class KeyAgreementModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
PayloadEncoder providePayloadEncoder(BdfWriterFactory bdfWriterFactory) {
|
PayloadEncoder providePayloadEncoder(PayloadEncoderImpl payloadEncoder) {
|
||||||
return new PayloadEncoderImpl(bdfWriterFactory);
|
return payloadEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
PayloadParser providePayloadParser(BdfReaderFactory bdfReaderFactory) {
|
PayloadParser providePayloadParser(PayloadParserImpl payloadParser) {
|
||||||
return new PayloadParserImpl(bdfReaderFactory);
|
return payloadParser;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ import java.io.IOException;
|
|||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.QR_FORMAT_ID;
|
||||||
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.QR_FORMAT_VERSION;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -29,7 +30,8 @@ class PayloadEncoderImpl implements PayloadEncoder {
|
|||||||
@Override
|
@Override
|
||||||
public byte[] encode(Payload p) {
|
public byte[] encode(Payload p) {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
out.write(PROTOCOL_VERSION);
|
int formatIdAndVersion = (QR_FORMAT_ID << 5) | QR_FORMAT_VERSION;
|
||||||
|
out.write(formatIdAndVersion);
|
||||||
BdfWriter w = bdfWriterFactory.createWriter(out);
|
BdfWriter w = bdfWriterFactory.createWriter(out);
|
||||||
try {
|
try {
|
||||||
w.writeListStart(); // Payload start
|
w.writeListStart(); // Payload start
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.briarproject.bramble.keyagreement;
|
package org.briarproject.bramble.keyagreement;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
import org.briarproject.bramble.api.Pair;
|
||||||
import org.briarproject.bramble.api.UnsupportedVersionException;
|
import org.briarproject.bramble.api.UnsupportedVersionException;
|
||||||
import org.briarproject.bramble.api.data.BdfList;
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
import org.briarproject.bramble.api.data.BdfReader;
|
import org.briarproject.bramble.api.data.BdfReader;
|
||||||
@@ -11,6 +12,8 @@ import org.briarproject.bramble.api.keyagreement.TransportDescriptor;
|
|||||||
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
||||||
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
||||||
import org.briarproject.bramble.api.plugin.TransportId;
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
|
import org.briarproject.bramble.api.qrcode.QrCodeClassifier;
|
||||||
|
import org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType;
|
||||||
import org.briarproject.nullsafety.NotNullByDefault;
|
import org.briarproject.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
@@ -21,34 +24,41 @@ import java.util.List;
|
|||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.BETA_PROTOCOL_VERSION;
|
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.QR_FORMAT_VERSION;
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
|
||||||
|
import static org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType.BQP;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.ISO_8859_1;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class PayloadParserImpl implements PayloadParser {
|
class PayloadParserImpl implements PayloadParser {
|
||||||
|
|
||||||
private final BdfReaderFactory bdfReaderFactory;
|
private final BdfReaderFactory bdfReaderFactory;
|
||||||
|
private final QrCodeClassifier qrCodeClassifier;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
PayloadParserImpl(BdfReaderFactory bdfReaderFactory) {
|
PayloadParserImpl(BdfReaderFactory bdfReaderFactory,
|
||||||
|
QrCodeClassifier qrCodeClassifier) {
|
||||||
this.bdfReaderFactory = bdfReaderFactory;
|
this.bdfReaderFactory = bdfReaderFactory;
|
||||||
|
this.qrCodeClassifier = qrCodeClassifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Payload parse(byte[] raw) throws IOException {
|
public Payload parse(String payloadString) throws IOException {
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(raw);
|
Pair<QrCodeType, Integer> typeAndVersion =
|
||||||
// First byte: the protocol version
|
qrCodeClassifier.classifyQrCode(payloadString);
|
||||||
int protocolVersion = in.read();
|
if (typeAndVersion.getFirst() != BQP) throw new FormatException();
|
||||||
if (protocolVersion == -1) throw new FormatException();
|
int formatVersion = typeAndVersion.getSecond();
|
||||||
if (protocolVersion != PROTOCOL_VERSION) {
|
if (formatVersion != QR_FORMAT_VERSION) {
|
||||||
boolean tooOld = protocolVersion < PROTOCOL_VERSION ||
|
boolean tooOld = formatVersion < QR_FORMAT_VERSION;
|
||||||
protocolVersion == BETA_PROTOCOL_VERSION;
|
|
||||||
throw new UnsupportedVersionException(tooOld);
|
throw new UnsupportedVersionException(tooOld);
|
||||||
}
|
}
|
||||||
|
byte[] raw = payloadString.getBytes(ISO_8859_1);
|
||||||
|
ByteArrayInputStream in = new ByteArrayInputStream(raw);
|
||||||
|
// First byte: the format identifier and version (already parsed)
|
||||||
|
if (in.read() == -1) throw new AssertionError();
|
||||||
// The rest of the payload is a BDF list with one or more elements
|
// The rest of the payload is a BDF list with one or more elements
|
||||||
BdfReader r = bdfReaderFactory.createReader(in);
|
BdfReader r = bdfReaderFactory.createReader(in);
|
||||||
BdfList payload = r.readList();
|
BdfList payload = r.readList();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.event.EventExecutor;
|
|||||||
import org.briarproject.bramble.api.mailbox.MailboxPairingTask;
|
import org.briarproject.bramble.api.mailbox.MailboxPairingTask;
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
|
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
|
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
|
||||||
|
import org.briarproject.bramble.api.qrcode.QrCodeClassifier;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.nullsafety.NotNullByDefault;
|
import org.briarproject.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
@@ -25,6 +26,7 @@ class MailboxPairingTaskFactoryImpl implements MailboxPairingTaskFactory {
|
|||||||
private final MailboxApi api;
|
private final MailboxApi api;
|
||||||
private final MailboxSettingsManager mailboxSettingsManager;
|
private final MailboxSettingsManager mailboxSettingsManager;
|
||||||
private final MailboxUpdateManager mailboxUpdateManager;
|
private final MailboxUpdateManager mailboxUpdateManager;
|
||||||
|
private final QrCodeClassifier qrCodeClassifier;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
MailboxPairingTaskFactoryImpl(
|
MailboxPairingTaskFactoryImpl(
|
||||||
@@ -34,7 +36,8 @@ class MailboxPairingTaskFactoryImpl implements MailboxPairingTaskFactory {
|
|||||||
Clock clock,
|
Clock clock,
|
||||||
MailboxApi api,
|
MailboxApi api,
|
||||||
MailboxSettingsManager mailboxSettingsManager,
|
MailboxSettingsManager mailboxSettingsManager,
|
||||||
MailboxUpdateManager mailboxUpdateManager) {
|
MailboxUpdateManager mailboxUpdateManager,
|
||||||
|
QrCodeClassifier qrCodeClassifier) {
|
||||||
this.eventExecutor = eventExecutor;
|
this.eventExecutor = eventExecutor;
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.crypto = crypto;
|
this.crypto = crypto;
|
||||||
@@ -42,12 +45,13 @@ class MailboxPairingTaskFactoryImpl implements MailboxPairingTaskFactory {
|
|||||||
this.api = api;
|
this.api = api;
|
||||||
this.mailboxSettingsManager = mailboxSettingsManager;
|
this.mailboxSettingsManager = mailboxSettingsManager;
|
||||||
this.mailboxUpdateManager = mailboxUpdateManager;
|
this.mailboxUpdateManager = mailboxUpdateManager;
|
||||||
|
this.qrCodeClassifier = qrCodeClassifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MailboxPairingTask createPairingTask(String qrCodePayload) {
|
public MailboxPairingTask createPairingTask(String qrCodePayload) {
|
||||||
return new MailboxPairingTaskImpl(qrCodePayload, eventExecutor, db,
|
return new MailboxPairingTaskImpl(qrCodePayload, eventExecutor, db,
|
||||||
crypto, clock, api, mailboxSettingsManager,
|
crypto, clock, api, mailboxSettingsManager,
|
||||||
mailboxUpdateManager);
|
mailboxUpdateManager, qrCodeClassifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.briarproject.bramble.mailbox;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.Consumer;
|
import org.briarproject.bramble.api.Consumer;
|
||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
import org.briarproject.bramble.api.Pair;
|
||||||
import org.briarproject.bramble.api.contact.Contact;
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
@@ -14,13 +15,14 @@ import org.briarproject.bramble.api.mailbox.MailboxProperties;
|
|||||||
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
|
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxUpdate;
|
import org.briarproject.bramble.api.mailbox.MailboxUpdate;
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
|
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
|
||||||
|
import org.briarproject.bramble.api.qrcode.QrCodeClassifier;
|
||||||
|
import org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.mailbox.MailboxApi.ApiException;
|
import org.briarproject.bramble.mailbox.MailboxApi.ApiException;
|
||||||
import org.briarproject.bramble.mailbox.MailboxApi.MailboxAlreadyPairedException;
|
import org.briarproject.bramble.mailbox.MailboxApi.MailboxAlreadyPairedException;
|
||||||
import org.briarproject.nullsafety.NotNullByDefault;
|
import org.briarproject.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -32,7 +34,10 @@ import javax.annotation.concurrent.ThreadSafe;
|
|||||||
|
|
||||||
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.bramble.api.mailbox.MailboxConstants.QR_FORMAT_VERSION;
|
||||||
|
import static org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType.MAILBOX;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.ISO_8859_1;
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -40,9 +45,6 @@ class MailboxPairingTaskImpl implements MailboxPairingTask {
|
|||||||
|
|
||||||
private final static Logger LOG =
|
private final static Logger LOG =
|
||||||
getLogger(MailboxPairingTaskImpl.class.getName());
|
getLogger(MailboxPairingTaskImpl.class.getName());
|
||||||
@SuppressWarnings("CharsetObjectCanBeUsed") // Requires minSdkVersion >= 19
|
|
||||||
private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
|
|
||||||
private static final int VERSION_REQUIRED = 32;
|
|
||||||
|
|
||||||
private final String payload;
|
private final String payload;
|
||||||
private final Executor eventExecutor;
|
private final Executor eventExecutor;
|
||||||
@@ -52,6 +54,7 @@ class MailboxPairingTaskImpl implements MailboxPairingTask {
|
|||||||
private final MailboxApi api;
|
private final MailboxApi api;
|
||||||
private final MailboxSettingsManager mailboxSettingsManager;
|
private final MailboxSettingsManager mailboxSettingsManager;
|
||||||
private final MailboxUpdateManager mailboxUpdateManager;
|
private final MailboxUpdateManager mailboxUpdateManager;
|
||||||
|
private final QrCodeClassifier qrCodeClassifier;
|
||||||
private final long timeStarted;
|
private final long timeStarted;
|
||||||
|
|
||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
@@ -69,7 +72,8 @@ class MailboxPairingTaskImpl implements MailboxPairingTask {
|
|||||||
Clock clock,
|
Clock clock,
|
||||||
MailboxApi api,
|
MailboxApi api,
|
||||||
MailboxSettingsManager mailboxSettingsManager,
|
MailboxSettingsManager mailboxSettingsManager,
|
||||||
MailboxUpdateManager mailboxUpdateManager) {
|
MailboxUpdateManager mailboxUpdateManager,
|
||||||
|
QrCodeClassifier qrCodeClassifier) {
|
||||||
this.payload = payload;
|
this.payload = payload;
|
||||||
this.eventExecutor = eventExecutor;
|
this.eventExecutor = eventExecutor;
|
||||||
this.db = db;
|
this.db = db;
|
||||||
@@ -78,6 +82,7 @@ class MailboxPairingTaskImpl implements MailboxPairingTask {
|
|||||||
this.api = api;
|
this.api = api;
|
||||||
this.mailboxSettingsManager = mailboxSettingsManager;
|
this.mailboxSettingsManager = mailboxSettingsManager;
|
||||||
this.mailboxUpdateManager = mailboxUpdateManager;
|
this.mailboxUpdateManager = mailboxUpdateManager;
|
||||||
|
this.qrCodeClassifier = qrCodeClassifier;
|
||||||
timeStarted = clock.currentTimeMillis();
|
timeStarted = clock.currentTimeMillis();
|
||||||
state = new MailboxPairingState.QrCodeReceived(timeStarted);
|
state = new MailboxPairingState.QrCodeReceived(timeStarted);
|
||||||
}
|
}
|
||||||
@@ -101,10 +106,20 @@ class MailboxPairingTaskImpl implements MailboxPairingTask {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
Pair<QrCodeType, Integer> typeAndVersion =
|
||||||
|
qrCodeClassifier.classifyQrCode(payload);
|
||||||
|
QrCodeType qrCodeType = typeAndVersion.getFirst();
|
||||||
|
int formatVersion = typeAndVersion.getSecond();
|
||||||
|
if (qrCodeType != MAILBOX || formatVersion != QR_FORMAT_VERSION) {
|
||||||
|
setState(new MailboxPairingState.InvalidQrCode(qrCodeType,
|
||||||
|
formatVersion));
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
pairMailbox();
|
pairMailbox();
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
onMailboxError(e, new MailboxPairingState.InvalidQrCode());
|
onMailboxError(e, new MailboxPairingState.InvalidQrCode(qrCodeType,
|
||||||
|
formatVersion));
|
||||||
} catch (MailboxAlreadyPairedException e) {
|
} catch (MailboxAlreadyPairedException e) {
|
||||||
onMailboxError(e, new MailboxPairingState.MailboxAlreadyPaired());
|
onMailboxError(e, new MailboxPairingState.MailboxAlreadyPaired());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -169,14 +184,6 @@ class MailboxPairingTaskImpl implements MailboxPairingTask {
|
|||||||
}
|
}
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
int version = bytes[0] & 0xFF;
|
|
||||||
if (version != VERSION_REQUIRED) {
|
|
||||||
if (LOG.isLoggable(WARNING)) {
|
|
||||||
LOG.warning("QR code has not version " + VERSION_REQUIRED +
|
|
||||||
": " + version);
|
|
||||||
}
|
|
||||||
throw new FormatException();
|
|
||||||
}
|
|
||||||
LOG.info("QR code is valid");
|
LOG.info("QR code is valid");
|
||||||
byte[] onionPubKey = Arrays.copyOfRange(bytes, 1, 33);
|
byte[] onionPubKey = Arrays.copyOfRange(bytes, 1, 33);
|
||||||
String onion = crypto.encodeOnion(onionPubKey);
|
String onion = crypto.encodeOnion(onionPubKey);
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ import java.io.OutputStream;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -100,6 +99,7 @@ import static org.briarproject.bramble.util.IoUtils.copyAndClose;
|
|||||||
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
|
import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.UTF_8;
|
||||||
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@@ -419,9 +419,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
append(strb, "ClientTransportPlugin meek_lite exec", obfs4Path);
|
append(strb, "ClientTransportPlugin meek_lite exec", obfs4Path);
|
||||||
String snowflakePath = getSnowflakeExecutableFile().getAbsolutePath();
|
String snowflakePath = getSnowflakeExecutableFile().getAbsolutePath();
|
||||||
append(strb, "ClientTransportPlugin snowflake exec", snowflakePath);
|
append(strb, "ClientTransportPlugin snowflake exec", snowflakePath);
|
||||||
//noinspection CharsetObjectCanBeUsed
|
return new ByteArrayInputStream(strb.toString().getBytes(UTF_8));
|
||||||
return new ByteArrayInputStream(
|
|
||||||
strb.toString().getBytes(Charset.forName("UTF-8")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void listFiles(File f) {
|
private void listFiles(File f) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
|
|||||||
import org.bouncycastle.util.encoders.Base64;
|
import org.bouncycastle.util.encoders.Base64;
|
||||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import static org.briarproject.bramble.util.StringUtils.US_ASCII;
|
||||||
|
|
||||||
class TorRendezvousCryptoImpl implements TorRendezvousCrypto {
|
class TorRendezvousCryptoImpl implements TorRendezvousCrypto {
|
||||||
|
|
||||||
@@ -31,6 +31,6 @@ class TorRendezvousCryptoImpl implements TorRendezvousCrypto {
|
|||||||
EdDSAPrivateKeySpec spec = new EdDSAPrivateKeySpec(seed, CURVE_SPEC);
|
EdDSAPrivateKeySpec spec = new EdDSAPrivateKeySpec(seed, CURVE_SPEC);
|
||||||
byte[] hash = spec.getH();
|
byte[] hash = spec.getH();
|
||||||
byte[] base64 = Base64.encode(hash);
|
byte[] base64 = Base64.encode(hash);
|
||||||
return "ED25519-V3:" + new String(base64, Charset.forName("US-ASCII"));
|
return "ED25519-V3:" + new String(base64, US_ASCII);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package org.briarproject.bramble.qrcode;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.Pair;
|
||||||
|
import org.briarproject.bramble.api.keyagreement.KeyAgreementConstants;
|
||||||
|
import org.briarproject.bramble.api.mailbox.MailboxConstants;
|
||||||
|
import org.briarproject.bramble.api.qrcode.QrCodeClassifier;
|
||||||
|
import org.briarproject.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType.BQP;
|
||||||
|
import static org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType.MAILBOX;
|
||||||
|
import static org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType.UNKNOWN;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.ISO_8859_1;
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
@NotNullByDefault
|
||||||
|
class QrCodeClassifierImpl implements QrCodeClassifier {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
QrCodeClassifierImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pair<QrCodeType, Integer> classifyQrCode(String payload) {
|
||||||
|
byte[] bytes = payload.getBytes(ISO_8859_1);
|
||||||
|
if (bytes.length == 0) return new Pair<>(UNKNOWN, 0);
|
||||||
|
// If this is a Bramble QR code then the first byte encodes the
|
||||||
|
// format ID (3 bits) and version (5 bits)
|
||||||
|
int formatIdAndVersion = bytes[0] & 0xFF;
|
||||||
|
int formatId = formatIdAndVersion >> 5;
|
||||||
|
int formatVersion = formatIdAndVersion & 0x1F;
|
||||||
|
if (formatId == KeyAgreementConstants.QR_FORMAT_ID) {
|
||||||
|
return new Pair<>(BQP, formatVersion);
|
||||||
|
}
|
||||||
|
if (formatId == MailboxConstants.QR_FORMAT_ID) {
|
||||||
|
return new Pair<>(MAILBOX, formatVersion);
|
||||||
|
}
|
||||||
|
return new Pair<>(UNKNOWN, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package org.briarproject.bramble.qrcode;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.qrcode.QrCodeClassifier;
|
||||||
|
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.Provides;
|
||||||
|
|
||||||
|
@Module
|
||||||
|
public class QrCodeModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
QrCodeClassifier provideQrCodeClassifier(
|
||||||
|
QrCodeClassifierImpl qrCodeClassifier) {
|
||||||
|
return qrCodeClassifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,7 +20,6 @@ import java.io.FileInputStream;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@@ -34,6 +33,7 @@ import static org.briarproject.bramble.test.TestUtils.getIdentity;
|
|||||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
|
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.UTF_8;
|
||||||
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||||
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
@@ -342,7 +342,7 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
|
|||||||
private void storeDatabaseKey(File f, String hex) throws IOException {
|
private void storeDatabaseKey(File f, String hex) throws IOException {
|
||||||
f.getParentFile().mkdirs();
|
f.getParentFile().mkdirs();
|
||||||
FileOutputStream out = new FileOutputStream(f);
|
FileOutputStream out = new FileOutputStream(f);
|
||||||
out.write(hex.getBytes(Charset.forName("UTF-8")));
|
out.write(hex.getBytes(UTF_8));
|
||||||
out.flush();
|
out.flush();
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
@@ -350,7 +350,7 @@ public class AccountManagerImplTest extends BrambleMockTestCase {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private String loadDatabaseKey(File f) throws IOException {
|
private String loadDatabaseKey(File f) throws IOException {
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||||
new FileInputStream(f), Charset.forName("UTF-8")));
|
new FileInputStream(f), UTF_8));
|
||||||
String hex = reader.readLine();
|
String hex = reader.readLine();
|
||||||
reader.close();
|
reader.close();
|
||||||
return hex;
|
return hex;
|
||||||
|
|||||||
@@ -2,21 +2,26 @@ package org.briarproject.bramble.keyagreement;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.Bytes;
|
import org.briarproject.bramble.api.Bytes;
|
||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
import org.briarproject.bramble.api.Pair;
|
||||||
import org.briarproject.bramble.api.UnsupportedVersionException;
|
import org.briarproject.bramble.api.UnsupportedVersionException;
|
||||||
import org.briarproject.bramble.api.data.BdfList;
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
import org.briarproject.bramble.api.data.BdfReader;
|
import org.briarproject.bramble.api.data.BdfReader;
|
||||||
import org.briarproject.bramble.api.data.BdfReaderFactory;
|
import org.briarproject.bramble.api.data.BdfReaderFactory;
|
||||||
import org.briarproject.bramble.api.keyagreement.Payload;
|
import org.briarproject.bramble.api.keyagreement.Payload;
|
||||||
|
import org.briarproject.bramble.api.qrcode.QrCodeClassifier;
|
||||||
|
import org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType;
|
||||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.BETA_PROTOCOL_VERSION;
|
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.QR_FORMAT_VERSION;
|
||||||
|
import static org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType.BQP;
|
||||||
|
import static org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType.MAILBOX;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
@@ -26,32 +31,29 @@ public class PayloadParserImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
private final BdfReaderFactory bdfReaderFactory =
|
private final BdfReaderFactory bdfReaderFactory =
|
||||||
context.mock(BdfReaderFactory.class);
|
context.mock(BdfReaderFactory.class);
|
||||||
|
private final QrCodeClassifier qrCodeClassifier =
|
||||||
|
context.mock(QrCodeClassifier.class);
|
||||||
private final BdfReader bdfReader = context.mock(BdfReader.class);
|
private final BdfReader bdfReader = context.mock(BdfReader.class);
|
||||||
|
|
||||||
|
private final String payload = getRandomString(123);
|
||||||
|
|
||||||
private final PayloadParserImpl payloadParser =
|
private final PayloadParserImpl payloadParser =
|
||||||
new PayloadParserImpl(bdfReaderFactory);
|
new PayloadParserImpl(bdfReaderFactory, qrCodeClassifier);
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testThrowsFormatExceptionIfPayloadIsEmpty() throws Exception {
|
public void testThrowsFormatExceptionForWrongQrCodeType() throws Exception {
|
||||||
payloadParser.parse(new byte[0]);
|
expectClassifyQrCode(payload, MAILBOX, QR_FORMAT_VERSION);
|
||||||
|
|
||||||
|
payloadParser.parse(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testThrowsUnsupportedVersionExceptionForOldVersion()
|
public void testThrowsUnsupportedVersionExceptionForOldVersion()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
try {
|
expectClassifyQrCode(payload, BQP, QR_FORMAT_VERSION - 1);
|
||||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION - 1});
|
|
||||||
fail();
|
|
||||||
} catch (UnsupportedVersionException e) {
|
|
||||||
assertTrue(e.isTooOld());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testThrowsUnsupportedVersionExceptionForBetaVersion()
|
|
||||||
throws Exception {
|
|
||||||
try {
|
try {
|
||||||
payloadParser.parse(new byte[] {BETA_PROTOCOL_VERSION});
|
payloadParser.parse(payload);
|
||||||
fail();
|
fail();
|
||||||
} catch (UnsupportedVersionException e) {
|
} catch (UnsupportedVersionException e) {
|
||||||
assertTrue(e.isTooOld());
|
assertTrue(e.isTooOld());
|
||||||
@@ -61,8 +63,10 @@ public class PayloadParserImplTest extends BrambleMockTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testThrowsUnsupportedVersionExceptionForNewVersion()
|
public void testThrowsUnsupportedVersionExceptionForNewVersion()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
expectClassifyQrCode(payload, BQP, QR_FORMAT_VERSION + 1);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION + 1});
|
payloadParser.parse(payload);
|
||||||
fail();
|
fail();
|
||||||
} catch (UnsupportedVersionException e) {
|
} catch (UnsupportedVersionException e) {
|
||||||
assertFalse(e.isTooOld());
|
assertFalse(e.isTooOld());
|
||||||
@@ -71,6 +75,8 @@ public class PayloadParserImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testThrowsFormatExceptionForEmptyList() throws Exception {
|
public void testThrowsFormatExceptionForEmptyList() throws Exception {
|
||||||
|
expectClassifyQrCode(payload, BQP, QR_FORMAT_VERSION);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(bdfReaderFactory).createReader(
|
oneOf(bdfReaderFactory).createReader(
|
||||||
with(any(ByteArrayInputStream.class)));
|
with(any(ByteArrayInputStream.class)));
|
||||||
@@ -79,7 +85,7 @@ public class PayloadParserImplTest extends BrambleMockTestCase {
|
|||||||
will(returnValue(new BdfList()));
|
will(returnValue(new BdfList()));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
payloadParser.parse(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
@@ -87,6 +93,8 @@ public class PayloadParserImplTest extends BrambleMockTestCase {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
byte[] commitment = getRandomBytes(COMMIT_LENGTH);
|
byte[] commitment = getRandomBytes(COMMIT_LENGTH);
|
||||||
|
|
||||||
|
expectClassifyQrCode(payload, BQP, QR_FORMAT_VERSION);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(bdfReaderFactory).createReader(
|
oneOf(bdfReaderFactory).createReader(
|
||||||
with(any(ByteArrayInputStream.class)));
|
with(any(ByteArrayInputStream.class)));
|
||||||
@@ -97,7 +105,7 @@ public class PayloadParserImplTest extends BrambleMockTestCase {
|
|||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
payloadParser.parse(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
@@ -105,6 +113,7 @@ public class PayloadParserImplTest extends BrambleMockTestCase {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
byte[] commitment = getRandomBytes(COMMIT_LENGTH - 1);
|
byte[] commitment = getRandomBytes(COMMIT_LENGTH - 1);
|
||||||
|
|
||||||
|
expectClassifyQrCode(payload, BQP, QR_FORMAT_VERSION);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(bdfReaderFactory).createReader(
|
oneOf(bdfReaderFactory).createReader(
|
||||||
with(any(ByteArrayInputStream.class)));
|
with(any(ByteArrayInputStream.class)));
|
||||||
@@ -115,7 +124,7 @@ public class PayloadParserImplTest extends BrambleMockTestCase {
|
|||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
payloadParser.parse(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
@@ -123,6 +132,7 @@ public class PayloadParserImplTest extends BrambleMockTestCase {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
byte[] commitment = getRandomBytes(COMMIT_LENGTH + 1);
|
byte[] commitment = getRandomBytes(COMMIT_LENGTH + 1);
|
||||||
|
|
||||||
|
expectClassifyQrCode(payload, BQP, QR_FORMAT_VERSION);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(bdfReaderFactory).createReader(
|
oneOf(bdfReaderFactory).createReader(
|
||||||
with(any(ByteArrayInputStream.class)));
|
with(any(ByteArrayInputStream.class)));
|
||||||
@@ -133,12 +143,14 @@ public class PayloadParserImplTest extends BrambleMockTestCase {
|
|||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
payloadParser.parse(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAcceptsPayloadWithNoDescriptors() throws Exception {
|
public void testAcceptsPayloadWithNoDescriptors() throws Exception {
|
||||||
byte[] commitment = getRandomBytes(COMMIT_LENGTH);
|
byte[] commitment = getRandomBytes(COMMIT_LENGTH);
|
||||||
|
|
||||||
|
expectClassifyQrCode(payload, BQP, QR_FORMAT_VERSION);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(bdfReaderFactory).createReader(
|
oneOf(bdfReaderFactory).createReader(
|
||||||
with(any(ByteArrayInputStream.class)));
|
with(any(ByteArrayInputStream.class)));
|
||||||
@@ -149,8 +161,16 @@ public class PayloadParserImplTest extends BrambleMockTestCase {
|
|||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
Payload p = payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
Payload p = payloadParser.parse(payload);
|
||||||
assertArrayEquals(commitment, p.getCommitment());
|
assertArrayEquals(commitment, p.getCommitment());
|
||||||
assertTrue(p.getTransportDescriptors().isEmpty());
|
assertTrue(p.getTransportDescriptors().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void expectClassifyQrCode(String payload, QrCodeType qrCodeType,
|
||||||
|
int formatVersion) {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(qrCodeClassifier).classifyQrCode(payload);
|
||||||
|
will(returnValue(new Pair<>(qrCodeType, formatVersion)));
|
||||||
|
}});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.bramble.mailbox;
|
package org.briarproject.bramble.mailbox;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.Pair;
|
||||||
import org.briarproject.bramble.api.contact.Contact;
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
@@ -13,6 +14,8 @@ import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
|
|||||||
import org.briarproject.bramble.api.mailbox.MailboxUpdate;
|
import org.briarproject.bramble.api.mailbox.MailboxUpdate;
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
|
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxVersion;
|
import org.briarproject.bramble.api.mailbox.MailboxVersion;
|
||||||
|
import org.briarproject.bramble.api.qrcode.QrCodeClassifier;
|
||||||
|
import org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
import org.briarproject.bramble.test.DbExpectations;
|
import org.briarproject.bramble.test.DbExpectations;
|
||||||
@@ -27,6 +30,9 @@ import java.util.concurrent.Executor;
|
|||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
|
import static org.briarproject.bramble.api.mailbox.MailboxConstants.QR_FORMAT_VERSION;
|
||||||
|
import static org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType.BQP;
|
||||||
|
import static org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType.MAILBOX;
|
||||||
import static org.briarproject.bramble.mailbox.MailboxTestUtils.getQrCodePayload;
|
import static org.briarproject.bramble.mailbox.MailboxTestUtils.getQrCodePayload;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getContact;
|
import static org.briarproject.bramble.test.TestUtils.getContact;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||||
@@ -48,9 +54,8 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
|
|||||||
context.mock(MailboxSettingsManager.class);
|
context.mock(MailboxSettingsManager.class);
|
||||||
private final MailboxUpdateManager mailboxUpdateManager =
|
private final MailboxUpdateManager mailboxUpdateManager =
|
||||||
context.mock(MailboxUpdateManager.class);
|
context.mock(MailboxUpdateManager.class);
|
||||||
private final MailboxPairingTaskFactory factory =
|
private final QrCodeClassifier qrCodeClassifier =
|
||||||
new MailboxPairingTaskFactoryImpl(executor, db, crypto, clock, api,
|
context.mock(QrCodeClassifier.class);
|
||||||
mailboxSettingsManager, mailboxUpdateManager);
|
|
||||||
|
|
||||||
private final String onion = getRandomString(56);
|
private final String onion = getRandomString(56);
|
||||||
private final byte[] onionBytes = getRandomBytes(32);
|
private final byte[] onionBytes = getRandomBytes(32);
|
||||||
@@ -75,23 +80,47 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInvalidQrCode() {
|
public void testInvalidQrCodeType() {
|
||||||
MailboxPairingTask task1 = createPairingTask(getRandomString(42));
|
String payload = getRandomString(65);
|
||||||
task1.run();
|
MailboxPairingTask task = createPairingTask(payload);
|
||||||
task1.addObserver(state ->
|
|
||||||
|
expectClassifyQrCode(payload, BQP, QR_FORMAT_VERSION);
|
||||||
|
|
||||||
|
task.run();
|
||||||
|
task.addObserver(state ->
|
||||||
assertTrue(state instanceof MailboxPairingState.InvalidQrCode)
|
assertTrue(state instanceof MailboxPairingState.InvalidQrCode)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
String goodLength = "00" + getRandomString(63);
|
@Test
|
||||||
MailboxPairingTask task2 = createPairingTask(goodLength);
|
public void testInvalidQrCodeVersion() {
|
||||||
task2.run();
|
String payload = getRandomString(65);
|
||||||
task2.addObserver(state ->
|
MailboxPairingTask task = createPairingTask(payload);
|
||||||
|
|
||||||
|
expectClassifyQrCode(payload, MAILBOX, QR_FORMAT_VERSION + 1);
|
||||||
|
|
||||||
|
task.run();
|
||||||
|
task.addObserver(state ->
|
||||||
|
assertTrue(state instanceof MailboxPairingState.InvalidQrCode)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidQrCodeLength() {
|
||||||
|
String payload = getRandomString(42);
|
||||||
|
MailboxPairingTask task = createPairingTask(payload);
|
||||||
|
|
||||||
|
expectClassifyQrCode(payload, MAILBOX, QR_FORMAT_VERSION);
|
||||||
|
|
||||||
|
task.run();
|
||||||
|
task.addObserver(state ->
|
||||||
assertTrue(state instanceof MailboxPairingState.InvalidQrCode)
|
assertTrue(state instanceof MailboxPairingState.InvalidQrCode)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccessfulPairing() throws Exception {
|
public void testSuccessfulPairing() throws Exception {
|
||||||
|
expectClassifyQrCode(validPayload, MAILBOX, QR_FORMAT_VERSION);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(crypto).encodeOnion(onionBytes);
|
oneOf(crypto).encodeOnion(onionBytes);
|
||||||
will(returnValue(onion));
|
will(returnValue(onion));
|
||||||
@@ -156,6 +185,7 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
private void testApiException(Exception e,
|
private void testApiException(Exception e,
|
||||||
Class<? extends MailboxPairingState> s) throws Exception {
|
Class<? extends MailboxPairingState> s) throws Exception {
|
||||||
|
expectClassifyQrCode(validPayload, MAILBOX, QR_FORMAT_VERSION);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(crypto).encodeOnion(onionBytes);
|
oneOf(crypto).encodeOnion(onionBytes);
|
||||||
will(returnValue(onion));
|
will(returnValue(onion));
|
||||||
@@ -170,6 +200,7 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDbException() throws Exception {
|
public void testDbException() throws Exception {
|
||||||
|
expectClassifyQrCode(validPayload, MAILBOX, QR_FORMAT_VERSION);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(crypto).encodeOnion(onionBytes);
|
oneOf(crypto).encodeOnion(onionBytes);
|
||||||
will(returnValue(onion));
|
will(returnValue(onion));
|
||||||
@@ -206,6 +237,16 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
|
|||||||
will(returnValue(time));
|
will(returnValue(time));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
return factory.createPairingTask(qrCodePayload);
|
return new MailboxPairingTaskImpl(qrCodePayload, executor, db,
|
||||||
|
crypto, clock, api, mailboxSettingsManager,
|
||||||
|
mailboxUpdateManager, qrCodeClassifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectClassifyQrCode(String payload, QrCodeType qrCodeType,
|
||||||
|
int formatVersion) {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(qrCodeClassifier).classifyQrCode(payload);
|
||||||
|
will(returnValue(new Pair<>(qrCodeType, formatVersion)));
|
||||||
|
}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package org.briarproject.bramble.mailbox;
|
|||||||
import org.briarproject.bramble.api.WeakSingletonProvider;
|
import org.briarproject.bramble.api.WeakSingletonProvider;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.net.SocketFactory;
|
import javax.net.SocketFactory;
|
||||||
@@ -11,20 +10,24 @@ import javax.net.SocketFactory;
|
|||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
|
import static org.briarproject.bramble.api.mailbox.MailboxConstants.QR_FORMAT_ID;
|
||||||
|
import static org.briarproject.bramble.api.mailbox.MailboxConstants.QR_FORMAT_VERSION;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.ISO_8859_1;
|
||||||
|
|
||||||
class MailboxTestUtils {
|
class MailboxTestUtils {
|
||||||
|
|
||||||
static String getQrCodePayload(byte[] onionBytes, byte[] setupToken) {
|
static String getQrCodePayload(byte[] onionBytes, byte[] setupToken) {
|
||||||
|
int formatIdAndVersion = (QR_FORMAT_ID << 5) | QR_FORMAT_VERSION;
|
||||||
byte[] payloadBytes = ByteBuffer.allocate(65)
|
byte[] payloadBytes = ByteBuffer.allocate(65)
|
||||||
.put((byte) 32) // 1
|
.put((byte) formatIdAndVersion) // 1
|
||||||
.put(onionBytes) // 32
|
.put(onionBytes) // 32
|
||||||
.put(setupToken) // 32
|
.put(setupToken) // 32
|
||||||
.array();
|
.array();
|
||||||
//noinspection CharsetObjectCanBeUsed
|
return new String(payloadBytes, ISO_8859_1);
|
||||||
return new String(payloadBytes, Charset.forName("ISO-8859-1"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used by mailbox integration tests
|
||||||
static String getQrCodePayload(byte[] setupToken) {
|
static String getQrCodePayload(byte[] setupToken) {
|
||||||
return getQrCodePayload(getRandomId(), setupToken);
|
return getQrCodePayload(getRandomId(), setupToken);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package org.briarproject.bramble.qrcode;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.Pair;
|
||||||
|
import org.briarproject.bramble.api.keyagreement.KeyAgreementConstants;
|
||||||
|
import org.briarproject.bramble.api.mailbox.MailboxConstants;
|
||||||
|
import org.briarproject.bramble.api.qrcode.QrCodeClassifier;
|
||||||
|
import org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType;
|
||||||
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType.BQP;
|
||||||
|
import static org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType.MAILBOX;
|
||||||
|
import static org.briarproject.bramble.api.qrcode.QrCodeClassifier.QrCodeType.UNKNOWN;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.ISO_8859_1;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class QrCodeClassifierImplTest extends BrambleTestCase {
|
||||||
|
|
||||||
|
private final QrCodeClassifier classifier = new QrCodeClassifierImpl();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClassifiesEmptyStringAsUnknown() {
|
||||||
|
Pair<QrCodeType, Integer> result = classifier.classifyQrCode("");
|
||||||
|
assertEquals(UNKNOWN, result.getFirst());
|
||||||
|
assertEquals(0, result.getSecond().intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClassifiesKeyAgreement() {
|
||||||
|
byte[] payloadBytes = getRandomBytes(123);
|
||||||
|
for (int version = 0; version < 32; version++) {
|
||||||
|
int typeAndVersion =
|
||||||
|
(KeyAgreementConstants.QR_FORMAT_ID << 5) | version;
|
||||||
|
payloadBytes[0] = (byte) typeAndVersion;
|
||||||
|
String payload = new String(payloadBytes, ISO_8859_1);
|
||||||
|
Pair<QrCodeType, Integer> result =
|
||||||
|
classifier.classifyQrCode(payload);
|
||||||
|
assertEquals(BQP, result.getFirst());
|
||||||
|
assertEquals(version, result.getSecond().intValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClassifiesMailbox() {
|
||||||
|
byte[] payloadBytes = getRandomBytes(123);
|
||||||
|
for (int version = 0; version < 32; version++) {
|
||||||
|
int typeAndVersion =
|
||||||
|
(MailboxConstants.QR_FORMAT_ID << 5) | version;
|
||||||
|
payloadBytes[0] = (byte) typeAndVersion;
|
||||||
|
String payload = new String(payloadBytes, ISO_8859_1);
|
||||||
|
Pair<QrCodeType, Integer> result =
|
||||||
|
classifier.classifyQrCode(payload);
|
||||||
|
assertEquals(MAILBOX, result.getFirst());
|
||||||
|
assertEquals(version, result.getSecond().intValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClassifiesUnknownFormatIdAsUnknown() {
|
||||||
|
byte[] payloadBytes = getRandomBytes(123);
|
||||||
|
int unknownFormatId = MailboxConstants.QR_FORMAT_ID + 1;
|
||||||
|
int typeAndVersion = unknownFormatId << 5;
|
||||||
|
payloadBytes[0] = (byte) typeAndVersion;
|
||||||
|
String payload = new String(payloadBytes, ISO_8859_1);
|
||||||
|
Pair<QrCodeType, Integer> result = classifier.classifyQrCode(payload);
|
||||||
|
assertEquals(UNKNOWN, result.getFirst());
|
||||||
|
assertEquals(0, result.getSecond().intValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,6 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.CharacterCodingException;
|
import java.nio.charset.CharacterCodingException;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.nio.charset.CharsetDecoder;
|
import java.nio.charset.CharsetDecoder;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
@@ -33,6 +32,7 @@ import static java.util.logging.Level.WARNING;
|
|||||||
import static jssc.SerialPort.PURGE_RXCLEAR;
|
import static jssc.SerialPort.PURGE_RXCLEAR;
|
||||||
import static jssc.SerialPort.PURGE_TXCLEAR;
|
import static jssc.SerialPort.PURGE_TXCLEAR;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.US_ASCII;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -41,7 +41,6 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
|||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(ModemImpl.class.getName());
|
Logger.getLogger(ModemImpl.class.getName());
|
||||||
|
|
||||||
private static final Charset US_ASCII = Charset.forName("US-ASCII");
|
|
||||||
private static final int MAX_LINE_LENGTH = 256;
|
private static final int MAX_LINE_LENGTH = 256;
|
||||||
private static final int[] BAUD_RATES = {
|
private static final int[] BAUD_RATES = {
|
||||||
256000, 128000, 115200, 57600, 38400, 19200, 14400, 9600, 4800, 1200
|
256000, 128000, 115200, 57600, 38400, 19200, 14400, 9600, 4800, 1200
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
|
|||||||
import org.briarproject.nullsafety.NotNullByDefault;
|
import org.briarproject.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
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;
|
||||||
|
|
||||||
@@ -85,6 +84,7 @@ import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
|
|||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
|
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
|
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.ISO_8859_1;
|
||||||
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactPermissionManager.areEssentialPermissionsGranted;
|
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactPermissionManager.areEssentialPermissionsGranted;
|
||||||
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.NO_ADAPTER;
|
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.NO_ADAPTER;
|
||||||
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.REFUSED;
|
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.REFUSED;
|
||||||
@@ -126,9 +126,6 @@ class AddNearbyContactViewModel extends AndroidViewModel
|
|||||||
REFUSED
|
REFUSED
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("CharsetObjectCanBeUsed") // Requires minSdkVersion >= 19
|
|
||||||
private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
|
|
||||||
|
|
||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
private final AndroidExecutor androidExecutor;
|
private final AndroidExecutor androidExecutor;
|
||||||
private final Executor ioExecutor;
|
private final Executor ioExecutor;
|
||||||
@@ -446,10 +443,7 @@ class AddNearbyContactViewModel extends AndroidViewModel
|
|||||||
// Ignore results until the KeyAgreementTask is ready
|
// Ignore results until the KeyAgreementTask is ready
|
||||||
if (!gotLocalPayload || gotRemotePayload || currentTask == null) return;
|
if (!gotLocalPayload || gotRemotePayload || currentTask == null) return;
|
||||||
try {
|
try {
|
||||||
byte[] payloadBytes = result.getText().getBytes(ISO_8859_1);
|
Payload remotePayload = payloadParser.parse(result.getText());
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Remote payload is " + payloadBytes.length + " bytes");
|
|
||||||
Payload remotePayload = payloadParser.parse(payloadBytes);
|
|
||||||
gotRemotePayload = true;
|
gotRemotePayload = true;
|
||||||
currentTask.connectAndRunProtocol(remotePayload);
|
currentTask.connectAndRunProtocol(remotePayload);
|
||||||
state.postValue(new AddContactState.QrCodeScanned());
|
state.postValue(new AddContactState.QrCodeScanned());
|
||||||
|
|||||||
@@ -436,7 +436,7 @@ class HotspotManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String createWifiLoginString(String ssid, String password) {
|
private static String createWifiLoginString(String ssid, String password) {
|
||||||
// https://en.wikipedia.org/wiki/QR_code#WiFi_network_login
|
// https://en.wikipedia.org/wiki/QR_code#Joining_a_Wi%E2%80%91Fi_network
|
||||||
// do not remove the dangling ';', it can cause problems to omit it
|
// do not remove the dangling ';', it can cause problems to omit it
|
||||||
return "WIFI:S:" + ssid + ";T:WPA;P:" + password + ";;";
|
return "WIFI:S:" + ssid + ";T:WPA;P:" + password + ";;";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ public class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
|
|||||||
private final ResultCallback callback;
|
private final ResultCallback callback;
|
||||||
|
|
||||||
private Camera camera = null;
|
private Camera camera = null;
|
||||||
private int cameraIndex = 0;
|
|
||||||
|
|
||||||
public QrCodeDecoder(AndroidExecutor androidExecutor,
|
public QrCodeDecoder(AndroidExecutor androidExecutor,
|
||||||
@IoExecutor Executor ioExecutor, ResultCallback callback) {
|
@IoExecutor Executor ioExecutor, ResultCallback callback) {
|
||||||
@@ -53,14 +52,12 @@ public class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
|
|||||||
@Override
|
@Override
|
||||||
public void start(Camera camera, int cameraIndex) {
|
public void start(Camera camera, int cameraIndex) {
|
||||||
this.camera = camera;
|
this.camera = camera;
|
||||||
this.cameraIndex = cameraIndex;
|
|
||||||
askForPreviewFrame();
|
askForPreviewFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
camera = null;
|
camera = null;
|
||||||
cameraIndex = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
|
|||||||
Reference in New Issue
Block a user