Compare commits

..

121 Commits

Author SHA1 Message Date
Sebastian Kürten
4c29c4fa5b Add a bunch of tests highlighting implicit acks 2021-03-19 18:33:48 +01:00
Sebastian Kürten
34948fce13 Implement auto-declining for self-destructed introductions 2021-03-19 18:31:17 +01:00
Torsten Grote
f604320989 Merge branch '1835-auto-decline-self-destructed-incoming-blog-forum-sharing' into '804-self-destructing-messages'
Automatically decline incoming blog/forum invitations when they self-destruct

See merge request briar/briar!1392
2021-03-16 11:23:41 +00:00
Daniel Lublin
ea8c78bfef Make sure invitation accept msg is linking to shareable 2021-03-16 11:07:44 +01:00
Daniel Lublin
37d8a34c69 Add test for invitee responding after sharer deleted invitation 2021-03-16 11:07:44 +01:00
Daniel Lublin
45e3c56eb8 Keep members in subclasses and use getters 2021-03-16 11:07:44 +01:00
Daniel Lublin
647467a51a Assert that expected event is broadcasted 2021-03-16 11:07:43 +01:00
Daniel Lublin
144bd7bf1d Remember when invitation was auto-declined due to deletion
And render differently
2021-03-16 11:07:43 +01:00
Daniel Lublin
9d1c49c6b6 Auto-decline/auto-delete Forum & Blog sharing invitations/responses 2021-03-16 11:07:42 +01:00
akwizgran
f5c2bed528 Merge branch '804-auto-decline-unread' into '804-self-destructing-messages'
No notification for auto-decline messages

See merge request briar/briar!1406
2021-03-15 13:20:54 +00:00
Torsten Grote
b4de1424ac Don't show notification for own auto-decline responses 2021-03-15 08:58:08 -03:00
akwizgran
f184bfe9ac Merge branch 'test-event-listener' into '804-self-destructing-messages'
Add a way to check for expected events

See merge request briar/briar!1394
2021-03-09 13:35:59 +00:00
Torsten Grote
d3204ab3ee Use AtomicReference in TestEventListener to store event 2021-03-09 10:11:15 -03:00
akwizgran
163565e15c Merge branch '804-real-time-update' into '804-self-destructing-messages'
Update support for disappearing messages in real time

See merge request briar/briar!1397
2021-03-08 17:57:41 +00:00
Torsten Grote
ef46f8ed64 Update support for disappearing messages in real time 2021-03-08 14:22:15 -03:00
Torsten Grote
f42a9a20d8 Add a way to check for expected events
and use it for private group auto-declines
2021-03-08 12:15:11 -03:00
Torsten Grote
03c55311c7 Merge branch 'messaging-module-feature-flags' into '804-self-destructing-messages'
Don't advertise support for messaging features that are disabled by flags

See merge request briar/briar!1390
2021-03-08 11:47:09 +00:00
akwizgran
ad67a0abd6 Merge branch 'count-sent-messages-in-integration-tests' into '804-self-destructing-messages'
Count sent messages in integration tests

See merge request briar/briar!1393
2021-03-04 14:50:37 +00:00
akwizgran
9bc3a2c73d Count sent messages in integration tests. 2021-03-03 17:00:25 +00:00
akwizgran
af55d181e9 Merge branch '1836-delete-group-messages' into '804-self-destructing-messages'
Automatically decline incoming private group invitations when they self-destruct

See merge request briar/briar!1389
2021-03-03 16:56:16 +00:00
Torsten Grote
dde94baebd Use stored session metadata instead of fetching it again 2021-03-03 11:32:38 -03:00
Torsten Grote
64e3940f77 Render automatic declines differently in the UI
and show them as they happen via an Event
2021-03-02 14:06:06 -03:00
Torsten Grote
012ab0310f Remember when declines were automatic due to deletion
so they can be shown differently for sender
2021-03-02 14:06:05 -03:00
Torsten Grote
63012d0a72 Add integration tests for auto-deletion of private group invitations and responses 2021-03-02 10:35:00 -03:00
Torsten Grote
ebd233d005 Factor out auto-delete integration test code
so we can re-use it in other tests
2021-03-02 10:35:00 -03:00
akwizgran
f3b4440105 Don't advertise support for messaging features that are disabled by flags. 2021-03-02 13:04:23 +00:00
Torsten Grote
e36f275be7 Auto-delete PrivateGroup invitations and responses as well 2021-03-02 08:35:42 -03:00
akwizgran
3dc3d384d3 Merge branch '1833-update-onboarding-ui' into '804-self-destructing-messages'
Update self-destructing onboarding

See merge request briar/briar!1385
2021-03-02 10:37:13 +00:00
Torsten Grote
0c0c34696a Turn 'Learn more' link into a button to have a larger tap area
and a selectable background
2021-03-01 18:09:13 -03:00
Torsten Grote
7047f7d3d6 Turn ConversationSettingsLearnMoreDialog into a generic Onboarding fragment 2021-03-01 18:09:12 -03:00
Torsten Grote
abc8c86eaa Update auto-delete onboarding text 2021-03-01 18:09:12 -03:00
akwizgran
fa14448aa7 Show disabled menu item if we support feature but contact doesn't. 2021-03-01 17:57:06 -03:00
akwizgran
654603cfad Don't advertise support for disappearing messages unless flag is enabled. 2021-03-01 17:57:06 -03:00
akwizgran
112dace96c Hide disappearing messages menu item unless feature flag is enabled. 2021-03-01 17:57:06 -03:00
akwizgran
35bdb8075f Add feature flag for self-destructing messages. 2021-03-01 17:57:05 -03:00
Torsten Grote
f9d312a632 Replace all messages when re-loading
to ensure that messages deleted in the meantime get removed
2021-03-01 17:57:05 -03:00
Torsten Grote
dd93c6852e Remove auto-deleted messages immediately from conversation 2021-03-01 17:57:05 -03:00
Torsten Grote
5c4d971873 Replace MessagesCleanedUpEvent with ConversationMessagesDeletedEvent 2021-03-01 17:57:04 -03:00
akwizgran
1d9acc7425 Wait for events to be delivered before continuing with test. 2021-03-01 17:57:04 -03:00
akwizgran
6738287a83 Log how long it takes to deliver private messages and attachments. 2021-03-01 17:57:04 -03:00
akwizgran
ea4f763a55 Remove redundant call to getAutoDeleteTimer(). 2021-03-01 17:57:03 -03:00
akwizgran
9d027fb250 Check group counts in AutoDeleteIntegrationTest. 2021-03-01 17:57:03 -03:00
akwizgran
b56a9beb1d Include legacy messages when recalculating group count. 2021-03-01 17:57:03 -03:00
akwizgran
1083507752 Delete private messages when their timers expire (needs UI support). 2021-03-01 17:57:02 -03:00
akwizgran
0d2137f0f8 Move ConversationManagerImpl to conversation package. 2021-03-01 17:57:02 -03:00
akwizgran
f9ddb3a3a4 Set default timer duration to 1 minute for testing. 2021-03-01 17:57:02 -03:00
akwizgran
539198026d Update javadoc to explain that a new timer can be set. 2021-03-01 17:57:01 -03:00
akwizgran
d84fb0e761 Pass message IDs to cleanup hooks in batches. 2021-03-01 17:57:01 -03:00
akwizgran
7bf07b3b84 Group messages by group ID when fetching them from database. 2021-03-01 17:57:01 -03:00
akwizgran
e4da7968e3 Throw an exception if no cleanup hook was registered. 2021-03-01 17:57:00 -03:00
akwizgran
f0e4e3c164 Remove copypasta. 2021-03-01 17:57:00 -03:00
akwizgran
fac4132289 Add comment to explain that starting timer may be a no-op. 2021-03-01 17:57:00 -03:00
akwizgran
917da9ce36 Stop the timer if no hook has been registered. 2021-03-01 17:56:59 -03:00
akwizgran
e9249a9463 Add javadocs for CleanupManager and CleanupHook. 2021-03-01 17:56:59 -03:00
akwizgran
ec0a59db01 Simplify deadline comparison logic. 2021-03-01 17:56:59 -03:00
akwizgran
7e62d2aeff Stop the cleanup timer if the hook returns false. 2021-03-01 17:56:58 -03:00
akwizgran
3d8826cef9 Add cleanup manager. 2021-03-01 17:56:58 -03:00
akwizgran
6113b4ebee Query message IDs rather than metadata when only IDs are needed. 2021-03-01 17:56:58 -03:00
Torsten Grote
00e3e64495 Add support for showing auto-delete timers in minutes 2021-03-01 17:56:57 -03:00
Torsten Grote
115724a0a4 Show actual auto-delete timer duration in UI
(only days and hours for now)
2021-03-01 17:56:57 -03:00
Torsten Grote
0a92f0516f Show outgoing message status icon in same color as time 2021-03-01 17:56:57 -03:00
Torsten Grote
cc09a6deb2 Fix bomb icon color
in incoming image messages without text (on old phones)
2021-03-01 17:56:56 -03:00
Torsten Grote
5888775300 Get rid of SENDING state and publish new live data in order on UiThread 2021-03-01 17:56:56 -03:00
Torsten Grote
712f0f7cd9 Return LiveData when sending message 2021-03-01 17:56:56 -03:00
Torsten Grote
0d3f531545 Show warning dialog when auto-delete timer has changed since starting to compose message 2021-03-01 17:56:55 -03:00
Torsten Grote
b02629bf34 Add "Tap to learn more" to message bubbles for timer changes 2021-03-01 17:56:55 -03:00
akwizgran
b6693071f9 Provide clock for UI tests. 2021-03-01 17:56:55 -03:00
akwizgran
ff739e1982 Add some comments. 2021-03-01 17:56:54 -03:00
akwizgran
47fa7ccc81 Sync acks for initial messages when setting up integration tests. 2021-03-01 17:56:54 -03:00
akwizgran
1cf1e8b617 Allow time travel in integration tests. 2021-03-01 17:56:54 -03:00
akwizgran
b012f0991f Inject DefaultTaskSchedulerModule.EagerSingletons at startup in headless app. 2021-03-01 17:56:53 -03:00
akwizgran
1b7a1de881 Refactor integration tests to allow clock to be replaced. 2021-03-01 17:56:53 -03:00
Sebastian Kürten
8510fc80c9 Introduce conversation settings screen 2021-03-01 17:20:33 -03:00
Torsten Grote
5ae2a37d37 Create group invitation with read-write transaction
because the AutoDeleteManager needs to change the DB
and otherwise crashes.

Closes #1863
2021-03-01 17:20:33 -03:00
Torsten Grote
b032a84902 Make view state of text send UI easier to reason about
and fix bugs with bomb badge and hint display
2021-03-01 17:20:32 -03:00
Torsten Grote
f6414b5ca1 Show bomb badge in same style as send button 2021-03-01 17:20:32 -03:00
Torsten Grote
c5669bece5 Show a bomb badge on the send button when disappearing messages is active 2021-03-01 17:20:32 -03:00
Torsten Grote
8c76db6216 Use a different hint in conversation when message will disappear
and keep the hint updated when the auto-delete timer changes
2021-03-01 17:20:31 -03:00
Torsten Grote
370fe7601d Broadcast event when auto delete timer is mirrored 2021-03-01 17:20:31 -03:00
Torsten Grote
55de9859e0 Remove mirrored timer texts
as we can't detect reliably if a timer setting was mirrored or manually changed.

Also remove item update optimization from adapter as this can cause issues when items already exist.
2021-03-01 17:20:31 -03:00
Torsten Grote
06a8086502 Show timer change notices in private conversations 2021-03-01 17:20:30 -03:00
Torsten Grote
5522929b9b Allow setting a self-destruct timer
This is a rough prototype of #1837 meant to make testing the UI easier.
2021-03-01 17:20:30 -03:00
akwizgran
50d4f825c8 Use Collections.sort() to satisfy Animal Sniffer. 2021-03-01 17:20:30 -03:00
akwizgran
6cc225ec22 Add integration tests for timer mirroring. 2021-03-01 17:20:29 -03:00
akwizgran
aaa03cd809 Add method for UI and tests to get current timer. 2021-03-01 17:20:29 -03:00
akwizgran
890c9837b5 Update integration tests. 2021-03-01 17:20:29 -03:00
akwizgran
6ac54af432 Don't receive auto-delete timer from remote accept message as introducee. 2021-03-01 17:20:28 -03:00
akwizgran
0ccbd57d1d Hook up incoming messages to the auto-delete manager. 2021-03-01 17:20:28 -03:00
akwizgran
66d3e8950e Mirror the remote auto-delete timer. 2021-03-01 17:20:28 -03:00
akwizgran
d291b7796e Add integration tests for auto-delete timer. 2021-03-01 17:20:27 -03:00
akwizgran
7af863160d Forwarded accept messages aren't visible to the introducee. 2021-03-01 17:20:27 -03:00
akwizgran
c74e585668 Only use conversation timestamp for messages that will be visible in conversation. 2021-03-01 17:20:26 -03:00
akwizgran
0fd56b6c38 Get timestamp for abort message in same way as other messages. 2021-03-01 17:20:26 -03:00
akwizgran
57264b0f04 Look up auto-delete timer when creating private group invitation. 2021-03-01 17:20:26 -03:00
akwizgran
70225c5380 Use the right timestamp when signing private group invitation. 2021-03-01 17:20:25 -03:00
akwizgran
f0a602a579 Provide TransactionManager. 2021-03-01 17:20:22 -03:00
akwizgran
f9ab242f43 Look up conversation timestamp when creating group invitation messages. 2021-03-01 17:13:52 -03:00
akwizgran
24efc29722 Move lookup of latest conversation timestamp to core for blog and forum sharing. 2021-03-01 17:13:52 -03:00
akwizgran
e72169ecee Move lookup of latest conversation timestamp to core. 2021-03-01 17:13:52 -03:00
akwizgran
47db28a738 Add transactional variant of getGroupCount(). 2021-03-01 17:13:51 -03:00
akwizgran
30261b0dcf Send current minor version of messaging client to contacts. 2021-03-01 17:13:51 -03:00
Torsten Grote
10f9df4dc8 Show bomb icon for messages with auto-destruct timer 2021-03-01 17:13:51 -03:00
akwizgran
60dd260a5a Check that timer argument is legal before storing. 2021-03-01 17:13:51 -03:00
akwizgran
579a72f54b Add unit tests for AutoDeleteManagerImpl. 2021-03-01 17:13:50 -03:00
akwizgran
e270910399 Implement AutoDeleteManager. 2021-03-01 17:13:50 -03:00
akwizgran
c1483ea61a Add dummy implementation of AutoDeleteManager. 2021-03-01 17:13:50 -03:00
akwizgran
35751ecef6 Refactor auto-delete code from Bramble to Briar. 2021-03-01 17:13:49 -03:00
akwizgran
37d058a766 Rewrap lines. 2021-03-01 17:13:49 -03:00
akwizgran
5a6846c972 Factor out methods for storing and retrieving contact ID. 2021-03-01 17:13:49 -03:00
akwizgran
b34e6ee2a7 Factor out method for validating auto-delete timers. 2021-03-01 17:13:48 -03:00
akwizgran
2ae1e9631f Update comments. 2021-03-01 17:13:48 -03:00
akwizgran
76f2859a45 Add unit tests for validating auto-delete timer. 2021-03-01 17:13:48 -03:00
akwizgran
1c25b2da82 Update private group invitation client to include self-destruct timers. 2021-03-01 17:13:47 -03:00
akwizgran
26fe2f804f Update blog and forum sharing clients to include self-destruct timers. 2021-03-01 17:13:47 -03:00
akwizgran
c8d1ee878c Update message parsing and encoding to include auto-delete timer. 2021-03-01 17:13:47 -03:00
akwizgran
7b16e78470 Update introduction validator to support auto-delete timers. 2021-03-01 17:13:46 -03:00
akwizgran
7fb71a6cb9 Add constant for NO_AUTO_DELETE_TIMER, address review comments. 2021-03-01 17:13:46 -03:00
akwizgran
fc076954a3 Add unit tests for private message validation. 2021-03-01 17:13:46 -03:00
akwizgran
6a1d2e65ba Fix comments in PrivateMessageValidator. 2021-03-01 17:13:45 -03:00
akwizgran
d67cbd40bd Add integration test for auto-delete timer in private messages. 2021-03-01 17:13:45 -03:00
akwizgran
dba85debfa Add auto-deletion timer to private messages. 2021-03-01 17:13:45 -03:00
558 changed files with 13207 additions and 16757 deletions

View File

@@ -31,6 +31,15 @@
<option name="PACKAGES_TO_USE_STAR_IMPORTS"> <option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value /> <value />
</option> </option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="java" alias="false" withSubpackages="true" />
<package name="javax" alias="false" withSubpackages="true" />
<package name="kotlin" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value>
</option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" /> <option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" /> <option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />

View File

@@ -7,6 +7,7 @@
<w>encrypter</w> <w>encrypter</w>
<w>identicon</w> <w>identicon</w>
<w>introducee</w> <w>introducee</w>
<w>introducees</w>
<w>introducer</w> <w>introducer</w>
<w>onboarding</w> <w>onboarding</w>
</words> </words>

View File

@@ -8,15 +8,11 @@ android {
compileSdkVersion 30 compileSdkVersion 30
buildToolsVersion '30.0.2' buildToolsVersion '30.0.2'
packagingOptions {
doNotStrip '**/*.so'
}
defaultConfig { defaultConfig {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 29 targetSdkVersion 29
versionCode 10218 versionCode 10216
versionName "1.2.18" versionName "1.2.16"
consumerProguardFiles 'proguard-rules.txt' consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -50,10 +46,10 @@ dependencies {
compileOnly 'javax.annotation:jsr250-api:1.0' compileOnly 'javax.annotation:jsr250-api:1.0'
testImplementation project(path: ':bramble-api', configuration: 'testOutput') testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation "junit:junit:$junit_version" testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:$jmock_version" testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:$jmock_version" testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-imposters:$jmock_version" testImplementation "org.jmock:jmock-legacy:2.8.2"
} }
def torBinariesDir = 'src/main/res/raw' def torBinariesDir = 'src/main/res/raw'

View File

@@ -175,11 +175,6 @@ class AndroidBluetoothPlugin
} catch (IOException e) { } catch (IOException e) {
IoUtils.tryToClose(s, LOG, WARNING); IoUtils.tryToClose(s, LOG, WARNING);
throw e; throw e;
} catch (NullPointerException e) {
// BluetoothSocket#connect() may throw an NPE under unknown
// circumstances
IoUtils.tryToClose(s, LOG, WARNING);
throw new IOException(e);
} }
} }

View File

@@ -114,8 +114,12 @@ public class AndroidUtils {
/** /**
* Returns an array of supported content types for image attachments. * Returns an array of supported content types for image attachments.
* GIFs can't be compressed on API < 24 so they're not supported.
* <p>
* TODO: Remove this restriction when large message support is added
*/ */
public static String[] getSupportedImageContentTypes() { public static String[] getSupportedImageContentTypes() {
return new String[] {"image/jpeg", "image/png", "image/gif"}; if (SDK_INT < 24) return new String[] {"image/jpeg", "image/png"};
else return new String[] {"image/jpeg", "image/png", "image/gif"};
} }
} }

View File

@@ -9,7 +9,7 @@ import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.imposters.ByteBuddyClassImposteriser; import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -44,7 +44,7 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
private AndroidAccountManager accountManager; private AndroidAccountManager accountManager;
public AndroidAccountManagerTest() { public AndroidAccountManagerTest() {
context.setImposteriser(ByteBuddyClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
app = context.mock(Application.class); app = context.mock(Application.class);
applicationInfo = new ApplicationInfo(); applicationInfo = new ApplicationInfo();
applicationInfo.dataDir = testDir.getAbsolutePath(); applicationInfo.dataDir = testDir.getAbsolutePath();

View File

@@ -1,39 +1,38 @@
dependencyVerification { dependencyVerification {
verify = [ verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.android.tools.analytics-library:protos:27.2.2:protos-27.2.2.jar:02482564443c294dfe87c5f2b25387f724a698a09ed58e0cf0127400caa35a19', 'com.android.tools.analytics-library:protos:27.1.1:protos-27.1.1.jar:13f77e73762e58ab372d140b3a6be6903aea9775b62dd14fbc62d4cc7069c9a4',
'com.android.tools.analytics-library:shared:27.2.2:shared-27.2.2.jar:0efe017ca17ee775c5af386475a09799a1282faa04821d54810c1a34f6348d9c', 'com.android.tools.analytics-library:shared:27.1.1:shared-27.1.1.jar:82930a52001410e97d809930b670f4de3002286975f046b9de5f6b777b06d366',
'com.android.tools.analytics-library:tracker:27.2.2:tracker-27.2.2.jar:62489d84192dc06219664945c43201654ff85c3b715f46550751512a880d0e39', 'com.android.tools.analytics-library:tracker:27.1.1:tracker-27.1.1.jar:31bc5a00be0055bac89c9b2f34751883e987cd89e3ac1783720645c164f591d9',
'com.android.tools.build:aapt2-proto:4.1.0-alpha01-6193524:aapt2-proto-4.1.0-alpha01-6193524.jar:17e75523e1e92dd4f222c7368ee41df9e964a508232f591e265d0c499baf9dca', 'com.android.tools.build:aapt2-proto:4.1.0-alpha01-6193524:aapt2-proto-4.1.0-alpha01-6193524.jar:17e75523e1e92dd4f222c7368ee41df9e964a508232f591e265d0c499baf9dca',
'com.android.tools.build:apksig:4.2.2:apksig-4.2.2.jar:632690bf641b429dcb31650e6b2f6a2e87c4ac8afd45a6ba3cbc99fb1612178f', 'com.android.tools.build:apksig:4.1.1:apksig-4.1.1.jar:e0a69da9e5a03986d608b45bbf954ef0e6a0b3f58c1b8315bd169ec08b279e72',
'com.android.tools.build:apkzlib:4.2.2:apkzlib-4.2.2.jar:3b5167c1265e97f65201c4d2be6a6f72165a3aa2fe9e0594a59b67af9e9e97b9', 'com.android.tools.build:apkzlib:4.1.1:apkzlib-4.1.1.jar:ba4b5e419b6be0130eae7f8301c3a551ad3976f487d2e0c6852ebb175ac41127',
'com.android.tools.build:builder-model:4.2.2:builder-model-4.2.2.jar:41868de0cb88ae70b828eee4191c13e0233f433abb1becdf6a2bd391bd446bc0', 'com.android.tools.build:builder-model:4.1.1:builder-model-4.1.1.jar:e95c99cc298ad67b8deb6ced99c51abc8f59afebedad044b1a10dde14646a4dd',
'com.android.tools.build:builder-test-api:4.2.2:builder-test-api-4.2.2.jar:2f305c6d3a7b637d736b821bad372dcabd959e979f2065a9f65bac1e7b4d1875', 'com.android.tools.build:builder-test-api:4.1.1:builder-test-api-4.1.1.jar:464f596ab261c051c3847406748e843770dea123f6fa5fee8a9390644e709b7a',
'com.android.tools.build:builder:4.2.2:builder-4.2.2.jar:40fedd0d16db8f34ddb4eaf812d966b90ef1764f65cf119030442823bcf995cd', 'com.android.tools.build:builder:4.1.1:builder-4.1.1.jar:0f78d4759d2f7b57b95865522ec34596ba419b9982f3b25e3449213f9c98b80d',
'com.android.tools.build:gradle-api:4.2.2:gradle-api-4.2.2.jar:dd4ef35bbbfb8fc2d20e3311c76b516bc1672e82b61cb3a59fc877da0f9b4f61', 'com.android.tools.build:gradle-api:4.1.1:gradle-api-4.1.1.jar:d42e6b539e4c1353ad3546e75ec8ce11a017b97481023e8ea18577eefe374358',
'com.android.tools.build:manifest-merger:27.2.2:manifest-merger-27.2.2.jar:971974756f32d9e94c857d92772b1499b0b0f5d9c70cb8ebbd20d9bbf804a923', 'com.android.tools.build:manifest-merger:27.1.1:manifest-merger-27.1.1.jar:7a45fa143687859bb2e5a961dcf6ee88094d3853de0cb543dc03dbcb0f4b554b',
'com.android.tools.ddms:ddmlib:27.2.2:ddmlib-27.2.2.jar:9ab0f9b58737c316af454184705854c75936ca3531f21acc29bd68a3343334d1', 'com.android.tools.ddms:ddmlib:27.1.1:ddmlib-27.1.1.jar:da6e4bd834b6a85dae8019039849d8bd96933347dfbf460df74913ddade6e40a',
'com.android.tools.external.com-intellij:intellij-core:27.2.2:intellij-core-27.2.2.jar:01619d5dc28ec909cbdee699f1f13056e84462faf6dccf4817561293fb28bef0', 'com.android.tools.external.com-intellij:intellij-core:27.1.1:intellij-core-27.1.1.jar:2591a7363c4443c59bf9f793730acafce9d6ec3076e2f46716edaf53a41b6fb6',
'com.android.tools.external.com-intellij:kotlin-compiler:27.2.2:kotlin-compiler-27.2.2.jar:71bd460199ce7293ecc54b91a115319c1e4b585eca5a5b3699f6a406f29e626c', 'com.android.tools.external.com-intellij:kotlin-compiler:27.1.1:kotlin-compiler-27.1.1.jar:5054ae770ba788f110303c65abd6b1fa28eccf52dee1274510e201b2b81885c8',
'com.android.tools.external.org-jetbrains:uast:27.2.2:uast-27.2.2.jar:efa59302fd433015e993143530cecb456b63d10d0b89bd1d3b1a016904338a65', 'com.android.tools.external.org-jetbrains:uast:27.1.1:uast-27.1.1.jar:54cd8f6886a9d2f5641659dd5c91f626629672cd48301f7f0bd6aad9bd448714',
'com.android.tools.layoutlib:layoutlib-api:27.2.2:layoutlib-api-27.2.2.jar:f0901f2295d814e82ad95850ea2103dd89d8489e01727fafa55ccccc0dccd163', 'com.android.tools.layoutlib:layoutlib-api:27.1.1:layoutlib-api-27.1.1.jar:8a9a22e3b309521ea83b724e5a89cfdac6076f52d675c0e17d77b05527bc0f8c',
'com.android.tools.lint:lint-api:27.2.2:lint-api-27.2.2.jar:1ecb5959c8e624ee49cdf9178de67bb0e823b4382ed253410eb36afe5c458b05', 'com.android.tools.lint:lint-api:27.1.1:lint-api-27.1.1.jar:c1d8176094cb0478786070d40533efb578ebc53529a82f6ef5bee879bdca418b',
'com.android.tools.lint:lint-checks:27.2.2:lint-checks-27.2.2.jar:989e545a6b5e398e63a9f3608da02d6111f2241faec1baa0a3b4492cb03aeaf2', 'com.android.tools.lint:lint-checks:27.1.1:lint-checks-27.1.1.jar:3899c91e00bd059b40c31a9ca00cd0f8303191947608735ae1b657323693fb61',
'com.android.tools.lint:lint-gradle-api:27.2.2:lint-gradle-api-27.2.2.jar:2be9c69d6fbbfb012ff6521fdfcb22eb7cfaa57d108e07bb1d4143dae9c1b433', 'com.android.tools.lint:lint-gradle-api:27.1.1:lint-gradle-api-27.1.1.jar:26aa89d38b9825cc73229daa82a68875801c8b8491f30497ce62aff1f206eb0d',
'com.android.tools.lint:lint-gradle:27.2.2:lint-gradle-27.2.2.jar:742dedd5ccb459a245a35bf4fa16dfecc762da1a6b1741332cfe5228e812301a', 'com.android.tools.lint:lint-gradle:27.1.1:lint-gradle-27.1.1.jar:f7355823ead869f4d28184ba28b7a0c693b507519a2d3705bb9848a0f35b3756',
'com.android.tools.lint:lint-model:27.2.2:lint-model-27.2.2.jar:ee31012586462bea2d591b6175934e5f29b6f781a78fda50f79387972364b9ab', 'com.android.tools.lint:lint-model:27.1.1:lint-model-27.1.1.jar:bc23c0c413bdfca59dac2cd56b870d8360d009e9ec0d365e71f774bcf127971d',
'com.android.tools.lint:lint:27.2.2:lint-27.2.2.jar:7247016af7fba8cabee6ae887515b144f5a2ff7823422654daf23be9202f8fb1', 'com.android.tools.lint:lint:27.1.1:lint-27.1.1.jar:2f6038a5398a42bd591883c3f5e5894f4ec52ca1c3683bf94fa8553c1700af81',
'com.android.tools:annotations:27.2.2:annotations-27.2.2.jar:9375fb2df5c0cf1b46fef9e65b3a27ac88925ccf90054b19ae0ca0adc7036fe1', 'com.android.tools:annotations:27.1.1:annotations-27.1.1.jar:ff28c504d2acb9fd1a5ffbd97ae85cf59ee18c76927525aad250509bccf2cab1',
'com.android.tools:common:27.2.2:common-27.2.2.jar:a76f4e10cad39bed317be031fee915d280aa8bc11616c58ab94e051b1e38769d', 'com.android.tools:common:27.1.1:common-27.1.1.jar:63d9a2a9ad6d278db319f3749b9f50bdf5457ef7020074a1bebe124e714b535c',
'com.android.tools:dvlib:27.2.2:dvlib-27.2.2.jar:9931c6b57460b5f8cc2613ca5ff8596aa089a67655ace13d173f90538ecb4301', 'com.android.tools:dvlib:27.1.1:dvlib-27.1.1.jar:998a54201fc1cefee5f2399215e95c42b1f64f9e1d8f4452eb8255c68ba5440f',
'com.android.tools:repository:27.2.2:repository-27.2.2.jar:ac5f9b19dc5d9d08e80b57da76059f5760ca76c221e40ffd4bf43d7b13991674', 'com.android.tools:repository:27.1.1:repository-27.1.1.jar:d25b74ccabf4d876903efb375e9af6fb380d8ae0445bb74bbdcc225c1e37fa1d',
'com.android.tools:sdk-common:27.2.2:sdk-common-27.2.2.jar:b147acc13850808d61fc391ccfeeebdf90841b461a7042acb2d92e466da8e674', 'com.android.tools:sdk-common:27.1.1:sdk-common-27.1.1.jar:4473ae97d0ef7061ee1de61041d5aa97405ae08e44c09cf7bb278b42e4b97c7c',
'com.android.tools:sdklib:27.2.2:sdklib-27.2.2.jar:fae0bafbe8b4f546cf64986a22b7d8ed108d45519366ff22f0170a9cf3ea7f34', 'com.android.tools:sdklib:27.1.1:sdklib-27.1.1.jar:08e6b83961ac9724b3c1e3d0eff971f13be6701292c77914b8794480f3391250',
'com.android:signflinger:4.2.2:signflinger-4.2.2.jar:4d7aafd9666707b483b1ad2c466824287cf2e379dda1d204dd3b7e453ffcf760', 'com.android:signflinger:4.1.1:signflinger-4.1.1.jar:0c66825988873ec2d51057fa463f54a8f18fc7326ff4530b9da363b71e97ce60',
'com.android:zipflinger:4.2.2:zipflinger-4.2.2.jar:8e4677086c9a8f4a67374a4edc31db7e481f0d9b85907263c51ca72452c23a93', 'com.android:zipflinger:4.1.1:zipflinger-4.1.1.jar:0a8c3e52ac13dd031236f9fb5ba4408b1d5dcd12325a05440b36da09d8881446',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.code.gson:gson:2.8.6:gson-2.8.6.jar:c8fb4839054d280b3033f800d1f5a97de2f028eb8ba2eb458ad287e536f3f25f', 'com.google.code.gson:gson:2.8.5:gson-2.8.5.jar:233a0149fc365c9f6edbd683cfe266b19bdc773be98eabdaf6b3c924b48e7d81',
'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f', 'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f',
'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a', 'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a',
'com.google.dagger:dagger-spi:2.24:dagger-spi-2.24.jar:c038445d14dbcb4054e61bf49e05009edf26fce4fdc7ec1a9db544784f68e718', 'com.google.dagger:dagger-spi:2.24:dagger-spi-2.24.jar:c038445d14dbcb4054e61bf49e05009edf26fce4fdc7ec1a9db544784f68e718',
@@ -54,28 +53,26 @@ dependencyVerification {
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90', 'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0', 'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce', 'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
'com.sun.istack:istack-commons-runtime:3.0.8:istack-commons-runtime-3.0.8.jar:4ffabb06be454a05e4398e20c77fa2b6308d4b88dfbef7ca30a76b5b7d5505ef', 'com.sun.istack:istack-commons-runtime:3.0.7:istack-commons-runtime-3.0.7.jar:6443e10ba2e259fb821d9b6becf10db5316285fc30c53cec9d7b19a3877e7fdf',
'com.sun.xml.fastinfoset:FastInfoset:1.2.16:FastInfoset-1.2.16.jar:056f3a1e144409f21ed16afc26805f58e9a21f3fce1543c42d400719d250c511', 'com.sun.xml.fastinfoset:FastInfoset:1.2.15:FastInfoset-1.2.15.jar:785861db11ca1bd0d1956682b974ad73eb19cd3e01a4b3fa82d62eca97210aec',
'commons-codec:commons-codec:1.10:commons-codec-1.10.jar:4241dfa94e711d435f29a4604a3e2de5c4aa3c165e23bd066be6fc1fc4309569', 'commons-codec:commons-codec:1.10:commons-codec-1.10.jar:4241dfa94e711d435f29a4604a3e2de5c4aa3c165e23bd066be6fc1fc4309569',
'commons-logging:commons-logging:1.2:commons-logging-1.2.jar:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636', 'commons-logging:commons-logging:1.2:commons-logging-1.2.jar:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636',
'it.unimi.dsi:fastutil:8.4.0:fastutil-8.4.0.jar:2ad2824a4a0a0eb836b52ee2fc84ba2134f44bce7bfa54015ae3f31c710a3071', 'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
'jakarta.activation:jakarta.activation-api:1.2.1:jakarta.activation-api-1.2.1.jar:8b0a0f52fa8b05c5431921a063ed866efaa41dadf2e3a7ee3e1961f2b0d9645b', 'javax.activation:javax.activation-api:1.2.0:javax.activation-api-1.2.0.jar:43fdef0b5b6ceb31b0424b208b930c74ab58fac2ceeb7b3f6fd3aeb8b5ca4393',
'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2:jakarta.xml.bind-api-2.3.2.jar:69156304079bdeed9fc0ae3b39389f19b3cc4ba4443bc80508995394ead742ea',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f', 'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'javax.xml.bind:jaxb-api:2.3.1:jaxb-api-2.3.1.jar:88b955a0df57880a26a74708bc34f74dcaf8ebf4e78843a28b50eae945732b06',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a', 'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
'net.java.dev.jna:jna-platform:5.6.0:jna-platform-5.6.0.jar:9ecea8bf2b1b39963939d18b70464eef60c508fed8820f9dcaba0c35518eabf7',
'net.java.dev.jna:jna:5.6.0:jna-5.6.0.jar:5557e235a8aa2f9766d5dc609d67948f2a8832c2d796cea9ef1d6cbe0b3b7eaf',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd', 'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5', 'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2', 'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047', 'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6', 'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
'org.apache.httpcomponents:httpclient:4.5.6:httpclient-4.5.6.jar:c03f813195e7a80e3608d0ddd8da80b21696a4c92a6a2298865bf149071551c7', 'org.apache.httpcomponents:httpclient:4.5.6:httpclient-4.5.6.jar:c03f813195e7a80e3608d0ddd8da80b21696a4c92a6a2298865bf149071551c7',
'org.apache.httpcomponents:httpcore:4.4.10:httpcore-4.4.10.jar:78ba1096561957db1b55200a159b648876430342d15d461277e62360da19f6fd', 'org.apache.httpcomponents:httpcore:4.4.10:httpcore-4.4.10.jar:78ba1096561957db1b55200a159b648876430342d15d461277e62360da19f6fd',
'org.apache.httpcomponents:httpmime:4.5.6:httpmime-4.5.6.jar:0b2b1102c18d3c7e05a77214b9b7501a6f6056174ae5604e0e256776eda7553e', 'org.apache.httpcomponents:httpmime:4.5.6:httpmime-4.5.6.jar:0b2b1102c18d3c7e05a77214b9b7501a6f6056174ae5604e0e256776eda7553e',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca', 'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349', 'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
'org.briarproject:obfs4proxy-android:0.0.12-dev-40245c4a:obfs4proxy-android-0.0.12-dev-40245c4a.zip:8ab05a8f8391be2cb5ab2b665c281a06d9e3a756bd0f95a40a36ca927866ea82', 'org.briarproject:obfs4proxy-android:0.0.12-dev-40245c4a:obfs4proxy-android-0.0.12-dev-40245c4a.zip:8ab05a8f8391be2cb5ab2b665c281a06d9e3a756bd0f95a40a36ca927866ea82',
@@ -86,32 +83,28 @@ dependencyVerification {
'org.codehaus.groovy:groovy-all:2.4.15:groovy-all-2.4.15.jar:51d6c4e71782e85674239189499854359d380fb75e1a703756e3aaa5b98a5af0', 'org.codehaus.groovy:groovy-all:2.4.15:groovy-all-2.4.15.jar:51d6c4e71782e85674239189499854359d380fb75e1a703756e3aaa5b98a5af0',
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53', 'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
'org.codehaus.mojo:animal-sniffer-annotations:1.18:animal-sniffer-annotations-1.18.jar:47f05852b48ee9baefef80fa3d8cea60efa4753c0013121dd7fe5eef2e5c729d', 'org.codehaus.mojo:animal-sniffer-annotations:1.18:animal-sniffer-annotations-1.18.jar:47f05852b48ee9baefef80fa3d8cea60efa4753c0013121dd7fe5eef2e5c729d',
'org.glassfish.jaxb:jaxb-runtime:2.3.2:jaxb-runtime-2.3.2.jar:e6e0a1e89fb6ff786279e6a0082d5cef52dc2ebe67053d041800737652b4fd1b', 'org.glassfish.jaxb:jaxb-runtime:2.3.1:jaxb-runtime-2.3.1.jar:45fecfa5c8217ce1f3652ab95179790ec8cc0dec0384bca51cbeb94a293d9f2f',
'org.glassfish.jaxb:txw2:2.3.2:txw2-2.3.2.jar:4a6a9f483388d461b81aa9a28c685b8b74c0597993bf1884b04eddbca95f48fe', 'org.glassfish.jaxb:txw2:2.3.1:txw2-2.3.1.jar:34975dde1c6920f1a39791142235689bc3cd357e24d05edd8ff93b885bd68d60',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9', 'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21', 'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050', 'org.jetbrains.kotlin:kotlin-reflect:1.3.72:kotlin-reflect-1.3.72.jar:a188d9367de1c4ee9479db630985c0597b20709c83161b1430d24edb27e38c40',
'org.jetbrains.intellij.deps:trove4j:1.0.20181211:trove4j-1.0.20181211.jar:affb7c85a3c87bdcf69ff1dbb84de11f63dc931293934bc08cd7ab18de083601', 'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72:kotlin-stdlib-common-1.3.72.jar:5e7d1552863e480c1628b1cc39ce230ef829f5b7230106215a05acda5172203a',
'org.jetbrains.kotlin:kotlin-reflect:1.4.31:kotlin-reflect-1.4.31.jar:91fad0b42974a7d5811e30a61f05706e176b144235717c6de7e81e3a781028f2', 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72:kotlin-stdlib-jdk7-1.3.72.jar:40566c0c08d414b9413ba556ff7f8a0b04b98b9f0f424d122dd2088510efccc4',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.31:kotlin-stdlib-common-1.4.31.jar:57962f44371a746b678218a0802a8712c6255206de9a69ede215e3aa4b044708', 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72:kotlin-stdlib-jdk8-1.3.72.jar:133da70cfc07b56094282eac5c59bccd59f167ee2ead22e5282876d8bc10bf95',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.31:kotlin-stdlib-jdk7-1.4.31.jar:1f966e54e86cf4b7d7014afdce04e0f3ee4625084cda3494edccc7b84af52664', 'org.jetbrains.kotlin:kotlin-stdlib:1.3.72:kotlin-stdlib-1.3.72.jar:3856a7349ebacd6d1be6802b2fed9c4dc2c5a564ea92b6b945ac988243d4b16b',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.31:kotlin-stdlib-jdk8-1.4.31.jar:b2f8364435ebcb0106ff9d4415a11ffdef8ec7786ee6e5ed465a01556cbd1683', 'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.31:kotlin-stdlib-1.4.31.jar:76a599d88b167e8ac90879b6daa722c6ad3452ba714c9aba19bd196544b97f1c',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478', 'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09', 'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b', 'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd', 'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04', 'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be', 'org.jvnet.staxex:stax-ex:1.8:stax-ex-1.8.jar:95b05d9590af4154c6513b9c5dc1fb2e55b539972ba0a9ef28e9a0c01d83ad77',
'org.jvnet.staxex:stax-ex:1.8.1:stax-ex-1.8.1.jar:20522549056e9e50aa35ef0b445a2e47a53d06be0b0a9467d704e2483ffb049a', 'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm-analysis:7.0:asm-analysis-7.0.jar:e981f8f650c4d900bb033650b18e122fa6b161eadd5f88978d08751f72ee8474', 'org.ow2.asm:asm-analysis:7.0:asm-analysis-7.0.jar:e981f8f650c4d900bb033650b18e122fa6b161eadd5f88978d08751f72ee8474',
'org.ow2.asm:asm-commons:7.0:asm-commons-7.0.jar:fed348ef05958e3e846a3ac074a12af5f7936ef3d21ce44a62c4fa08a771927d', 'org.ow2.asm:asm-commons:7.0:asm-commons-7.0.jar:fed348ef05958e3e846a3ac074a12af5f7936ef3d21ce44a62c4fa08a771927d',
'org.ow2.asm:asm-tree:7.0:asm-tree-7.0.jar:cfd7a0874f9de36a999c127feeadfbfe6e04d4a71ee954d7af3d853f0be48a6c', 'org.ow2.asm:asm-tree:7.0:asm-tree-7.0.jar:cfd7a0874f9de36a999c127feeadfbfe6e04d4a71ee954d7af3d853f0be48a6c',
'org.ow2.asm:asm-util:7.0:asm-util-7.0.jar:75fbbca440ef463f41c2b0ab1a80abe67e910ac486da60a7863cbcb5bae7e145', 'org.ow2.asm:asm-util:7.0:asm-util-7.0.jar:75fbbca440ef463f41c2b0ab1a80abe67e910ac486da60a7863cbcb5bae7e145',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.ow2.asm:asm:7.0:asm-7.0.jar:b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf', 'org.ow2.asm:asm:7.0:asm-7.0.jar:b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'xerces:xercesImpl:2.12.0:xercesImpl-2.12.0.jar:b50d3a4ca502faa4d1c838acb8aa9480446953421f7327e338c5dda3da5e76d0',
'xml-apis:xml-apis:1.4.01:xml-apis-1.4.01.jar:a840968176645684bb01aed376e067ab39614885f9eee44abe35a5f20ebe7fad',
] ]
} }

View File

@@ -10,9 +10,10 @@ dependencies {
implementation "com.google.dagger:dagger:2.24" implementation "com.google.dagger:dagger:2.24"
implementation 'com.google.code.findbugs:jsr305:3.0.2' implementation 'com.google.code.findbugs:jsr305:3.0.2'
testImplementation "junit:junit:$junit_version" testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:$jmock_version" testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:$jmock_version" testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
signature 'org.codehaus.mojo.signature:java16:1.1@signature' signature 'org.codehaus.mojo.signature:java16:1.1@signature'
} }

View File

@@ -9,4 +9,5 @@ public interface FeatureFlags {
boolean shouldEnableProfilePictures(); boolean shouldEnableProfilePictures();
boolean shouldEnableDisappearingMessages();
} }

View File

@@ -2,7 +2,6 @@ package org.briarproject.bramble.api.account;
import org.briarproject.bramble.api.crypto.DecryptionException; import org.briarproject.bramble.api.crypto.DecryptionException;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@@ -44,17 +43,6 @@ public interface AccountManager {
*/ */
boolean createAccount(String name, String password); boolean createAccount(String name, String password);
/**
* Restores a given identity by registering it with the
* {@link IdentityManager}. Creates a database key, encrypts it with the
* given password and stores it on disk. {@link #accountExists()} will
* return true after this method returns true.
* @param identity
* @param password
* @return
*/
boolean restoreAccount(Identity identity, String password);
/** /**
* Deletes all account state from disk. {@link #accountExists()} will * Deletes all account state from disk. {@link #accountExists()} will
* return false after this method returns. * return false after this method returns.

View File

@@ -0,0 +1,29 @@
package org.briarproject.bramble.api.cleanup;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import java.util.Collection;
/**
* An interface for registering a hook with the {@link CleanupManager}
* that will be called when a message's cleanup deadline is reached.
*/
@NotNullByDefault
public interface CleanupHook {
/**
* Called when the cleanup deadlines of one or more messages are reached.
* <p>
* The callee is not required to delete the messages, but the hook won't be
* called again for these messages unless another cleanup timer is set (see
* {@link DatabaseComponent#setCleanupTimerDuration(Transaction, MessageId, long)}
* and {@link DatabaseComponent#startCleanupTimer(Transaction, MessageId)}).
*/
void deleteMessages(Transaction txn, GroupId g,
Collection<MessageId> messageIds) throws DbException;
}

View File

@@ -0,0 +1,42 @@
package org.briarproject.bramble.api.cleanup;
import org.briarproject.bramble.api.cleanup.event.CleanupTimerStartedEvent;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.MessageId;
/**
* The CleanupManager is responsible for tracking the cleanup deadlines of
* messages and passing them to their respective
* {@link CleanupHook CleanupHooks} when the deadlines are reached.
* <p>
* The CleanupManager responds to
* {@link CleanupTimerStartedEvent CleanupTimerStartedEvents} broadcast by the
* {@link DatabaseComponent}.
* <p>
* See {@link DatabaseComponent#setCleanupTimerDuration(Transaction, MessageId, long)},
* {@link DatabaseComponent#startCleanupTimer(Transaction, MessageId)},
* {@link DatabaseComponent#stopCleanupTimer(Transaction, MessageId)}.
*/
@NotNullByDefault
public interface CleanupManager {
/**
* When scheduling a cleanup task we overshoot the deadline by this many
* milliseconds to reduce the number of tasks that need to be scheduled
* when messages have cleanup deadlines that are close together.
*/
long BATCH_DELAY_MS = 1000;
/**
* Registers a hook to be called when messages are due for cleanup.
* This method should be called before
* {@link LifecycleManager#startServices(SecretKey)}.
*/
void registerCleanupHook(ClientId c, int majorVersion,
CleanupHook hook);
}

View File

@@ -0,0 +1,32 @@
package org.briarproject.bramble.api.cleanup.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.MessageId;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a message's cleanup timer is started.
*/
@Immutable
@NotNullByDefault
public class CleanupTimerStartedEvent extends Event {
private final MessageId messageId;
private final long cleanupDeadline;
public CleanupTimerStartedEvent(MessageId messageId,
long cleanupDeadline) {
this.messageId = messageId;
this.cleanupDeadline = cleanupDeadline;
}
public MessageId getMessageId() {
return messageId;
}
public long getCleanupDeadline() {
return cleanupDeadline;
}
}

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.api.client; package org.briarproject.bramble.api.client;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
@@ -16,6 +17,7 @@ import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.Collection;
import java.util.Map; import java.util.Map;
@NotNullByDefault @NotNullByDefault
@@ -50,9 +52,11 @@ public interface ClientHelper {
BdfDictionary getGroupMetadataAsDictionary(Transaction txn, GroupId g) BdfDictionary getGroupMetadataAsDictionary(Transaction txn, GroupId g)
throws DbException, FormatException; throws DbException, FormatException;
Collection<MessageId> getMessageIds(Transaction txn, GroupId g,
BdfDictionary query) throws DbException, FormatException;
BdfDictionary getMessageMetadataAsDictionary(MessageId m) BdfDictionary getMessageMetadataAsDictionary(MessageId m)
throws DbException, throws DbException, FormatException;
FormatException;
BdfDictionary getMessageMetadataAsDictionary(Transaction txn, MessageId m) BdfDictionary getMessageMetadataAsDictionary(Transaction txn, MessageId m)
throws DbException, FormatException; throws DbException, FormatException;
@@ -119,4 +123,17 @@ public interface ClientHelper {
Map<TransportId, TransportProperties> parseAndValidateTransportPropertiesMap( Map<TransportId, TransportProperties> parseAndValidateTransportPropertiesMap(
BdfDictionary properties) throws FormatException; BdfDictionary properties) throws FormatException;
/**
* Retrieves the contact ID from the group metadata of the given contact
* group.
*/
ContactId getContactId(Transaction txn, GroupId contactGroupId)
throws DbException, FormatException;
/**
* Stores the given contact ID in the group metadata of the given contact
* group.
*/
void setContactId(Transaction txn, GroupId contactGroupId, ContactId c)
throws DbException;
} }

View File

@@ -0,0 +1,9 @@
package org.briarproject.bramble.api.client;
public interface ContactGroupConstants {
/**
* Group metadata key for associating a contact ID with a contact group.
*/
String GROUP_KEY_CONTACT_ID = "contactId";
}

View File

@@ -1,9 +0,0 @@
package org.briarproject.bramble.api.contact;
/**
* Record types for the contact exchange protocol.
*/
public interface ContactExchangeRecordTypes {
byte CONTACT_INFO = 0;
}

View File

@@ -3,7 +3,6 @@ package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.Pair; import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.UnsupportedVersionException; import org.briarproject.bramble.api.UnsupportedVersionException;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.ContactExistsException; import org.briarproject.bramble.api.db.ContactExistsException;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
@@ -49,10 +48,6 @@ public interface ContactManager {
SecretKey rootKey, long timestamp, boolean alice, boolean verified, SecretKey rootKey, long timestamp, boolean alice, boolean verified,
boolean active) throws DbException; boolean active) throws DbException;
ContactId addContact(Transaction txn, Author remote, AuthorId local,
PublicKey handshake, boolean verified)
throws DbException, GeneralSecurityException;
/** /**
* Stores a contact associated with the given local and remote pseudonyms, * Stores a contact associated with the given local and remote pseudonyms,
* replacing the given pending contact, derives and stores handshake mode * replacing the given pending contact, derives and stores handshake mode
@@ -210,19 +205,6 @@ public interface ContactManager {
void setContactAlias(ContactId c, @Nullable String alias) void setContactAlias(ContactId c, @Nullable String alias)
throws DbException; throws DbException;
/**
* Sets the contact's handshake public key
*/
void setHandshakePublicKey(Transaction txn, ContactId c,
PublicKey handshakePublicKey) throws DbException,
GeneralSecurityException;
/**
* Sets the contact's handshake public key
*/
void setHandshakePublicKey(ContactId c, PublicKey handshakePublicKey)
throws DbException, GeneralSecurityException;
/** /**
* Returns true if a contact with this {@code remoteAuthorId} belongs to * Returns true if a contact with this {@code remoteAuthorId} belongs to
* the local pseudonym with this {@code localAuthorId}. * the local pseudonym with this {@code localAuthorId}.

View File

@@ -24,19 +24,6 @@ public interface HandshakeManager {
HandshakeResult handshake(PendingContactId p, InputStream in, HandshakeResult handshake(PendingContactId p, InputStream in,
StreamWriter out) throws DbException, IOException; StreamWriter out) throws DbException, IOException;
/**
* Handshakes with the given contact. Returns an ephemeral master key
* authenticated with both parties' handshake key pairs and a flag
* indicating whether the local peer is Alice or Bob.
*
* @param in An incoming stream for the handshake, which must be secured in
* handshake mode
* @param out An outgoing stream for the handshake, which must be secured
* in handshake mode
*/
HandshakeResult handshake(ContactId c, InputStream in, StreamWriter out)
throws DbException, IOException;
class HandshakeResult { class HandshakeResult {
private final SecretKey masterKey; private final SecretKey masterKey;

View File

@@ -41,6 +41,18 @@ import javax.annotation.Nullable;
@NotNullByDefault @NotNullByDefault
public interface DatabaseComponent extends TransactionManager { public interface DatabaseComponent extends TransactionManager {
/**
* Return value for {@link #getNextCleanupDeadline(Transaction)} if
* no messages are scheduled to be deleted.
*/
long NO_CLEANUP_DEADLINE = -1;
/**
* Return value for {@link #startCleanupTimer(Transaction, MessageId)}
* if the cleanup timer was not started.
*/
long TIMER_NOT_STARTED = -1;
/** /**
* Opens the database and returns true if the database already existed. * Opens the database and returns true if the database already existed.
* *
@@ -288,6 +300,16 @@ public interface DatabaseComponent extends TransactionManager {
Collection<MessageId> getMessageIds(Transaction txn, GroupId g) Collection<MessageId> getMessageIds(Transaction txn, GroupId g)
throws DbException; throws DbException;
/**
* Returns the IDs of any delivered messages in the given group with
* metadata that matches all entries in the given query. If the query is
* empty, the IDs of all delivered messages are returned.
* <p/>
* Read-only.
*/
Collection<MessageId> getMessageIds(Transaction txn, GroupId g,
Metadata query) throws DbException;
/** /**
* Returns the IDs of any messages that need to be validated. * Returns the IDs of any messages that need to be validated.
* <p/> * <p/>
@@ -314,6 +336,15 @@ public interface DatabaseComponent extends TransactionManager {
Collection<MessageId> getMessagesToShare(Transaction txn) Collection<MessageId> getMessagesToShare(Transaction txn)
throws DbException; throws DbException;
/**
* Returns the IDs of any messages of any messages that are due for
* deletion, along with their group IDs.
* <p/>
* Read-only.
*/
Map<GroupId, Collection<MessageId>> getMessagesToDelete(Transaction txn)
throws DbException;
/** /**
* Returns the metadata for all delivered messages in the given group. * Returns the metadata for all delivered messages in the given group.
* <p/> * <p/>
@@ -395,6 +426,15 @@ public interface DatabaseComponent extends TransactionManager {
MessageStatus getMessageStatus(Transaction txn, ContactId c, MessageId m) MessageStatus getMessageStatus(Transaction txn, ContactId c, MessageId m)
throws DbException; throws DbException;
/**
* Returns the next time (in milliseconds since the Unix epoch) when a
* message is due to be deleted, or {@link #NO_CLEANUP_DEADLINE}
* if no messages are scheduled to be deleted.
* <p/>
* Read-only.
*/
long getNextCleanupDeadline(Transaction txn) throws DbException;
/* /*
* Returns the next time (in milliseconds since the Unix epoch) when a * Returns the next time (in milliseconds since the Unix epoch) when a
* message is due to be sent to the given contact. The returned value may * message is due to be sent to the given contact. The returned value may
@@ -535,6 +575,13 @@ public interface DatabaseComponent extends TransactionManager {
void removeTransportKeys(Transaction txn, TransportId t, KeySetId k) void removeTransportKeys(Transaction txn, TransportId t, KeySetId k)
throws DbException; throws DbException;
/**
* Sets the cleanup timer duration for the given message. This does not
* start the message's cleanup timer.
*/
void setCleanupTimerDuration(Transaction txn, MessageId m, long duration)
throws DbException;
/** /**
* Marks the given contact as verified. * Marks the given contact as verified.
*/ */
@@ -546,11 +593,6 @@ public interface DatabaseComponent extends TransactionManager {
void setContactAlias(Transaction txn, ContactId c, @Nullable String alias) void setContactAlias(Transaction txn, ContactId c, @Nullable String alias)
throws DbException; throws DbException;
/**
* Sets the remote handshake public key for a given contact
*/
void setHandshakePublicKey(Transaction txn, ContactId c, PublicKey handshakePublicKey) throws DbException;
/** /**
* Sets the given group's visibility to the given contact. * Sets the given group's visibility to the given contact.
*/ */
@@ -562,6 +604,12 @@ public interface DatabaseComponent extends TransactionManager {
*/ */
void setMessagePermanent(Transaction txn, MessageId m) throws DbException; void setMessagePermanent(Transaction txn, MessageId m) throws DbException;
/**
* Marks the given message as not shared. This method is only meant for
* testing.
*/
void setMessageNotShared(Transaction txn, MessageId m) throws DbException;
/** /**
* Marks the given message as shared. * Marks the given message as shared.
*/ */
@@ -604,6 +652,22 @@ public interface DatabaseComponent extends TransactionManager {
void setTransportKeysActive(Transaction txn, TransportId t, KeySetId k) void setTransportKeysActive(Transaction txn, TransportId t, KeySetId k)
throws DbException; throws DbException;
/**
* Starts the cleanup timer for the given message, if a timer duration
* has been set and the timer has not already been started.
*
* @return The cleanup deadline, or {@link #TIMER_NOT_STARTED} if no
* timer duration has been set for this message or its timer has already
* been started.
*/
long startCleanupTimer(Transaction txn, MessageId m) throws DbException;
/**
* Stops the cleanup timer for the given message, if the timer has been
* started.
*/
void stopCleanupTimer(Transaction txn, MessageId m) throws DbException;
/** /**
* Stores the given transport keys, deleting any keys they have replaced. * Stores the given transport keys, deleting any keys they have replaced.
*/ */

View File

@@ -26,11 +26,6 @@ public interface IdentityManager {
*/ */
void registerIdentity(Identity i); void registerIdentity(Identity i);
/**
* Returns the cached local identity or loads it from the database.
*/
Identity getIdentity(Transaction txn) throws DbException;
/** /**
* Returns the cached local identity or loads it from the database. * Returns the cached local identity or loads it from the database.
*/ */

View File

@@ -74,13 +74,6 @@ public interface TransportPropertyManager {
TransportProperties getRemoteProperties(ContactId c, TransportId t) TransportProperties getRemoteProperties(ContactId c, TransportId t)
throws DbException; throws DbException;
/**
* Returns the remote transport properties for the given contact and
* transport.
*/
TransportProperties getRemoteProperties(Transaction txn, ContactId c,
TransportId t) throws DbException;
/** /**
* Merges the given properties with the existing local properties for the * Merges the given properties with the existing local properties for the
* given transport. * given transport.

View File

@@ -35,20 +35,6 @@ public interface KeyManager {
ContactId c, SecretKey rootKey, long timestamp, boolean alice, ContactId c, SecretKey rootKey, long timestamp, boolean alice,
boolean active) throws DbException; boolean active) throws DbException;
/**
* Derives and stores a set of rotation mode transport keys for
* communicating with the given contact over each transport and returns the
* key set IDs.
* <p/>
* {@link StreamContext StreamContexts} for the contact can be created
* after this method has returned.
*
* @param alice True if the local party is Alice
* @param active Whether the derived keys can be used for outgoing streams
*/
Map<TransportId, KeySetId> addRotationKeys(ContactId c, SecretKey rootKey,
long timestamp, boolean alice, boolean active) throws DbException;
/** /**
* Informs the key manager that a new contact has been added. Derives and * Informs the key manager that a new contact has been added. Derives and
* stores a set of handshake mode transport keys for communicating with the * stores a set of handshake mode transport keys for communicating with the

View File

@@ -6,7 +6,9 @@ import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault @NotNullByDefault
public class ValidationUtils { public class ValidationUtils {
@@ -64,4 +66,9 @@ public class ValidationUtils {
if (dictionary != null && dictionary.size() != size) if (dictionary != null && dictionary.size() != size)
throw new FormatException(); throw new FormatException();
} }
public static void checkRange(@Nullable Long l, long min, long max)
throws FormatException {
if (l != null && (l < min || l > max)) throw new FormatException();
}
} }

View File

@@ -0,0 +1,8 @@
package org.briarproject.bramble.test;
public interface TimeTravel {
void setCurrentTimeMillis(long now) throws InterruptedException;
void addCurrentTimeMillis(long add) throws InterruptedException;
}

View File

@@ -1,27 +1,24 @@
dependencyVerification { dependencyVerification {
verify = [ verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger:2.24:dagger-2.24.jar:550a6e46a6dfcdf1d764887b6090cea94f783327e50e5c73754f18facfc70b64', 'com.google.dagger:dagger:2.24:dagger-2.24.jar:550a6e46a6dfcdf1d764887b6090cea94f783327e50e5c73754f18facfc70b64',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a', 'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11', 'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0', 'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047', 'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619', 'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90', 'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52', 'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9', 'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21', 'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050', 'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09', 'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b', 'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd', 'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04', 'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d', 'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de', 'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
] ]
} }

View File

@@ -10,7 +10,7 @@ apply from: '../dagger.gradle'
dependencies { dependencies {
implementation project(path: ':bramble-api', configuration: 'default') implementation project(path: ':bramble-api', configuration: 'default')
implementation 'org.bouncycastle:bcprov-jdk15on:1.65' implementation 'com.madgag.spongycastle:core:1.58.0.0'
implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6 implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6
implementation 'org.bitlet:weupnp:0.1.4' implementation 'org.bitlet:weupnp:0.1.4'
implementation 'net.i2p.crypto:eddsa:0.2.0' implementation 'net.i2p.crypto:eddsa:0.2.0'
@@ -21,25 +21,16 @@ dependencies {
testImplementation project(path: ':bramble-api', configuration: 'testOutput') testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation 'org.hsqldb:hsqldb:2.3.5' // The last version that supports Java 1.6 testImplementation 'org.hsqldb:hsqldb:2.3.5' // The last version that supports Java 1.6
testImplementation 'net.jodah:concurrentunit:0.4.2' testImplementation 'junit:junit:4.12'
testImplementation "junit:junit:$junit_version" testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock:$jmock_version" testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-junit4:$jmock_version" testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation "org.jmock:jmock-imposters:$jmock_version"
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.24' testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.24'
signature 'org.codehaus.mojo.signature:java16:1.1@signature' signature 'org.codehaus.mojo.signature:java16:1.1@signature'
} }
animalsniffer {
// Allow requireNonNull: Android desugaring rewrites it (so it's safe for us to use),
// and it gets used when passing method references instead of lambdas with Java 11.
// Note that this line allows *all* methods from java.util.Objects.
// That's the best that we can do with the configuration options that Animal Sniffer offers.
ignore 'java.util.Objects'
}
// needed to make test output available to bramble-java // needed to make test output available to bramble-java
configurations { configurations {
testOutput.extendsFrom(testCompile) testOutput.extendsFrom(testCompile)

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble; package org.briarproject.bramble;
import org.briarproject.bramble.cleanup.CleanupModule;
import org.briarproject.bramble.contact.ContactModule; import org.briarproject.bramble.contact.ContactModule;
import org.briarproject.bramble.crypto.CryptoExecutorModule; import org.briarproject.bramble.crypto.CryptoExecutorModule;
import org.briarproject.bramble.db.DatabaseExecutorModule; import org.briarproject.bramble.db.DatabaseExecutorModule;
@@ -14,6 +15,8 @@ import org.briarproject.bramble.versioning.VersioningModule;
public interface BrambleCoreEagerSingletons { public interface BrambleCoreEagerSingletons {
void inject(CleanupModule.EagerSingletons init);
void inject(ContactModule.EagerSingletons init); void inject(ContactModule.EagerSingletons init);
void inject(CryptoExecutorModule.EagerSingletons init); void inject(CryptoExecutorModule.EagerSingletons init);
@@ -39,6 +42,7 @@ public interface BrambleCoreEagerSingletons {
class Helper { class Helper {
public static void injectEagerSingletons(BrambleCoreEagerSingletons c) { public static void injectEagerSingletons(BrambleCoreEagerSingletons c) {
c.inject(new CleanupModule.EagerSingletons());
c.inject(new ContactModule.EagerSingletons()); c.inject(new ContactModule.EagerSingletons());
c.inject(new CryptoExecutorModule.EagerSingletons()); c.inject(new CryptoExecutorModule.EagerSingletons());
c.inject(new DatabaseExecutorModule.EagerSingletons()); c.inject(new DatabaseExecutorModule.EagerSingletons());

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble; package org.briarproject.bramble;
import org.briarproject.bramble.cleanup.CleanupModule;
import org.briarproject.bramble.client.ClientModule; import org.briarproject.bramble.client.ClientModule;
import org.briarproject.bramble.connection.ConnectionModule; import org.briarproject.bramble.connection.ConnectionModule;
import org.briarproject.bramble.contact.ContactModule; import org.briarproject.bramble.contact.ContactModule;
@@ -21,15 +22,14 @@ import org.briarproject.bramble.rendezvous.RendezvousModule;
import org.briarproject.bramble.settings.SettingsModule; import org.briarproject.bramble.settings.SettingsModule;
import org.briarproject.bramble.sync.SyncModule; import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.sync.validation.ValidationModule; import org.briarproject.bramble.sync.validation.ValidationModule;
import org.briarproject.bramble.system.ClockModule;
import org.briarproject.bramble.transport.TransportModule; import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.bramble.versioning.VersioningModule; import org.briarproject.bramble.versioning.VersioningModule;
import dagger.Module; import dagger.Module;
@Module(includes = { @Module(includes = {
CleanupModule.class,
ClientModule.class, ClientModule.class,
ClockModule.class,
ConnectionModule.class, ConnectionModule.class,
ContactModule.class, ContactModule.class,
CryptoModule.class, CryptoModule.class,

View File

@@ -176,18 +176,6 @@ class AccountManagerImpl implements AccountManager {
} }
} }
public boolean restoreAccount(Identity identity, String password) {
synchronized (stateChangeLock) {
if (hasDatabaseKey())
throw new AssertionError("Already have a database key");
identityManager.registerIdentity(identity);
SecretKey key = crypto.generateSecretKey();
if (!encryptAndStoreDatabaseKey(key, password)) return false;
databaseKey = key;
return true;
}
}
@GuardedBy("stateChangeLock") @GuardedBy("stateChangeLock")
private boolean encryptAndStoreDatabaseKey(SecretKey key, String password) { private boolean encryptAndStoreDatabaseKey(SecretKey key, String password) {
byte[] plaintext = key.getBytes(); byte[] plaintext = key.getBytes();

View File

@@ -0,0 +1,159 @@
package org.briarproject.bramble.cleanup;
import org.briarproject.bramble.api.cleanup.CleanupHook;
import org.briarproject.bramble.api.cleanup.CleanupManager;
import org.briarproject.bramble.api.cleanup.event.CleanupTimerStartedEvent;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.TaskScheduler;
import org.briarproject.bramble.api.versioning.ClientMajorVersion;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.lang.Math.max;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.db.DatabaseComponent.NO_CLEANUP_DEADLINE;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe
@NotNullByDefault
class CleanupManagerImpl implements CleanupManager, Service, EventListener {
private static final Logger LOG =
getLogger(CleanupManagerImpl.class.getName());
private final Executor dbExecutor;
private final DatabaseComponent db;
private final TaskScheduler taskScheduler;
private final Clock clock;
private final Map<ClientMajorVersion, CleanupHook> hooks =
new ConcurrentHashMap<>();
private final Object lock = new Object();
@GuardedBy("lock")
private final Set<CleanupTask> pending = new HashSet<>();
@Inject
CleanupManagerImpl(@DatabaseExecutor Executor dbExecutor,
DatabaseComponent db, TaskScheduler taskScheduler, Clock clock) {
this.dbExecutor = dbExecutor;
this.db = db;
this.taskScheduler = taskScheduler;
this.clock = clock;
}
@Override
public void registerCleanupHook(ClientId c, int majorVersion,
CleanupHook hook) {
hooks.put(new ClientMajorVersion(c, majorVersion), hook);
}
@Override
public void startService() {
maybeScheduleTask(clock.currentTimeMillis());
}
@Override
public void stopService() {
}
@Override
public void eventOccurred(Event e) {
if (e instanceof CleanupTimerStartedEvent) {
CleanupTimerStartedEvent a = (CleanupTimerStartedEvent) e;
maybeScheduleTask(a.getCleanupDeadline());
}
}
private void maybeScheduleTask(long deadline) {
synchronized (lock) {
for (CleanupTask task : pending) {
if (task.deadline <= deadline) return;
}
CleanupTask task = new CleanupTask(deadline);
pending.add(task);
scheduleTask(task);
}
}
private void scheduleTask(CleanupTask task) {
long now = clock.currentTimeMillis();
long delay = max(0, task.deadline - now + BATCH_DELAY_MS);
if (LOG.isLoggable(INFO)) {
LOG.info("Scheduling cleanup task in " + delay + " ms");
}
taskScheduler.schedule(() -> deleteMessagesAndScheduleNextTask(task),
dbExecutor, delay, MILLISECONDS);
}
private void deleteMessagesAndScheduleNextTask(CleanupTask task) {
try {
synchronized (lock) {
pending.remove(task);
}
long deadline = db.transactionWithResult(false, txn -> {
deleteMessages(txn);
return db.getNextCleanupDeadline(txn);
});
if (deadline != NO_CLEANUP_DEADLINE) {
maybeScheduleTask(deadline);
}
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}
private void deleteMessages(Transaction txn) throws DbException {
Map<GroupId, Collection<MessageId>> ids = db.getMessagesToDelete(txn);
for (Entry<GroupId, Collection<MessageId>> e : ids.entrySet()) {
GroupId groupId = e.getKey();
Collection<MessageId> messageIds = e.getValue();
if (LOG.isLoggable(INFO)) {
LOG.info(messageIds.size() + " messages to delete");
}
for (MessageId m : messageIds) db.stopCleanupTimer(txn, m);
Group group = db.getGroup(txn, groupId);
ClientMajorVersion cv = new ClientMajorVersion(group.getClientId(),
group.getMajorVersion());
CleanupHook hook = hooks.get(cv);
if (hook == null) {
throw new IllegalStateException("No cleanup hook for " + cv);
}
hook.deleteMessages(txn, groupId, messageIds);
}
}
private static class CleanupTask {
private final long deadline;
private CleanupTask(long deadline) {
this.deadline = deadline;
}
}
}

View File

@@ -0,0 +1,29 @@
package org.briarproject.bramble.cleanup;
import org.briarproject.bramble.api.cleanup.CleanupManager;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class CleanupModule {
public static class EagerSingletons {
@Inject
CleanupManager cleanupManager;
}
@Provides
@Singleton
CleanupManager provideCleanupManager(LifecycleManager lifecycleManager,
EventBus eventBus, CleanupManagerImpl cleanupManager) {
lifecycleManager.registerService(cleanupManager);
eventBus.addListener(cleanupManager);
return cleanupManager;
}
}

View File

@@ -2,11 +2,13 @@ package org.briarproject.bramble.client;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyParser; import org.briarproject.bramble.api.crypto.KeyParser;
import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry;
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;
@@ -32,6 +34,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@@ -39,6 +42,7 @@ import java.util.Map.Entry;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.bramble.api.client.ContactGroupConstants.GROUP_KEY_CONTACT_ID;
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION; import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
@@ -151,6 +155,12 @@ class ClientHelperImpl implements ClientHelper {
return metadataParser.parse(metadata); return metadataParser.parse(metadata);
} }
@Override
public Collection<MessageId> getMessageIds(Transaction txn, GroupId g,
BdfDictionary query) throws DbException, FormatException {
return db.getMessageIds(txn, g, metadataEncoder.encode(query));
}
@Override @Override
public BdfDictionary getMessageMetadataAsDictionary(MessageId m) public BdfDictionary getMessageMetadataAsDictionary(MessageId m)
throws DbException, FormatException { throws DbException, FormatException {
@@ -389,4 +399,27 @@ class ClientHelperImpl implements ClientHelper {
return tpMap; return tpMap;
} }
@Override
public ContactId getContactId(Transaction txn, GroupId contactGroupId)
throws DbException {
try {
BdfDictionary meta =
getGroupMetadataAsDictionary(txn, contactGroupId);
return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue());
} catch (FormatException e) {
throw new DbException(e); // Invalid group metadata
}
}
@Override
public void setContactId(Transaction txn, GroupId contactGroupId,
ContactId c) throws DbException {
BdfDictionary meta = BdfDictionary.of(
new BdfEntry(GROUP_KEY_CONTACT_ID, c.getInt()));
try {
mergeGroupMetadata(txn, contactGroupId, meta);
} catch (FormatException e) {
throw new AssertionError(e);
}
}
} }

View File

@@ -76,7 +76,7 @@ class ConnectionManagerImpl implements ConnectionManager {
ioExecutor.execute(new IncomingDuplexSyncConnection(keyManager, ioExecutor.execute(new IncomingDuplexSyncConnection(keyManager,
connectionRegistry, streamReaderFactory, streamWriterFactory, connectionRegistry, streamReaderFactory, streamWriterFactory,
syncSessionFactory, transportPropertyManager, ioExecutor, syncSessionFactory, transportPropertyManager, ioExecutor,
t, d, handshakeManager)); t, d));
} }
@Override @Override
@@ -101,7 +101,7 @@ class ConnectionManagerImpl implements ConnectionManager {
ioExecutor.execute(new OutgoingDuplexSyncConnection(keyManager, ioExecutor.execute(new OutgoingDuplexSyncConnection(keyManager,
connectionRegistry, streamReaderFactory, streamWriterFactory, connectionRegistry, streamReaderFactory, streamWriterFactory,
syncSessionFactory, transportPropertyManager, ioExecutor, syncSessionFactory, transportPropertyManager, ioExecutor,
secureRandom, handshakeManager, c, t, d)); secureRandom, c, t, d));
} }
@Override @Override

View File

@@ -3,7 +3,6 @@ package org.briarproject.bramble.connection;
import org.briarproject.bramble.api.connection.ConnectionRegistry; import org.briarproject.bramble.api.connection.ConnectionRegistry;
import org.briarproject.bramble.api.connection.InterruptibleConnection; import org.briarproject.bramble.api.connection.InterruptibleConnection;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.HandshakeManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportConnectionReader; import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter; import org.briarproject.bramble.api.plugin.TransportConnectionWriter;

View File

@@ -2,7 +2,6 @@ package org.briarproject.bramble.connection;
import org.briarproject.bramble.api.connection.ConnectionRegistry; import org.briarproject.bramble.api.connection.ConnectionRegistry;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.HandshakeManager;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
@@ -14,11 +13,9 @@ import org.briarproject.bramble.api.sync.SyncSessionFactory;
import org.briarproject.bramble.api.transport.KeyManager; import org.briarproject.bramble.api.transport.KeyManager;
import org.briarproject.bramble.api.transport.StreamContext; import org.briarproject.bramble.api.transport.StreamContext;
import org.briarproject.bramble.api.transport.StreamReaderFactory; import org.briarproject.bramble.api.transport.StreamReaderFactory;
import org.briarproject.bramble.api.transport.StreamWriter;
import org.briarproject.bramble.api.transport.StreamWriterFactory; import org.briarproject.bramble.api.transport.StreamWriterFactory;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
@@ -27,10 +24,6 @@ import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault @NotNullByDefault
class IncomingDuplexSyncConnection extends DuplexSyncConnection class IncomingDuplexSyncConnection extends DuplexSyncConnection
implements Runnable { implements Runnable {
private final HandshakeManager handshakeManager;
// FIXME: Exchange timestamp as part of handshake protocol?
private static final long TIMESTAMP = 1617235200; // 1 April 2021 00:00 UTC
IncomingDuplexSyncConnection(KeyManager keyManager, IncomingDuplexSyncConnection(KeyManager keyManager,
ConnectionRegistry connectionRegistry, ConnectionRegistry connectionRegistry,
@@ -39,18 +32,14 @@ class IncomingDuplexSyncConnection extends DuplexSyncConnection
SyncSessionFactory syncSessionFactory, SyncSessionFactory syncSessionFactory,
TransportPropertyManager transportPropertyManager, TransportPropertyManager transportPropertyManager,
Executor ioExecutor, TransportId transportId, Executor ioExecutor, TransportId transportId,
DuplexTransportConnection connection, DuplexTransportConnection connection) {
HandshakeManager handshakeManager) {
super(keyManager, connectionRegistry, streamReaderFactory, super(keyManager, connectionRegistry, streamReaderFactory,
streamWriterFactory, syncSessionFactory, streamWriterFactory, syncSessionFactory,
transportPropertyManager, ioExecutor, transportId, connection); transportPropertyManager, ioExecutor, transportId, connection);
this.handshakeManager = handshakeManager;
} }
@Override @Override
public void run() { public void run() {
LOG.info("Running IncomingDuplexSyncConnection on transport " +
transportId.getString());
// Read and recognise the tag // Read and recognise the tag
StreamContext ctx = recogniseTag(reader, transportId); StreamContext ctx = recogniseTag(reader, transportId);
if (ctx == null) { if (ctx == null) {
@@ -65,22 +54,10 @@ class IncomingDuplexSyncConnection extends DuplexSyncConnection
return; return;
} }
if (ctx.isHandshakeMode()) { if (ctx.isHandshakeMode()) {
if (!performHandshake(ctx, contactId)) { // TODO: Support handshake mode for contacts
LOG.warning("Handshake failed"); LOG.warning("Received handshake tag, expected rotation mode");
return; onReadError(true);
} return;
// Allocate a rotation mode stream context
ctx = allocateStreamContext(contactId, transportId);
if (ctx == null) {
LOG.warning("Could not allocate stream context");
onWriteError();
return;
}
if (ctx.isHandshakeMode()) {
LOG.warning("Got handshake mode context after handshaking");
onWriteError();
return;
}
} }
connectionRegistry.registerIncomingConnection(contactId, transportId, connectionRegistry.registerIncomingConnection(contactId, transportId,
this); this);
@@ -126,35 +103,5 @@ class IncomingDuplexSyncConnection extends DuplexSyncConnection
onWriteError(); onWriteError();
} }
} }
private boolean performHandshake(StreamContext ctxIn, ContactId contactId) {
LOG.info("Performing handshake (Incoming)");
// Allocate the outgoing stream context
StreamContext ctxOut =
allocateStreamContext(contactId, transportId);
if (ctxOut == null) {
LOG.warning("Could not allocate stream context");
onReadError(true);
return false;
}
try {
InputStream in = streamReaderFactory.createStreamReader(
reader.getInputStream(), ctxIn);
// Flush the output stream to send the outgoing stream header
StreamWriter out = streamWriterFactory.createStreamWriter(
writer.getOutputStream(), ctxOut);
out.getOutputStream().flush();
HandshakeManager.HandshakeResult result =
handshakeManager.handshake(contactId, in, out);
keyManager.addRotationKeys(contactId, result.getMasterKey(),
TIMESTAMP, result.isAlice(), true);
LOG.info("Rotation keys added");
return true;
} catch (IOException | DbException e) {
logException(LOG, WARNING, e);
onReadError(true);
return false;
}
}
} }

View File

@@ -2,7 +2,6 @@ package org.briarproject.bramble.connection;
import org.briarproject.bramble.api.connection.ConnectionRegistry; import org.briarproject.bramble.api.connection.ConnectionRegistry;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.HandshakeManager;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
@@ -15,11 +14,9 @@ import org.briarproject.bramble.api.sync.SyncSessionFactory;
import org.briarproject.bramble.api.transport.KeyManager; import org.briarproject.bramble.api.transport.KeyManager;
import org.briarproject.bramble.api.transport.StreamContext; import org.briarproject.bramble.api.transport.StreamContext;
import org.briarproject.bramble.api.transport.StreamReaderFactory; import org.briarproject.bramble.api.transport.StreamReaderFactory;
import org.briarproject.bramble.api.transport.StreamWriter;
import org.briarproject.bramble.api.transport.StreamWriterFactory; import org.briarproject.bramble.api.transport.StreamWriterFactory;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -31,38 +28,26 @@ import static org.briarproject.bramble.util.LogUtils.logException;
class OutgoingDuplexSyncConnection extends DuplexSyncConnection class OutgoingDuplexSyncConnection extends DuplexSyncConnection
implements Runnable { implements Runnable {
// FIXME: Exchange timestamp as part of handshake protocol?
private static final long TIMESTAMP = 1617235200; // 1 April 2021 00:00 UTC
private final SecureRandom secureRandom; private final SecureRandom secureRandom;
private final HandshakeManager handshakeManager;
private final ContactId contactId; private final ContactId contactId;
OutgoingDuplexSyncConnection( OutgoingDuplexSyncConnection(KeyManager keyManager,
KeyManager keyManager,
ConnectionRegistry connectionRegistry, ConnectionRegistry connectionRegistry,
StreamReaderFactory streamReaderFactory, StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory, StreamWriterFactory streamWriterFactory,
SyncSessionFactory syncSessionFactory, SyncSessionFactory syncSessionFactory,
TransportPropertyManager transportPropertyManager, TransportPropertyManager transportPropertyManager,
Executor ioExecutor, Executor ioExecutor, SecureRandom secureRandom, ContactId contactId,
SecureRandom secureRandom, TransportId transportId, DuplexTransportConnection connection) {
HandshakeManager handshakeManager,
ContactId contactId,
TransportId transportId,
DuplexTransportConnection connection) {
super(keyManager, connectionRegistry, streamReaderFactory, super(keyManager, connectionRegistry, streamReaderFactory,
streamWriterFactory, syncSessionFactory, streamWriterFactory, syncSessionFactory,
transportPropertyManager, ioExecutor, transportId, connection); transportPropertyManager, ioExecutor, transportId, connection);
this.secureRandom = secureRandom; this.secureRandom = secureRandom;
this.handshakeManager = handshakeManager;
this.contactId = contactId; this.contactId = contactId;
} }
@Override @Override
public void run() { public void run() {
LOG.info("Running OutgoingDuplexSyncConnection on transport " +
transportId.getString());
// Allocate a stream context // Allocate a stream context
StreamContext ctx = allocateStreamContext(contactId, transportId); StreamContext ctx = allocateStreamContext(contactId, transportId);
if (ctx == null) { if (ctx == null) {
@@ -71,22 +56,10 @@ class OutgoingDuplexSyncConnection extends DuplexSyncConnection
return; return;
} }
if (ctx.isHandshakeMode()) { if (ctx.isHandshakeMode()) {
if (!performHandshake(ctx)) { // TODO: Support handshake mode for contacts
LOG.warning("Handshake failed"); LOG.warning("Cannot use handshake mode stream context");
return; onWriteError();
} return;
// Allocate a rotation mode stream context
ctx = allocateStreamContext(contactId, transportId);
if (ctx == null) {
LOG.warning("Could not allocate stream context");
onWriteError();
return;
}
if (ctx.isHandshakeMode()) {
LOG.warning("Got handshake mode context after handshaking");
onWriteError();
return;
}
} }
// Start the incoming session on another thread // Start the incoming session on another thread
Priority priority = generatePriority(); Priority priority = generatePriority();
@@ -154,59 +127,6 @@ class OutgoingDuplexSyncConnection extends DuplexSyncConnection
} }
} }
private boolean performHandshake(StreamContext ctxOut) {
LOG.info("Performing handshake (Outgoing)");
// Flush the output stream to send the outgoing stream header
StreamWriter out;
try {
out = streamWriterFactory.createStreamWriter(
writer.getOutputStream(), ctxOut);
out.getOutputStream().flush();
} catch (IOException e) {
logException(LOG, WARNING, e);
onWriteError();
return false;
}
// Read and recognise the tag
StreamContext ctxIn = recogniseTag(reader, transportId);
// Unrecognised tags are suspicious in this case
if (ctxIn == null) {
LOG.warning("Unrecognised tag for returning stream");
onReadError();
return false;
}
// Check that the stream comes from the expected contact
ContactId inContactId = ctxIn.getContactId();
if (contactId == null) {
LOG.warning("Expected contact tag, got rendezvous tag");
onReadError();
return false;
}
if (!inContactId.equals(contactId)) {
LOG.warning("Wrong contact ID for returning stream");
onReadError();
return false;
}
// TODO: Register the connection, close it if it's redundant
// Handshake and exchange contacts
try {
InputStream in = streamReaderFactory.createStreamReader(
reader.getInputStream(), ctxIn);
HandshakeManager.HandshakeResult result =
handshakeManager.handshake(contactId, in, out);
keyManager.addRotationKeys(contactId, result.getMasterKey(),
TIMESTAMP, result.isAlice(), true);
LOG.info("Rotation keys added");
return true;
} catch (IOException | DbException e) {
logException(LOG, WARNING, e);
onWriteError();
return false;
} finally {
// TODO: Unregister the connection
}
}
private void onReadError() { private void onReadError() {
// 'Recognised' is always true for outgoing connections // 'Recognised' is always true for outgoing connections
onReadError(true); onReadError(true);

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.contact; package org.briarproject.bramble.contact;
public interface ContactExchangeConstants { interface ContactExchangeConstants {
/** /**
* The current version of the contact exchange protocol. * The current version of the contact exchange protocol.

View File

@@ -1,4 +1,4 @@
package org.briarproject.bramble.api.contact; package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
@@ -6,7 +6,7 @@ import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault @NotNullByDefault
public interface ContactExchangeCrypto { interface ContactExchangeCrypto {
/** /**
* Derives the header key for a contact exchange stream from the master key. * Derives the header key for a contact exchange stream from the master key.

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.contact; package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.contact.ContactExchangeCrypto;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
@@ -11,12 +10,12 @@ import java.security.GeneralSecurityException;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.bramble.api.contact.ContactExchangeConstants.ALICE_KEY_LABEL; import static org.briarproject.bramble.contact.ContactExchangeConstants.ALICE_KEY_LABEL;
import static org.briarproject.bramble.api.contact.ContactExchangeConstants.ALICE_NONCE_LABEL; import static org.briarproject.bramble.contact.ContactExchangeConstants.ALICE_NONCE_LABEL;
import static org.briarproject.bramble.api.contact.ContactExchangeConstants.BOB_KEY_LABEL; import static org.briarproject.bramble.contact.ContactExchangeConstants.BOB_KEY_LABEL;
import static org.briarproject.bramble.api.contact.ContactExchangeConstants.BOB_NONCE_LABEL; import static org.briarproject.bramble.contact.ContactExchangeConstants.BOB_NONCE_LABEL;
import static org.briarproject.bramble.api.contact.ContactExchangeConstants.PROTOCOL_VERSION; import static org.briarproject.bramble.contact.ContactExchangeConstants.PROTOCOL_VERSION;
import static org.briarproject.bramble.api.contact.ContactExchangeConstants.SIGNING_LABEL; import static org.briarproject.bramble.contact.ContactExchangeConstants.SIGNING_LABEL;
@NotNullByDefault @NotNullByDefault
class ContactExchangeCryptoImpl implements ContactExchangeCrypto { class ContactExchangeCryptoImpl implements ContactExchangeCrypto {

View File

@@ -4,7 +4,6 @@ import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.Predicate; import org.briarproject.bramble.api.Predicate;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactExchangeCrypto;
import org.briarproject.bramble.api.contact.ContactExchangeManager; import org.briarproject.bramble.api.contact.ContactExchangeManager;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
@@ -48,8 +47,8 @@ import javax.inject.Inject;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.api.contact.ContactExchangeConstants.PROTOCOL_VERSION; import static org.briarproject.bramble.contact.ContactExchangeConstants.PROTOCOL_VERSION;
import static org.briarproject.bramble.api.contact.ContactExchangeRecordTypes.CONTACT_INFO; import static org.briarproject.bramble.contact.ContactExchangeRecordTypes.CONTACT_INFO;
import static org.briarproject.bramble.util.ValidationUtils.checkLength; import static org.briarproject.bramble.util.ValidationUtils.checkLength;
import static org.briarproject.bramble.util.ValidationUtils.checkSize; import static org.briarproject.bramble.util.ValidationUtils.checkSize;
@@ -82,8 +81,7 @@ class ContactExchangeManagerImpl implements ContactExchangeManager {
private final ContactManager contactManager; private final ContactManager contactManager;
private final IdentityManager identityManager; private final IdentityManager identityManager;
private final TransportPropertyManager transportPropertyManager; private final TransportPropertyManager transportPropertyManager;
private final org.briarproject.bramble.api.contact.ContactExchangeCrypto private final ContactExchangeCrypto contactExchangeCrypto;
contactExchangeCrypto;
private final StreamReaderFactory streamReaderFactory; private final StreamReaderFactory streamReaderFactory;
private final StreamWriterFactory streamWriterFactory; private final StreamWriterFactory streamWriterFactory;

View File

@@ -0,0 +1,9 @@
package org.briarproject.bramble.contact;
/**
* Record types for the contact exchange protocol.
*/
interface ContactExchangeRecordTypes {
byte CONTACT_INFO = 0;
}

View File

@@ -9,7 +9,6 @@ import org.briarproject.bramble.api.contact.PendingContact;
import org.briarproject.bramble.api.contact.PendingContactId; import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.contact.PendingContactState; import org.briarproject.bramble.api.contact.PendingContactState;
import org.briarproject.bramble.api.contact.event.PendingContactStateChangedEvent; import org.briarproject.bramble.api.contact.event.PendingContactStateChangedEvent;
import org.briarproject.bramble.api.crypto.CryptoConstants;
import org.briarproject.bramble.api.crypto.KeyPair; import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
@@ -120,18 +119,6 @@ class ContactManagerImpl implements ContactManager, EventListener {
verified, active)); verified, active));
} }
@Override
public ContactId addContact(Transaction txn, Author remote, AuthorId local,
PublicKey handshake, boolean verified)
throws DbException, GeneralSecurityException {
ContactId c = db.addContact(txn, remote, local, handshake, verified);
Contact contact = db.getContact(txn, c);
KeyPair ourKeyPair = identityManager.getHandshakeKeys(txn);
keyManager.addContact(txn, c, handshake, ourKeyPair);
for (ContactHook hook : hooks) hook.addingContact(txn, contact);
return c;
}
@Override @Override
public String getHandshakeLink() throws DbException { public String getHandshakeLink() throws DbException {
KeyPair keyPair = db.transactionWithResult(true, KeyPair keyPair = db.transactionWithResult(true,
@@ -247,25 +234,6 @@ class ContactManagerImpl implements ContactManager, EventListener {
db.transaction(false, txn -> setContactAlias(txn, c, alias)); db.transaction(false, txn -> setContactAlias(txn, c, alias));
} }
@Override
public void setHandshakePublicKey(Transaction txn, ContactId c,
PublicKey handshakePublicKey) throws DbException, GeneralSecurityException {
if (handshakePublicKey.getKeyType() !=
CryptoConstants.KEY_TYPE_AGREEMENT) {
throw new IllegalArgumentException();
}
db.setHandshakePublicKey(txn, c, handshakePublicKey);
KeyPair ourKeyPair = identityManager.getHandshakeKeys(txn);
keyManager.addContact(txn, c, handshakePublicKey, ourKeyPair);
}
@Override
public void setHandshakePublicKey(ContactId c, PublicKey handshakePublicKey)
throws DbException, GeneralSecurityException {
db.transaction(false,
txn -> setHandshakePublicKey(txn, c, handshakePublicKey));
}
@Override @Override
public boolean contactExists(Transaction txn, AuthorId remoteAuthorId, public boolean contactExists(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException { AuthorId localAuthorId) throws DbException {

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.contact; package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.contact.ContactExchangeCrypto;
import org.briarproject.bramble.api.contact.ContactExchangeManager; import org.briarproject.bramble.api.contact.ContactExchangeManager;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.HandshakeManager; import org.briarproject.bramble.api.contact.HandshakeManager;

View File

@@ -3,8 +3,6 @@ package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.Pair; import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.Predicate; import org.briarproject.bramble.api.Predicate;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.HandshakeManager; import org.briarproject.bramble.api.contact.HandshakeManager;
import org.briarproject.bramble.api.contact.PendingContact; import org.briarproject.bramble.api.contact.PendingContact;
@@ -90,27 +88,6 @@ class HandshakeManagerImpl implements HandshakeManager {
}); });
PublicKey theirStaticPublicKey = keys.getFirst(); PublicKey theirStaticPublicKey = keys.getFirst();
KeyPair ourStaticKeyPair = keys.getSecond(); KeyPair ourStaticKeyPair = keys.getSecond();
return handshake(theirStaticPublicKey, ourStaticKeyPair, in, out);
}
@Override
public HandshakeResult handshake(ContactId c, InputStream in,
StreamWriter out) throws DbException, IOException {
Pair<PublicKey, KeyPair> keys = db.transactionWithResult(true, txn -> {
Contact contact = contactManager.getContact(txn, c);
PublicKey handshakePublicKey = contact.getHandshakePublicKey();
if (handshakePublicKey == null) throw new DbException();
KeyPair keyPair = identityManager.getHandshakeKeys(txn);
return new Pair<>(handshakePublicKey, keyPair);
});
PublicKey theirStaticPublicKey = keys.getFirst();
KeyPair ourStaticKeyPair = keys.getSecond();
return handshake(theirStaticPublicKey, ourStaticKeyPair, in, out);
}
private HandshakeResult handshake(PublicKey theirStaticPublicKey,
KeyPair ourStaticKeyPair, InputStream in, StreamWriter out)
throws IOException {
boolean alice = transportCrypto.isAlice(theirStaticPublicKey, boolean alice = transportCrypto.isAlice(theirStaticPublicKey,
ourStaticKeyPair); ourStaticKeyPair);
RecordReader recordReader = recordReaderFactory.createRecordReader(in); RecordReader recordReader = recordReaderFactory.createRecordReader(in);

View File

@@ -1,11 +1,12 @@
package org.briarproject.bramble.api.crypto; package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
@NotNullByDefault @NotNullByDefault
public interface AuthenticatedCipher { interface AuthenticatedCipher {
/** /**
* Initializes this cipher for encryption or decryption with a key and an * Initializes this cipher for encryption or decryption with a key and an

View File

@@ -6,7 +6,6 @@ import net.i2p.crypto.eddsa.KeyPairGenerator;
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.AuthenticatedCipher;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.DecryptionException; import org.briarproject.bramble.api.crypto.DecryptionException;
import org.briarproject.bramble.api.crypto.KeyPair; import org.briarproject.bramble.api.crypto.KeyPair;
@@ -21,9 +20,9 @@ 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.ByteUtils; import org.briarproject.bramble.util.ByteUtils;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.bouncycastle.crypto.CryptoException; import org.spongycastle.crypto.CryptoException;
import org.bouncycastle.crypto.Digest; import org.spongycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.Blake2bDigest; import org.spongycastle.crypto.digests.Blake2bDigest;
import org.whispersystems.curve25519.Curve25519; import org.whispersystems.curve25519.Curve25519;
import org.whispersystems.curve25519.Curve25519KeyPair; import org.whispersystems.curve25519.Curve25519KeyPair;

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.AuthenticatedCipher;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyAgreementCrypto; import org.briarproject.bramble.api.crypto.KeyAgreementCrypto;
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator; import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;

View File

@@ -6,33 +6,33 @@ import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters; import org.spongycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.spongycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.BasicAgreement; import org.spongycastle.crypto.BasicAgreement;
import org.bouncycastle.crypto.BlockCipher; import org.spongycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters; import org.spongycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoException; import org.spongycastle.crypto.CryptoException;
import org.bouncycastle.crypto.DerivationFunction; import org.spongycastle.crypto.DerivationFunction;
import org.bouncycastle.crypto.KeyEncoder; import org.spongycastle.crypto.KeyEncoder;
import org.bouncycastle.crypto.Mac; import org.spongycastle.crypto.Mac;
import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement; import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
import org.bouncycastle.crypto.digests.SHA256Digest; import org.spongycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.engines.AESLightEngine; import org.spongycastle.crypto.engines.AESLightEngine;
import org.bouncycastle.crypto.engines.IESEngine; import org.spongycastle.crypto.engines.IESEngine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.spongycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator; import org.spongycastle.crypto.generators.EphemeralKeyPairGenerator;
import org.bouncycastle.crypto.generators.KDF2BytesGenerator; import org.spongycastle.crypto.generators.KDF2BytesGenerator;
import org.bouncycastle.crypto.macs.HMac; import org.spongycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.modes.CBCBlockCipher; import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher; import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.spongycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters; import org.spongycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.IESWithCipherParameters; import org.spongycastle.crypto.params.IESWithCipherParameters;
import org.bouncycastle.crypto.parsers.ECIESPublicKeyParser; import org.spongycastle.crypto.parsers.ECIESPublicKeyParser;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;

View File

@@ -3,7 +3,7 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.bouncycastle.crypto.generators.SCrypt; import org.spongycastle.crypto.generators.SCrypt;
import java.util.logging.Logger; import java.util.logging.Logger;

View File

@@ -4,11 +4,11 @@ import org.briarproject.bramble.api.crypto.KeyParser;
import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.bouncycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECCurve; import org.spongycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint; import org.spongycastle.math.ec.ECPoint;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;

View File

@@ -2,7 +2,7 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;

View File

@@ -2,7 +2,7 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.AuthenticatedCipher;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.crypto.StreamDecrypter; import org.briarproject.bramble.api.crypto.StreamDecrypter;
import org.briarproject.bramble.api.crypto.StreamDecrypterFactory; import org.briarproject.bramble.api.crypto.StreamDecrypterFactory;

View File

@@ -1,7 +1,6 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.crypto.AuthenticatedCipher;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.crypto.StreamDecrypter; import org.briarproject.bramble.api.crypto.StreamDecrypter;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.AuthenticatedCipher;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.crypto.StreamEncrypter; import org.briarproject.bramble.api.crypto.StreamEncrypter;

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.AuthenticatedCipher;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.crypto.StreamEncrypter; import org.briarproject.bramble.api.crypto.StreamEncrypter;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;

View File

@@ -9,8 +9,8 @@ import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.transport.IncomingKeys; import org.briarproject.bramble.api.transport.IncomingKeys;
import org.briarproject.bramble.api.transport.OutgoingKeys; import org.briarproject.bramble.api.transport.OutgoingKeys;
import org.briarproject.bramble.api.transport.TransportKeys; import org.briarproject.bramble.api.transport.TransportKeys;
import org.bouncycastle.crypto.Digest; import org.spongycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.Blake2bDigest; import org.spongycastle.crypto.digests.Blake2bDigest;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;

View File

@@ -1,14 +1,13 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.AuthenticatedCipher;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.bouncycastle.crypto.DataLengthException; import org.spongycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.engines.XSalsa20Engine; import org.spongycastle.crypto.engines.XSalsa20Engine;
import org.bouncycastle.crypto.generators.Poly1305KeyGenerator; import org.spongycastle.crypto.generators.Poly1305KeyGenerator;
import org.bouncycastle.crypto.macs.Poly1305; import org.spongycastle.crypto.macs.Poly1305;
import org.bouncycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV; import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;

View File

@@ -32,7 +32,6 @@ import org.briarproject.bramble.api.transport.KeySetId;
import org.briarproject.bramble.api.transport.TransportKeySet; import org.briarproject.bramble.api.transport.TransportKeySet;
import org.briarproject.bramble.api.transport.TransportKeys; import org.briarproject.bramble.api.transport.TransportKeys;
import java.sql.Connection;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -498,6 +497,25 @@ interface Database<T> {
*/ */
Collection<MessageId> getMessagesToShare(T txn) throws DbException; Collection<MessageId> getMessagesToShare(T txn) throws DbException;
/**
* Returns the IDs of any messages of any messages that are due for
* deletion, along with their group IDs.
* <p/>
* Read-only.
*/
Map<GroupId, Collection<MessageId>> getMessagesToDelete(T txn)
throws DbException;
/**
* Returns the next time (in milliseconds since the Unix epoch) when a
* message is due to be deleted, or
* {@link DatabaseComponent#NO_CLEANUP_DEADLINE} if no messages are
* scheduled to be deleted.
* <p/>
* Read-only.
*/
long getNextCleanupDeadline(T txn) throws DbException;
/** /**
* Returns the next time (in milliseconds since the Unix epoch) when a * Returns the next time (in milliseconds since the Unix epoch) when a
* message is due to be sent to the given contact. The returned value may * message is due to be sent to the given contact. The returned value may
@@ -607,8 +625,10 @@ interface Database<T> {
/** /**
* Marks a message as having been seen by the given contact. * Marks a message as having been seen by the given contact.
*
* @return True if the message was not already marked as seen.
*/ */
void raiseSeenFlag(T txn, ContactId c, MessageId m) throws DbException; boolean raiseSeenFlag(T txn, ContactId c, MessageId m) throws DbException;
/** /**
* Removes a contact from the database. * Removes a contact from the database.
@@ -672,6 +692,13 @@ interface Database<T> {
*/ */
void resetExpiryTime(T txn, ContactId c, MessageId m) throws DbException; void resetExpiryTime(T txn, ContactId c, MessageId m) throws DbException;
/**
* Sets the cleanup timer duration for the given message. This does not
* start the message's cleanup timer.
*/
void setCleanupTimerDuration(T txn, MessageId m, long duration)
throws DbException;
/** /**
* Marks the given contact as verified. * Marks the given contact as verified.
*/ */
@@ -696,20 +723,16 @@ interface Database<T> {
void setHandshakeKeyPair(T txn, AuthorId local, PublicKey publicKey, void setHandshakeKeyPair(T txn, AuthorId local, PublicKey publicKey,
PrivateKey privateKey) throws DbException; PrivateKey privateKey) throws DbException;
/**
* Sets the handshake public key for a given contact
*/
void setHandshakePublicKey(T txn, ContactId c, PublicKey handshakePublicKey) throws DbException;
/** /**
* Marks the given message as permanent, i.e. not temporary. * Marks the given message as permanent, i.e. not temporary.
*/ */
void setMessagePermanent(T txn, MessageId m) throws DbException; void setMessagePermanent(T txn, MessageId m) throws DbException;
/** /**
* Marks the given message as shared. * Marks the given message as shared or not.
*/ */
void setMessageShared(T txn, MessageId m) throws DbException; void setMessageShared(T txn, MessageId m, boolean shared)
throws DbException;
/** /**
* Sets the validation and delivery state of the given message. * Sets the validation and delivery state of the given message.
@@ -736,6 +759,22 @@ interface Database<T> {
void setTransportKeysActive(T txn, TransportId t, KeySetId k) void setTransportKeysActive(T txn, TransportId t, KeySetId k)
throws DbException; throws DbException;
/**
* Starts the cleanup timer for the given message, if a timer duration
* has been set and the timer has not already been started.
*
* @return The cleanup deadline, or
* {@link DatabaseComponent#TIMER_NOT_STARTED} if no timer duration has
* been set for this message or its timer has already been started.
*/
long startCleanupTimer(T txn, MessageId m) throws DbException;
/**
* Stops the cleanup timer for the given message, if the timer has been
* started.
*/
void stopCleanupTimer(T txn, MessageId m) throws DbException;
/** /**
* Updates the transmission count, expiry time and estimated time of arrival * Updates the transmission count, expiry time and estimated time of arrival
* of the given message with respect to the given contact, using the latency * of the given message with respect to the given contact, using the latency

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble.db; package org.briarproject.bramble.db;
import org.briarproject.bramble.api.cleanup.event.CleanupTimerStartedEvent;
import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.PendingContact; import org.briarproject.bramble.api.contact.PendingContact;
@@ -576,6 +577,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.getMessageIds(txn, g); return db.getMessageIds(txn, g);
} }
@Override
public Collection<MessageId> getMessageIds(Transaction transaction,
GroupId g, Metadata query) throws DbException {
T txn = unbox(transaction);
if (!db.containsGroup(txn, g))
throw new NoSuchGroupException();
return db.getMessageIds(txn, g, query);
}
@Override @Override
public Collection<MessageId> getMessagesToValidate(Transaction transaction) public Collection<MessageId> getMessagesToValidate(Transaction transaction)
throws DbException { throws DbException {
@@ -597,6 +607,13 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.getMessagesToShare(txn); return db.getMessagesToShare(txn);
} }
@Override
public Map<GroupId, Collection<MessageId>> getMessagesToDelete(
Transaction transaction) throws DbException {
T txn = unbox(transaction);
return db.getMessagesToDelete(txn);
}
@Override @Override
public Map<MessageId, Metadata> getMessageMetadata(Transaction transaction, public Map<MessageId, Metadata> getMessageMetadata(Transaction transaction,
GroupId g) throws DbException { GroupId g) throws DbException {
@@ -692,6 +709,13 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.getMessageDependents(txn, m); return db.getMessageDependents(txn, m);
} }
@Override
public long getNextCleanupDeadline(Transaction transaction)
throws DbException {
T txn = unbox(transaction);
return db.getNextCleanupDeadline(txn);
}
@Override @Override
public long getNextSendTime(Transaction transaction, ContactId c) public long getNextSendTime(Transaction transaction, ContactId c)
throws DbException { throws DbException {
@@ -795,8 +819,17 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
Collection<MessageId> acked = new ArrayList<>(); Collection<MessageId> acked = new ArrayList<>();
for (MessageId m : a.getMessageIds()) { for (MessageId m : a.getMessageIds()) {
if (db.containsVisibleMessage(txn, c, m)) { if (db.containsVisibleMessage(txn, c, m)) {
db.raiseSeenFlag(txn, c, m); if (db.raiseSeenFlag(txn, c, m)) {
acked.add(m); // This is the first time the message has been acked by
// this contact. Start the cleanup timer (a no-op unless
// a cleanup deadline has been set for this message)
long deadline = db.startCleanupTimer(txn, m);
if (deadline != TIMER_NOT_STARTED) {
transaction.attach(new CleanupTimerStartedEvent(m,
deadline));
}
acked.add(m);
}
} }
} }
if (acked.size() > 0) { if (acked.size() > 0) {
@@ -952,6 +985,16 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
db.removeTransportKeys(txn, t, k); db.removeTransportKeys(txn, t, k);
} }
@Override
public void setCleanupTimerDuration(Transaction transaction, MessageId m,
long duration) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
db.setCleanupTimerDuration(txn, m, duration);
}
@Override @Override
public void setContactVerified(Transaction transaction, ContactId c) public void setContactVerified(Transaction transaction, ContactId c)
throws DbException { throws DbException {
@@ -1001,6 +1044,16 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
db.setMessagePermanent(txn, m); db.setMessagePermanent(txn, m);
} }
@Override
public void setMessageNotShared(Transaction transaction, MessageId m)
throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
db.setMessageShared(txn, m, false);
}
@Override @Override
public void setMessageShared(Transaction transaction, MessageId m) public void setMessageShared(Transaction transaction, MessageId m)
throws DbException { throws DbException {
@@ -1010,7 +1063,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
throw new NoSuchMessageException(); throw new NoSuchMessageException();
if (db.getMessageState(txn, m) != DELIVERED) if (db.getMessageState(txn, m) != DELIVERED)
throw new IllegalArgumentException("Shared undelivered message"); throw new IllegalArgumentException("Shared undelivered message");
db.setMessageShared(txn, m); db.setMessageShared(txn, m, true);
transaction.attach(new MessageSharedEvent(m)); transaction.attach(new MessageSharedEvent(m));
} }
@@ -1040,15 +1093,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
} }
} }
@Override
public void setHandshakePublicKey(Transaction transaction, ContactId c, PublicKey handshakePublicKey) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
db.setHandshakePublicKey(txn, c, handshakePublicKey);
}
@Override @Override
public void setHandshakeKeyPair(Transaction transaction, AuthorId local, public void setHandshakeKeyPair(Transaction transaction, AuthorId local,
PublicKey publicKey, PrivateKey privateKey) throws DbException { PublicKey publicKey, PrivateKey privateKey) throws DbException {
@@ -1091,6 +1135,30 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
db.setTransportKeysActive(txn, t, k); db.setTransportKeysActive(txn, t, k);
} }
@Override
public long startCleanupTimer(Transaction transaction, MessageId m)
throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
long deadline = db.startCleanupTimer(txn, m);
if (deadline != TIMER_NOT_STARTED) {
transaction.attach(new CleanupTimerStartedEvent(m, deadline));
}
return deadline;
}
@Override
public void stopCleanupTimer(Transaction transaction, MessageId m)
throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
db.stopCleanupTimer(txn, m);
}
@Override @Override
public void updateTransportKeys(Transaction transaction, public void updateTransportKeys(Transaction transaction,
Collection<TransportKeySet> keys) throws DbException { Collection<TransportKeySet> keys) throws DbException {

View File

@@ -72,6 +72,8 @@ import static java.util.Arrays.asList;
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.bramble.api.db.DatabaseComponent.NO_CLEANUP_DEADLINE;
import static org.briarproject.bramble.api.db.DatabaseComponent.TIMER_NOT_STARTED;
import static org.briarproject.bramble.api.db.Metadata.REMOVE; import static org.briarproject.bramble.api.db.Metadata.REMOVE;
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
@@ -98,7 +100,7 @@ import static org.briarproject.bramble.util.LogUtils.now;
abstract class JdbcDatabase implements Database<Connection> { abstract class JdbcDatabase implements Database<Connection> {
// Package access for testing // Package access for testing
static final int CODE_SCHEMA_VERSION = 47; static final int CODE_SCHEMA_VERSION = 48;
// Time period offsets for incoming transport keys // Time period offsets for incoming transport keys
private static final int OFFSET_PREV = -1; private static final int OFFSET_PREV = -1;
@@ -180,6 +182,11 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " state INT NOT NULL," + " state INT NOT NULL,"
+ " shared BOOLEAN NOT NULL," + " shared BOOLEAN NOT NULL,"
+ " temporary BOOLEAN NOT NULL," + " temporary BOOLEAN NOT NULL,"
// Null if no timer duration has been set
+ " cleanupTimerDuration BIGINT,"
// Null if no timer duration has been set or the timer
// hasn't started
+ " cleanupDeadline BIGINT,"
+ " length INT NOT NULL," + " length INT NOT NULL,"
+ " raw BLOB," // Null if message has been deleted + " raw BLOB," // Null if message has been deleted
+ " PRIMARY KEY (messageId)," + " PRIMARY KEY (messageId),"
@@ -336,6 +343,10 @@ abstract class JdbcDatabase implements Database<Connection> {
"CREATE INDEX IF NOT EXISTS statusesByContactIdTimestamp" "CREATE INDEX IF NOT EXISTS statusesByContactIdTimestamp"
+ " ON statuses (contactId, timestamp)"; + " ON statuses (contactId, timestamp)";
private static final String INDEX_MESSAGES_BY_CLEANUP_DEADLINE =
"CREATE INDEX IF NOT EXISTS messagesByCleanupDeadline"
+ " ON messages (cleanupDeadline)";
private static final Logger LOG = private static final Logger LOG =
getLogger(JdbcDatabase.class.getName()); getLogger(JdbcDatabase.class.getName());
@@ -463,7 +474,8 @@ abstract class JdbcDatabase implements Database<Connection> {
new Migration43_44(dbTypes), new Migration43_44(dbTypes),
new Migration44_45(), new Migration44_45(),
new Migration45_46(), new Migration45_46(),
new Migration46_47(dbTypes) new Migration46_47(dbTypes),
new Migration47_48()
); );
} }
@@ -531,6 +543,7 @@ abstract class JdbcDatabase implements Database<Connection> {
s.executeUpdate(INDEX_MESSAGE_DEPENDENCIES_BY_DEPENDENCY_ID); s.executeUpdate(INDEX_MESSAGE_DEPENDENCIES_BY_DEPENDENCY_ID);
s.executeUpdate(INDEX_STATUSES_BY_CONTACT_ID_GROUP_ID); s.executeUpdate(INDEX_STATUSES_BY_CONTACT_ID_GROUP_ID);
s.executeUpdate(INDEX_STATUSES_BY_CONTACT_ID_TIMESTAMP); s.executeUpdate(INDEX_STATUSES_BY_CONTACT_ID_TIMESTAMP);
s.executeUpdate(INDEX_MESSAGES_BY_CLEANUP_DEADLINE);
s.close(); s.close();
} catch (SQLException e) { } catch (SQLException e) {
tryToClose(s, LOG, WARNING); tryToClose(s, LOG, WARNING);
@@ -1290,7 +1303,9 @@ abstract class JdbcDatabase implements Database<Connection> {
public void deleteMessage(Connection txn, MessageId m) throws DbException { public void deleteMessage(Connection txn, MessageId m) throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
String sql = "UPDATE messages SET raw = NULL WHERE messageId = ?"; String sql = "UPDATE messages"
+ " SET raw = NULL, cleanupDeadline = NULL"
+ " WHERE messageId = ?";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, m.getBytes()); ps.setBytes(1, m.getBytes());
int affected = ps.executeUpdate(); int affected = ps.executeUpdate();
@@ -1769,7 +1784,6 @@ abstract class JdbcDatabase implements Database<Connection> {
// Return early if there are no matches // Return early if there are no matches
if (intersection.isEmpty()) return Collections.emptySet(); if (intersection.isEmpty()) return Collections.emptySet();
} }
if (intersection == null) throw new AssertionError();
return intersection; return intersection;
} catch (SQLException e) { } catch (SQLException e) {
tryToClose(rs, LOG, WARNING); tryToClose(rs, LOG, WARNING);
@@ -2226,6 +2240,39 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@Override
public Map<GroupId, Collection<MessageId>> getMessagesToDelete(
Connection txn) throws DbException {
long now = clock.currentTimeMillis();
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT messageId, groupId FROM messages"
+ " WHERE cleanupDeadline <= ?";
ps = txn.prepareStatement(sql);
ps.setLong(1, now);
rs = ps.executeQuery();
Map<GroupId, Collection<MessageId>> ids = new HashMap<>();
while (rs.next()) {
MessageId m = new MessageId(rs.getBytes(1));
GroupId g = new GroupId(rs.getBytes(2));
Collection<MessageId> messageIds = ids.get(g);
if (messageIds == null) {
messageIds = new ArrayList<>();
ids.put(g, messageIds);
}
messageIds.add(m);
}
rs.close();
ps.close();
return ids;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override @Override
public long getNextSendTime(Connection txn, ContactId c) public long getNextSendTime(Connection txn, ContactId c)
throws DbException { throws DbException {
@@ -2256,6 +2303,31 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@Override
public long getNextCleanupDeadline(Connection txn) throws DbException {
Statement s = null;
ResultSet rs = null;
try {
String sql = "SELECT cleanupDeadline FROM messages"
+ " WHERE cleanupDeadline IS NOT NULL"
+ " ORDER BY cleanupDeadline LIMIT 1";
s = txn.createStatement();
rs = s.executeQuery(sql);
long nextDeadline = NO_CLEANUP_DEADLINE;
if (rs.next()) {
nextDeadline = rs.getLong(1);
if (rs.next()) throw new AssertionError();
}
rs.close();
s.close();
return nextDeadline;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(s, LOG, WARNING);
throw new DbException(e);
}
}
@Override @Override
public PendingContact getPendingContact(Connection txn, PendingContactId p) public PendingContact getPendingContact(Connection txn, PendingContactId p)
throws DbException { throws DbException {
@@ -2776,7 +2848,7 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
@Override @Override
public void raiseSeenFlag(Connection txn, ContactId c, MessageId m) public boolean raiseSeenFlag(Connection txn, ContactId c, MessageId m)
throws DbException { throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
@@ -2788,6 +2860,7 @@ abstract class JdbcDatabase implements Database<Connection> {
int affected = ps.executeUpdate(); int affected = ps.executeUpdate();
if (affected < 0 || affected > 1) throw new DbStateException(); if (affected < 0 || affected > 1) throw new DbStateException();
ps.close(); ps.close();
return affected == 1;
} catch (SQLException e) { } catch (SQLException e) {
tryToClose(ps, LOG, WARNING); tryToClose(ps, LOG, WARNING);
throw new DbException(e); throw new DbException(e);
@@ -3021,6 +3094,25 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@Override
public void setCleanupTimerDuration(Connection txn, MessageId m,
long duration) throws DbException {
PreparedStatement ps = null;
try {
String sql = "UPDATE messages SET cleanupTimerDuration = ?"
+ " WHERE messageId = ? AND cleanupTimerDuration IS NULL";
ps = txn.prepareStatement(sql);
ps.setLong(1, duration);
ps.setBytes(2, m.getBytes());
int affected = ps.executeUpdate();
if (affected < 0 || affected > 1) throw new DbStateException();
ps.close();
} catch (SQLException e) {
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override @Override
public void setContactVerified(Connection txn, ContactId c) public void setContactVerified(Connection txn, ContactId c)
throws DbException { throws DbException {
@@ -3058,23 +3150,6 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@Override
public void setHandshakePublicKey(Connection txn, ContactId c, PublicKey handshakePublicKey) throws DbException {
PreparedStatement ps = null;
try {
String sql = "UPDATE contacts SET handshakePublicKey = ? WHERE contactId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, handshakePublicKey.getEncoded());
ps.setInt(2, c.getInt());
int affected = ps.executeUpdate();
if (affected < 0 || affected > 1) throw new DbStateException();
ps.close();
} catch (SQLException e) {
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override @Override
public void setGroupVisibility(Connection txn, ContactId c, GroupId g, public void setGroupVisibility(Connection txn, ContactId c, GroupId g,
boolean shared) throws DbException { boolean shared) throws DbException {
@@ -3145,22 +3220,24 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
@Override @Override
public void setMessageShared(Connection txn, MessageId m) public void setMessageShared(Connection txn, MessageId m, boolean shared)
throws DbException { throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
String sql = "UPDATE messages SET shared = TRUE" String sql = "UPDATE messages SET shared = ?"
+ " WHERE messageId = ?"; + " WHERE messageId = ?";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, m.getBytes()); ps.setBoolean(1, shared);
ps.setBytes(2, m.getBytes());
int affected = ps.executeUpdate(); int affected = ps.executeUpdate();
if (affected < 0 || affected > 1) throw new DbStateException(); if (affected < 0 || affected > 1) throw new DbStateException();
ps.close(); ps.close();
// Update denormalised column in statuses // Update denormalised column in statuses
sql = "UPDATE statuses SET messageShared = TRUE" sql = "UPDATE statuses SET messageShared = ?"
+ " WHERE messageId = ?"; + " WHERE messageId = ?";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, m.getBytes()); ps.setBoolean(1, shared);
ps.setBytes(2, m.getBytes());
affected = ps.executeUpdate(); affected = ps.executeUpdate();
if (affected < 0) throw new DbStateException(); if (affected < 0) throw new DbStateException();
ps.close(); ps.close();
@@ -3289,6 +3366,60 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@Override
public long startCleanupTimer(Connection txn, MessageId m)
throws DbException {
long now = clock.currentTimeMillis();
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "UPDATE messages"
+ " SET cleanupDeadline = ? + cleanupTimerDuration"
+ " WHERE messageId = ?"
+ " AND cleanupTimerDuration IS NOT NULL"
+ " AND cleanupDeadline IS NULL";
ps = txn.prepareStatement(sql);
ps.setLong(1, now);
ps.setBytes(2, m.getBytes());
int affected = ps.executeUpdate();
if (affected < 0 || affected > 1) throw new DbStateException();
ps.close();
if (affected == 0) return TIMER_NOT_STARTED;
sql = "SELECT cleanupDeadline FROM messages WHERE messageId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, m.getBytes());
rs = ps.executeQuery();
if (!rs.next()) throw new DbStateException();
long deadline = rs.getLong(1);
if (rs.next()) throw new DbStateException();
rs.close();
ps.close();
return deadline;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override
public void stopCleanupTimer(Connection txn, MessageId m)
throws DbException {
PreparedStatement ps = null;
try {
String sql = "UPDATE messages SET cleanupDeadline = NULL"
+ " WHERE messageId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, m.getBytes());
int affected = ps.executeUpdate();
if (affected < 0 || affected > 1) throw new DbStateException();
ps.close();
} catch (SQLException e) {
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override @Override
public void updateExpiryTimeAndEta(Connection txn, ContactId c, MessageId m, public void updateExpiryTimeAndEta(Connection txn, ContactId c, MessageId m,
int maxLatency) throws DbException { int maxLatency) throws DbException {

View File

@@ -0,0 +1,47 @@
package org.briarproject.bramble.db;
import org.briarproject.bramble.api.db.DbException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
class Migration47_48 implements Migration<Connection> {
private static final Logger LOG = getLogger(Migration47_48.class.getName());
@Override
public int getStartVersion() {
return 47;
}
@Override
public int getEndVersion() {
return 48;
}
@Override
public void migrate(Connection txn) throws DbException {
Statement s = null;
try {
s = txn.createStatement();
// Null if no timer duration has been set
s.execute("ALTER TABLE messages"
+ " ADD COLUMN cleanupTimerDuration BIGINT");
// Null if no timer duration has been set or the timer
// hasn't started
s.execute("ALTER TABLE messages"
+ " ADD COLUMN cleanupDeadline BIGINT");
s.execute("CREATE INDEX IF NOT EXISTS messagesByCleanupDeadline"
+ " ON messages (cleanupDeadline)");
} catch (SQLException e) {
tryToClose(s, LOG, WARNING);
throw new DbException(e);
}
}
}

View File

@@ -118,11 +118,6 @@ class IdentityManagerImpl implements IdentityManager, OpenDatabaseHook {
return cached.getLocalAuthor(); return cached.getLocalAuthor();
} }
@Override
public Identity getIdentity(Transaction txn) throws DbException {
return getCachedIdentity(txn);
}
@Override @Override
public LocalAuthor getLocalAuthor(Transaction txn) throws DbException { public LocalAuthor getLocalAuthor(Transaction txn) throws DbException {
return getCachedIdentity(txn).getLocalAuthor(); return getCachedIdentity(txn).getLocalAuthor();

View File

@@ -127,7 +127,6 @@ class KeyAgreementConnector {
List<Pair<DuplexPlugin, BdfList>> transports = new ArrayList<>(); List<Pair<DuplexPlugin, BdfList>> transports = new ArrayList<>();
for (TransportId id : PREFERRED_TRANSPORTS) { for (TransportId id : PREFERRED_TRANSPORTS) {
TransportDescriptor d = descriptors.get(id); TransportDescriptor d = descriptors.get(id);
LOG.info("id: " + id + " d: " + d);
Plugin p = pluginManager.getPlugin(id); Plugin p = pluginManager.getPlugin(id);
if (d != null && p instanceof DuplexPlugin) { if (d != null && p instanceof DuplexPlugin) {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
@@ -138,9 +137,6 @@ class KeyAgreementConnector {
// TODO: If we don't have any transports in common with the peer, // TODO: If we don't have any transports in common with the peer,
// warn the user and give up (#1224) // warn the user and give up (#1224)
if (transports.isEmpty()) {
LOG.info("No transports found");
}
if (!transports.isEmpty()) { if (!transports.isEmpty()) {
byte[] commitment = remotePayload.getCommitment(); byte[] commitment = remotePayload.getCommitment();

View File

@@ -34,12 +34,12 @@ class KeyAgreementTransport {
Logger.getLogger(KeyAgreementTransport.class.getName()); Logger.getLogger(KeyAgreementTransport.class.getName());
// Accept records with current protocol version, known record type // Accept records with current protocol version, known record type
private static final Predicate<Record> ACCEPT = r -> private static Predicate<Record> ACCEPT = r ->
r.getProtocolVersion() == PROTOCOL_VERSION && r.getProtocolVersion() == PROTOCOL_VERSION &&
isKnownRecordType(r.getRecordType()); isKnownRecordType(r.getRecordType());
// Ignore records with current protocol version, unknown record type // Ignore records with current protocol version, unknown record type
private static final Predicate<Record> IGNORE = r -> private static Predicate<Record> IGNORE = r ->
r.getProtocolVersion() == PROTOCOL_VERSION && r.getProtocolVersion() == PROTOCOL_VERSION &&
!isKnownRecordType(r.getRecordType()); !isKnownRecordType(r.getRecordType());

View File

@@ -5,9 +5,9 @@ import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec; import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import org.briarproject.bramble.util.Base32; import org.briarproject.bramble.util.Base32;
import org.bouncycastle.crypto.Digest; import org.spongycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA3Digest; import org.spongycastle.crypto.digests.SHA3Digest;
import org.bouncycastle.util.encoders.Base64; import org.spongycastle.util.encoders.Base64;
import java.nio.charset.Charset; import java.nio.charset.Charset;

View File

@@ -294,13 +294,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
public TransportProperties getRemoteProperties(ContactId c, TransportId t) public TransportProperties getRemoteProperties(ContactId c, TransportId t)
throws DbException { throws DbException {
return db.transactionWithResult(true, txn -> return db.transactionWithResult(true, txn ->
getRemoteProperties(txn, c, t)); getRemoteProperties(txn, db.getContact(txn, c), t));
}
@Override
public TransportProperties getRemoteProperties(Transaction txn,
ContactId c, TransportId t) throws DbException {
return getRemoteProperties(txn, db.getContact(txn, c), t);
} }
@Override @Override

View File

@@ -3,9 +3,9 @@ package org.briarproject.bramble.rendezvous;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.rendezvous.KeyMaterialSource; import org.briarproject.bramble.api.rendezvous.KeyMaterialSource;
import org.bouncycastle.crypto.engines.Salsa20Engine; import org.spongycastle.crypto.engines.Salsa20Engine;
import org.bouncycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV; import org.spongycastle.crypto.params.ParametersWithIV;
import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.ThreadSafe;

View File

@@ -101,9 +101,9 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
} }
@Override @Override
public Map<TransportId, KeySetId> addRotationKeys(Transaction txn, public Map<TransportId, KeySetId> addRotationKeys(
ContactId c, SecretKey rootKey, long timestamp, boolean alice, Transaction txn, ContactId c, SecretKey rootKey, long timestamp,
boolean active) throws DbException { boolean alice, boolean active) throws DbException {
Map<TransportId, KeySetId> ids = new HashMap<>(); Map<TransportId, KeySetId> ids = new HashMap<>();
for (Entry<TransportId, TransportKeyManager> e : managers.entrySet()) { for (Entry<TransportId, TransportKeyManager> e : managers.entrySet()) {
TransportId t = e.getKey(); TransportId t = e.getKey();
@@ -114,14 +114,6 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
return ids; return ids;
} }
@Override
public Map<TransportId, KeySetId> addRotationKeys(ContactId c,
SecretKey rootKey, long timestamp, boolean alice, boolean active)
throws DbException {
return db.transactionWithResult(false, txn ->
addRotationKeys(txn, c, rootKey, timestamp, alice, active));
}
@Override @Override
public Map<TransportId, KeySetId> addContact(Transaction txn, ContactId c, public Map<TransportId, KeySetId> addContact(Transaction txn, ContactId c,
PublicKey theirPublicKey, KeyPair ourKeyPair) PublicKey theirPublicKey, KeyPair ourKeyPair)
@@ -145,7 +137,7 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
PendingContactId p, PublicKey theirPublicKey, KeyPair ourKeyPair) PendingContactId p, PublicKey theirPublicKey, KeyPair ourKeyPair)
throws DbException, GeneralSecurityException { throws DbException, GeneralSecurityException {
SecretKey staticMasterKey = transportCrypto SecretKey staticMasterKey = transportCrypto
.deriveStaticMasterKey(theirPublicKey, ourKeyPair); .deriveStaticMasterKey(theirPublicKey, ourKeyPair);
SecretKey rootKey = SecretKey rootKey =
transportCrypto.deriveHandshakeRootKey(staticMasterKey, true); transportCrypto.deriveHandshakeRootKey(staticMasterKey, true);
boolean alice = transportCrypto.isAlice(theirPublicKey, ourKeyPair); boolean alice = transportCrypto.isAlice(theirPublicKey, ourKeyPair);

View File

@@ -5,6 +5,5 @@ interface ClientVersioningConstants {
// Metadata keys // Metadata keys
String MSG_KEY_UPDATE_VERSION = "version"; String MSG_KEY_UPDATE_VERSION = "version";
String MSG_KEY_LOCAL = "local"; String MSG_KEY_LOCAL = "local";
String GROUP_KEY_CONTACT_ID = "contactId";
} }

View File

@@ -50,7 +50,6 @@ import static java.util.Collections.emptyList;
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
import static org.briarproject.bramble.versioning.ClientVersioningConstants.GROUP_KEY_CONTACT_ID;
import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_LOCAL; import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_LOCAL;
import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_UPDATE_VERSION; import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_UPDATE_VERSION;
@@ -161,13 +160,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager,
db.addGroup(txn, g); db.addGroup(txn, g);
db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED); db.setGroupVisibility(txn, c.getId(), g.getId(), SHARED);
// Attach the contact ID to the group // Attach the contact ID to the group
BdfDictionary meta = new BdfDictionary(); clientHelper.setContactId(txn, g.getId(), c.getId());
meta.put(GROUP_KEY_CONTACT_ID, c.getId().getInt());
try {
clientHelper.mergeGroupMetadata(txn, g.getId(), meta);
} catch (FormatException e) {
throw new AssertionError(e);
}
// Create and store the first local update // Create and store the first local update
List<ClientVersion> versions = new ArrayList<>(clients); List<ClientVersion> versions = new ArrayList<>(clients);
Collections.sort(versions); Collections.sort(versions);
@@ -229,7 +222,7 @@ class ClientVersioningManagerImpl implements ClientVersioningManager,
Map<ClientMajorVersion, Visibility> after = Map<ClientMajorVersion, Visibility> after =
getVisibilities(newLocalStates, newRemoteStates); getVisibilities(newLocalStates, newRemoteStates);
// Call hooks for any visibilities that have changed // Call hooks for any visibilities that have changed
ContactId c = getContactId(txn, m.getGroupId()); ContactId c = clientHelper.getContactId(txn, m.getGroupId());
if (!before.equals(after)) { if (!before.equals(after)) {
Contact contact = db.getContact(txn, c); Contact contact = db.getContact(txn, c);
callVisibilityHooks(txn, contact, before, after); callVisibilityHooks(txn, contact, before, after);
@@ -521,17 +514,6 @@ class ClientVersioningManagerImpl implements ClientVersioningManager,
storeUpdate(txn, g, states, 1); storeUpdate(txn, g, states, 1);
} }
private ContactId getContactId(Transaction txn, GroupId g)
throws DbException {
try {
BdfDictionary meta =
clientHelper.getGroupMetadataAsDictionary(txn, g);
return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue());
} catch (FormatException e) {
throw new DbException(e);
}
}
private List<ClientState> updateStatesFromRemoteStates( private List<ClientState> updateStatesFromRemoteStates(
List<ClientState> oldLocalStates, List<ClientState> remoteStates) { List<ClientState> oldLocalStates, List<ClientState> remoteStates) {
Set<ClientMajorVersion> remoteSet = new HashSet<>(); Set<ClientMajorVersion> remoteSet = new HashSet<>();

View File

@@ -2,11 +2,12 @@ Bridge obfs4 192.95.36.142:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUV
Bridge obfs4 38.229.1.78:80 C8CBDB2464FC9804A69531437BCF2BE31FDD2EE4 cert=Hmyfd2ev46gGY7NoVxA9ngrPF2zCZtzskRTzoWXbxNkzeVnGFPWmrTtILRyqCTjHR+s9dg iat-mode=1 Bridge obfs4 38.229.1.78:80 C8CBDB2464FC9804A69531437BCF2BE31FDD2EE4 cert=Hmyfd2ev46gGY7NoVxA9ngrPF2zCZtzskRTzoWXbxNkzeVnGFPWmrTtILRyqCTjHR+s9dg iat-mode=1
Bridge obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0 Bridge obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0
Bridge obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0 Bridge obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0
Bridge obfs4 144.217.20.138:80 FB70B257C162BF1038CA669D568D76F5B7F0BABB cert=vYIV5MgrghGQvZPIi1tJwnzorMgqgmlKaB77Y3Z9Q/v94wZBOAXkW+fdx4aSxLVnKO+xNw iat-mode=0 Bridge obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0
Bridge obfs4 193.11.166.194:27015 2D82C2E354D531A68469ADF7F878FA6060C6BACA cert=4TLQPJrTSaDffMK7Nbao6LC7G9OW/NHkUwIdjLSS3KYf0Nv4/nQiiI8dY2TcsQx01NniOg iat-mode=0 Bridge obfs4 193.11.166.194:27015 2D82C2E354D531A68469ADF7F878FA6060C6BACA cert=4TLQPJrTSaDffMK7Nbao6LC7G9OW/NHkUwIdjLSS3KYf0Nv4/nQiiI8dY2TcsQx01NniOg iat-mode=0
Bridge obfs4 193.11.166.194:27020 86AC7B8D430DAC4117E9F42C9EAED18133863AAF cert=0LDeJH4JzMDtkJJrFphJCiPqKx7loozKN7VNfuukMGfHO0Z8OGdzHVkhVAOfo1mUdv9cMg iat-mode=0 Bridge obfs4 193.11.166.194:27020 86AC7B8D430DAC4117E9F42C9EAED18133863AAF cert=0LDeJH4JzMDtkJJrFphJCiPqKx7loozKN7VNfuukMGfHO0Z8OGdzHVkhVAOfo1mUdv9cMg iat-mode=0
Bridge obfs4 193.11.166.194:27025 1AE2C08904527FEA90C4C4F8C1083EA59FBC6FAF cert=ItvYZzW5tn6v3G4UnQa6Qz04Npro6e81AP70YujmK/KXwDFPTs3aHXcHp4n8Vt6w/bv8cA iat-mode=0 Bridge obfs4 193.11.166.194:27025 1AE2C08904527FEA90C4C4F8C1083EA59FBC6FAF cert=ItvYZzW5tn6v3G4UnQa6Qz04Npro6e81AP70YujmK/KXwDFPTs3aHXcHp4n8Vt6w/bv8cA iat-mode=0
Bridge obfs4 209.148.46.65:443 74FAD13168806246602538555B5521A0383A1875 cert=ssH+9rP8dG2NLDN2XuFw63hIO/9MNNinLmxQDpVa+7kTOa9/m+tGWT1SmSYpQ9uTBGa6Hw iat-mode=0 Bridge obfs4 209.148.46.65:443 74FAD13168806246602538555B5521A0383A1875 cert=ssH+9rP8dG2NLDN2XuFw63hIO/9MNNinLmxQDpVa+7kTOa9/m+tGWT1SmSYpQ9uTBGa6Hw iat-mode=0
Bridge obfs4 146.57.248.225:22 10A6CD36A537FCE513A322361547444B393989F0 cert=K1gDtDAIcUfeLqbstggjIw2rtgIKqdIhUlHp82XRqNSq/mtAjp1BIC9vHKJ2FAEpGssTPw iat-mode=0
Bridge obfs4 45.145.95.6:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0 Bridge obfs4 45.145.95.6:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0
Bridge obfs4 51.222.13.177:80 5EDAC3B810E12B01F6FD8050D2FD3E277B289A08 cert=2uplIpLQ0q9+0qMFrK5pkaYRDOe460LL9WHBvatgkuRr/SL31wBOEupaMMJ6koRE6Ld0ew iat-mode=0 Bridge obfs4 51.222.13.177:80 5EDAC3B810E12B01F6FD8050D2FD3E277B289A08 cert=2uplIpLQ0q9+0qMFrK5pkaYRDOe460LL9WHBvatgkuRr/SL31wBOEupaMMJ6koRE6Ld0ew iat-mode=0
Bridge obfs4 78.46.188.239:37356 5A2D2F4158D0453E00C7C176978D3F41D69C45DB cert=3c0SwxpOisbohNxEc4tb875RVW8eOu1opRTVXJhafaKA/PNNtI7ElQIVOVZg1AdL5bxGCw iat-mode=0 Bridge obfs4 78.46.188.239:37356 5A2D2F4158D0453E00C7C176978D3F41D69C45DB cert=3c0SwxpOisbohNxEc4tb875RVW8eOu1opRTVXJhafaKA/PNNtI7ElQIVOVZg1AdL5bxGCw iat-mode=0

View File

@@ -1,18 +1,18 @@
package org.briarproject.bramble; package org.briarproject.bramble;
import org.briarproject.bramble.system.DefaultTaskSchedulerModule; import org.briarproject.bramble.system.TimeTravelModule;
public interface BrambleCoreIntegrationTestEagerSingletons public interface BrambleCoreIntegrationTestEagerSingletons
extends BrambleCoreEagerSingletons { extends BrambleCoreEagerSingletons {
void inject(DefaultTaskSchedulerModule.EagerSingletons init); void inject(TimeTravelModule.EagerSingletons init);
class Helper { class Helper {
public static void injectEagerSingletons( public static void injectEagerSingletons(
BrambleCoreIntegrationTestEagerSingletons c) { BrambleCoreIntegrationTestEagerSingletons c) {
BrambleCoreEagerSingletons.Helper.injectEagerSingletons(c); BrambleCoreEagerSingletons.Helper.injectEagerSingletons(c);
c.inject(new DefaultTaskSchedulerModule.EagerSingletons()); c.inject(new TimeTravelModule.EagerSingletons());
} }
} }
} }

View File

@@ -13,7 +13,7 @@ import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageContext; import org.briarproject.bramble.api.sync.MessageContext;
import org.briarproject.bramble.test.ValidatorTestCase; import org.briarproject.bramble.test.ValidatorTestCase;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.imposters.ByteBuddyClassImposteriser; import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Test; import org.junit.Test;
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE; import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
@@ -38,7 +38,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
private final Metadata meta = new Metadata(); private final Metadata meta = new Metadata();
public BdfMessageValidatorTest() { public BdfMessageValidatorTest() {
context.setImposteriser(ByteBuddyClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
} }
@Test(expected = InvalidMessageException.class) @Test(expected = InvalidMessageException.class)

View File

@@ -3,7 +3,7 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.junit.Test; import org.junit.Test;
import org.bouncycastle.crypto.digests.Blake2bDigest; import org.spongycastle.crypto.digests.Blake2bDigest;
import java.util.Random; import java.util.Random;

View File

@@ -0,0 +1,115 @@
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test;
import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.spongycastle.asn1.x9.X9ECParameters;
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
import org.spongycastle.crypto.params.ECDomainParameters;
import org.spongycastle.crypto.params.ECKeyGenerationParameters;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.spongycastle.math.ec.ECCurve;
import org.spongycastle.math.ec.ECPoint;
import org.spongycastle.math.ec.MontgomeryLadderMultiplier;
import java.math.BigInteger;
import java.security.SecureRandom;
import static org.junit.Assert.assertEquals;
public class EllipticCurveMultiplicationTest extends BrambleTestCase {
@Test
public void testMultiplierProducesSameResultsAsDefault() throws Exception {
// Instantiate the default implementation of the curve
X9ECParameters defaultX9Parameters =
TeleTrusTNamedCurves.getByName("brainpoolp256r1");
ECCurve defaultCurve = defaultX9Parameters.getCurve();
ECPoint defaultG = defaultX9Parameters.getG();
BigInteger defaultN = defaultX9Parameters.getN();
BigInteger defaultH = defaultX9Parameters.getH();
ECDomainParameters defaultParameters = new ECDomainParameters(
defaultCurve, defaultG, defaultN, defaultH);
// Instantiate an implementation using the Montgomery ladder multiplier
ECDomainParameters montgomeryParameters =
constantTime(defaultParameters);
// Generate two key pairs with each set of parameters, using the same
// deterministic PRNG for both sets of parameters
byte[] seed = new byte[32];
new SecureRandom().nextBytes(seed);
// Montgomery ladder multiplier
SecureRandom random = new PseudoSecureRandom(seed);
ECKeyGenerationParameters montgomeryGeneratorParams =
new ECKeyGenerationParameters(montgomeryParameters, random);
ECKeyPairGenerator montgomeryGenerator = new ECKeyPairGenerator();
montgomeryGenerator.init(montgomeryGeneratorParams);
AsymmetricCipherKeyPair montgomeryKeyPair1 =
montgomeryGenerator.generateKeyPair();
ECPrivateKeyParameters montgomeryPrivate1 =
(ECPrivateKeyParameters) montgomeryKeyPair1.getPrivate();
ECPublicKeyParameters montgomeryPublic1 =
(ECPublicKeyParameters) montgomeryKeyPair1.getPublic();
AsymmetricCipherKeyPair montgomeryKeyPair2 =
montgomeryGenerator.generateKeyPair();
ECPrivateKeyParameters montgomeryPrivate2 =
(ECPrivateKeyParameters) montgomeryKeyPair2.getPrivate();
ECPublicKeyParameters montgomeryPublic2 =
(ECPublicKeyParameters) montgomeryKeyPair2.getPublic();
// Default multiplier
random = new PseudoSecureRandom(seed);
ECKeyGenerationParameters defaultGeneratorParams =
new ECKeyGenerationParameters(defaultParameters, random);
ECKeyPairGenerator defaultGenerator = new ECKeyPairGenerator();
defaultGenerator.init(defaultGeneratorParams);
AsymmetricCipherKeyPair defaultKeyPair1 =
defaultGenerator.generateKeyPair();
ECPrivateKeyParameters defaultPrivate1 =
(ECPrivateKeyParameters) defaultKeyPair1.getPrivate();
ECPublicKeyParameters defaultPublic1 =
(ECPublicKeyParameters) defaultKeyPair1.getPublic();
AsymmetricCipherKeyPair defaultKeyPair2 =
defaultGenerator.generateKeyPair();
ECPrivateKeyParameters defaultPrivate2 =
(ECPrivateKeyParameters) defaultKeyPair2.getPrivate();
ECPublicKeyParameters defaultPublic2 =
(ECPublicKeyParameters) defaultKeyPair2.getPublic();
// The key pairs generated with both sets of parameters should be equal
assertEquals(montgomeryPrivate1.getD(), defaultPrivate1.getD());
assertEquals(montgomeryPublic1.getQ(), defaultPublic1.getQ());
assertEquals(montgomeryPrivate2.getD(), defaultPrivate2.getD());
assertEquals(montgomeryPublic2.getQ(), defaultPublic2.getQ());
// OK, all of the above was just sanity checks - now for the test!
ECDHCBasicAgreement agreement = new ECDHCBasicAgreement();
agreement.init(montgomeryPrivate1);
BigInteger sharedSecretMontgomeryMontgomery =
agreement.calculateAgreement(montgomeryPublic2);
agreement.init(montgomeryPrivate1);
BigInteger sharedSecretMontgomeryDefault =
agreement.calculateAgreement(defaultPublic2);
agreement.init(defaultPrivate1);
BigInteger sharedSecretDefaultMontgomery =
agreement.calculateAgreement(montgomeryPublic2);
agreement.init(defaultPrivate1);
BigInteger sharedSecretDefaultDefault =
agreement.calculateAgreement(defaultPublic2);
// Shared secrets calculated with different multipliers should be equal
assertEquals(sharedSecretMontgomeryMontgomery,
sharedSecretMontgomeryDefault);
assertEquals(sharedSecretMontgomeryMontgomery,
sharedSecretDefaultMontgomery);
assertEquals(sharedSecretMontgomeryMontgomery,
sharedSecretDefaultDefault);
}
private static ECDomainParameters constantTime(ECDomainParameters in) {
ECCurve curve = in.getCurve().configure().setMultiplier(
new MontgomeryLadderMultiplier()).create();
BigInteger x = in.getG().getAffineXCoord().toBigInteger();
BigInteger y = in.getG().getAffineYCoord().toBigInteger();
ECPoint g = curve.createPoint(x, y);
return new ECDomainParameters(curve, g, in.getN(), in.getH());
}
}

View File

@@ -3,26 +3,30 @@ package org.briarproject.bramble.crypto;
import net.i2p.crypto.eddsa.EdDSASecurityProvider; import net.i2p.crypto.eddsa.EdDSASecurityProvider;
import net.i2p.crypto.eddsa.KeyPairGenerator; import net.i2p.crypto.eddsa.KeyPairGenerator;
import org.bouncycastle.asn1.sec.SECNamedCurves; import org.spongycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters; import org.spongycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.spongycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.BasicAgreement; import org.spongycastle.crypto.BasicAgreement;
import org.bouncycastle.crypto.Digest; import org.spongycastle.crypto.Digest;
import org.bouncycastle.crypto.agreement.ECDHBasicAgreement; import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement; import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
import org.bouncycastle.crypto.digests.Blake2bDigest; import org.spongycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.spongycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters; import org.spongycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom; import org.spongycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.DSADigestSigner; import org.spongycastle.crypto.signers.DSADigestSigner;
import org.bouncycastle.crypto.signers.DSAKCalculator; import org.spongycastle.crypto.signers.DSAKCalculator;
import org.bouncycastle.crypto.signers.ECDSASigner; import org.spongycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.crypto.signers.HMacDSAKCalculator; import org.spongycastle.crypto.signers.HMacDSAKCalculator;
import org.spongycastle.math.ec.ECCurve;
import org.spongycastle.math.ec.ECPoint;
import org.spongycastle.math.ec.MontgomeryLadderMultiplier;
import org.whispersystems.curve25519.Curve25519; import org.whispersystems.curve25519.Curve25519;
import org.whispersystems.curve25519.Curve25519KeyPair; import org.whispersystems.curve25519.Curve25519KeyPair;
import java.math.BigInteger;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.Provider; import java.security.Provider;
@@ -51,12 +55,14 @@ public class EllipticCurvePerformanceTest {
for (String name : SEC_NAMES) { for (String name : SEC_NAMES) {
ECDomainParameters params = ECDomainParameters params =
convertParams(SECNamedCurves.getByName(name)); convertParams(SECNamedCurves.getByName(name));
runTest(name, params); runTest(name + " default", params);
runTest(name + " constant", constantTime(params));
} }
for (String name : BRAINPOOL_NAMES) { for (String name : BRAINPOOL_NAMES) {
ECDomainParameters params = ECDomainParameters params =
convertParams(TeleTrusTNamedCurves.getByName(name)); convertParams(TeleTrusTNamedCurves.getByName(name));
runTest(name, params); runTest(name + " default", params);
runTest(name + " constant", constantTime(params));
} }
runCurve25519Test(); runCurve25519Test();
runEd25519Test(); runEd25519Test();
@@ -187,4 +193,13 @@ public class EllipticCurvePerformanceTest {
return new ECDomainParameters(in.getCurve(), in.getG(), in.getN(), return new ECDomainParameters(in.getCurve(), in.getG(), in.getN(),
in.getH()); in.getH());
} }
private static ECDomainParameters constantTime(ECDomainParameters in) {
ECCurve curve = in.getCurve().configure().setMultiplier(
new MontgomeryLadderMultiplier()).create();
BigInteger x = in.getG().getAffineXCoord().toBigInteger();
BigInteger y = in.getG().getAffineYCoord().toBigInteger();
ECPoint g = curve.createPoint(x, y);
return new ECDomainParameters(curve, g, in.getN(), in.getH());
}
} }

View File

@@ -5,7 +5,7 @@ import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test; import org.junit.Test;
import org.bouncycastle.crypto.CryptoException; import org.spongycastle.crypto.CryptoException;
import java.security.SecureRandom; import java.security.SecureRandom;

View File

@@ -1,11 +1,11 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.bouncycastle.crypto.Digest; import org.spongycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.Blake2bDigest; import org.spongycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.engines.Salsa20Engine; import org.spongycastle.crypto.engines.Salsa20Engine;
import org.bouncycastle.crypto.params.KeyParameter; import org.spongycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV; import org.spongycastle.crypto.params.ParametersWithIV;
import javax.annotation.concurrent.NotThreadSafe; import javax.annotation.concurrent.NotThreadSafe;

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.AuthenticatedCipher;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestUtils; import org.briarproject.bramble.test.TestUtils;

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.AuthenticatedCipher;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestUtils; import org.briarproject.bramble.test.TestUtils;

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.AuthenticatedCipher;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.AuthenticatedCipher;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble.db; package org.briarproject.bramble.db;
import org.briarproject.bramble.api.cleanup.event.CleanupTimerStartedEvent;
import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.PendingContactId; import org.briarproject.bramble.api.contact.PendingContactId;
@@ -69,6 +70,8 @@ import static java.util.Arrays.asList;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap; import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.HOURS;
import static org.briarproject.bramble.api.db.DatabaseComponent.TIMER_NOT_STARTED;
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED; import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
@@ -510,11 +513,11 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
throws Exception { throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check whether the group is in the DB (which it's not) // Check whether the group is in the DB (which it's not)
exactly(8).of(database).startTransaction(); exactly(10).of(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
exactly(8).of(database).containsGroup(txn, groupId); exactly(10).of(database).containsGroup(txn, groupId);
will(returnValue(false)); will(returnValue(false));
exactly(8).of(database).abortTransaction(txn); exactly(10).of(database).abortTransaction(txn);
// Allow other checks to pass // Allow other checks to pass
allowing(database).containsContact(txn, contactId); allowing(database).containsContact(txn, contactId);
will(returnValue(true)); will(returnValue(true));
@@ -523,7 +526,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
eventExecutor, shutdownManager); eventExecutor, shutdownManager);
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getGroup(transaction, groupId)); db.getGroup(transaction, groupId));
fail(); fail();
} catch (NoSuchGroupException expected) { } catch (NoSuchGroupException expected) {
@@ -531,7 +534,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getGroupMetadata(transaction, groupId)); db.getGroupMetadata(transaction, groupId));
fail(); fail();
} catch (NoSuchGroupException expected) { } catch (NoSuchGroupException expected) {
@@ -539,7 +542,23 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getMessageIds(transaction, groupId));
fail();
} catch (NoSuchGroupException expected) {
// Expected
}
try {
db.transaction(true, transaction ->
db.getMessageIds(transaction, groupId, new Metadata()));
fail();
} catch (NoSuchGroupException expected) {
// Expected
}
try {
db.transaction(true, transaction ->
db.getMessageMetadata(transaction, groupId)); db.getMessageMetadata(transaction, groupId));
fail(); fail();
} catch (NoSuchGroupException expected) { } catch (NoSuchGroupException expected) {
@@ -547,7 +566,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getMessageMetadata(transaction, groupId, db.getMessageMetadata(transaction, groupId,
new Metadata())); new Metadata()));
fail(); fail();
@@ -556,7 +575,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getMessageStatus(transaction, contactId, groupId)); db.getMessageStatus(transaction, contactId, groupId));
fail(); fail();
} catch (NoSuchGroupException expected) { } catch (NoSuchGroupException expected) {
@@ -594,11 +613,11 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
throws Exception { throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check whether the message is in the DB (which it's not) // Check whether the message is in the DB (which it's not)
exactly(12).of(database).startTransaction(); exactly(15).of(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
exactly(12).of(database).containsMessage(txn, messageId); exactly(15).of(database).containsMessage(txn, messageId);
will(returnValue(false)); will(returnValue(false));
exactly(12).of(database).abortTransaction(txn); exactly(15).of(database).abortTransaction(txn);
// Allow other checks to pass // Allow other checks to pass
allowing(database).containsContact(txn, contactId); allowing(database).containsContact(txn, contactId);
will(returnValue(true)); will(returnValue(true));
@@ -623,7 +642,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getMessage(transaction, messageId)); db.getMessage(transaction, messageId));
fail(); fail();
} catch (NoSuchMessageException expected) { } catch (NoSuchMessageException expected) {
@@ -631,7 +650,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getMessageMetadata(transaction, messageId)); db.getMessageMetadata(transaction, messageId));
fail(); fail();
} catch (NoSuchMessageException expected) { } catch (NoSuchMessageException expected) {
@@ -639,7 +658,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getMessageState(transaction, messageId)); db.getMessageState(transaction, messageId));
fail(); fail();
} catch (NoSuchMessageException expected) { } catch (NoSuchMessageException expected) {
@@ -647,7 +666,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getMessageStatus(transaction, contactId, messageId)); db.getMessageStatus(transaction, contactId, messageId));
fail(); fail();
} catch (NoSuchMessageException expected) { } catch (NoSuchMessageException expected) {
@@ -662,6 +681,15 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
// Expected // Expected
} }
try {
db.transaction(false, transaction ->
db.setCleanupTimerDuration(transaction, message.getId(),
HOURS.toMillis(1)));
fail();
} catch (NoSuchMessageException expected) {
// Expected
}
try { try {
db.transaction(false, transaction -> db.transaction(false, transaction ->
db.setMessagePermanent(transaction, message.getId())); db.setMessagePermanent(transaction, message.getId()));
@@ -687,7 +715,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getMessageDependencies(transaction, messageId)); db.getMessageDependencies(transaction, messageId));
fail(); fail();
} catch (NoSuchMessageException expected) { } catch (NoSuchMessageException expected) {
@@ -695,12 +723,28 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
} }
try { try {
db.transaction(false, transaction -> db.transaction(true, transaction ->
db.getMessageDependents(transaction, messageId)); db.getMessageDependents(transaction, messageId));
fail(); fail();
} catch (NoSuchMessageException expected) { } catch (NoSuchMessageException expected) {
// Expected // Expected
} }
try {
db.transaction(false, transaction ->
db.startCleanupTimer(transaction, messageId));
fail();
} catch (NoSuchMessageException expected) {
// Expected
}
try {
db.transaction(false, transaction ->
db.stopCleanupTimer(transaction, messageId));
fail();
} catch (NoSuchMessageException expected) {
// Expected
}
} }
@Test @Test
@@ -981,6 +1025,9 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
oneOf(database).containsVisibleMessage(txn, contactId, messageId); oneOf(database).containsVisibleMessage(txn, contactId, messageId);
will(returnValue(true)); will(returnValue(true));
oneOf(database).raiseSeenFlag(txn, contactId, messageId); oneOf(database).raiseSeenFlag(txn, contactId, messageId);
will(returnValue(true));
oneOf(database).startCleanupTimer(txn, messageId);
will(returnValue(TIMER_NOT_STARTED)); // No cleanup duration was set
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
oneOf(eventBus).broadcast(with(any(MessagesAckedEvent.class))); oneOf(eventBus).broadcast(with(any(MessagesAckedEvent.class)));
}}); }});
@@ -993,6 +1040,56 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
}); });
} }
@Test
public void testReceiveDuplicateAck() throws Exception {
context.checking(new Expectations() {{
oneOf(database).startTransaction();
will(returnValue(txn));
oneOf(database).containsContact(txn, contactId);
will(returnValue(true));
oneOf(database).containsVisibleMessage(txn, contactId, messageId);
will(returnValue(true));
oneOf(database).raiseSeenFlag(txn, contactId, messageId);
will(returnValue(false)); // Already acked
oneOf(database).commitTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, eventBus,
eventExecutor, shutdownManager);
db.transaction(false, transaction -> {
Ack a = new Ack(singletonList(messageId));
db.receiveAck(transaction, contactId, a);
});
}
@Test
public void testReceiveAckWithCleanupTimer() throws Exception {
long deadline = System.currentTimeMillis();
context.checking(new Expectations() {{
oneOf(database).startTransaction();
will(returnValue(txn));
oneOf(database).containsContact(txn, contactId);
will(returnValue(true));
oneOf(database).containsVisibleMessage(txn, contactId, messageId);
will(returnValue(true));
oneOf(database).raiseSeenFlag(txn, contactId, messageId);
will(returnValue(true));
oneOf(database).startCleanupTimer(txn, messageId);
will(returnValue(deadline));
oneOf(database).commitTransaction(txn);
oneOf(eventBus).broadcast(with(any(
CleanupTimerStartedEvent.class)));
oneOf(eventBus).broadcast(with(any(MessagesAckedEvent.class)));
}});
DatabaseComponent db = createDatabaseComponent(database, eventBus,
eventExecutor, shutdownManager);
db.transaction(false, transaction -> {
Ack a = new Ack(singletonList(messageId));
db.receiveAck(transaction, contactId, a);
});
}
@Test @Test
public void testReceiveMessage() throws Exception { public void testReceiveMessage() throws Exception {
context.checking(new Expectations() {{ context.checking(new Expectations() {{

View File

@@ -53,10 +53,11 @@ import java.util.concurrent.atomic.AtomicLong;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.SECONDS;
import static org.briarproject.bramble.api.db.DatabaseComponent.NO_CLEANUP_DEADLINE;
import static org.briarproject.bramble.api.db.DatabaseComponent.TIMER_NOT_STARTED;
import static org.briarproject.bramble.api.db.Metadata.REMOVE; import static org.briarproject.bramble.api.db.Metadata.REMOVE;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE; import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
@@ -351,7 +352,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertTrue(ids.isEmpty()); assertTrue(ids.isEmpty());
// Sharing the message should make it sendable // Sharing the message should make it sendable
db.setMessageShared(txn, messageId); db.setMessageShared(txn, messageId, true);
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY); ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY);
assertEquals(singletonList(messageId), ids); assertEquals(singletonList(messageId), ids);
ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY); ids = db.getMessagesToOffer(txn, contactId, 100, MAX_LATENCY);
@@ -631,8 +632,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// The group should not be visible to the contact // The group should not be visible to the contact
assertEquals(INVISIBLE, db.getGroupVisibility(txn, contactId, groupId)); assertEquals(INVISIBLE, db.getGroupVisibility(txn, contactId, groupId));
assertEquals(emptyMap(), assertTrue(db.getGroupVisibility(txn, groupId).isEmpty());
db.getGroupVisibility(txn, groupId));
// Make the group visible to the contact // Make the group visible to the contact
db.addGroupVisibility(txn, contactId, groupId, false); db.addGroupVisibility(txn, contactId, groupId, false);
@@ -655,8 +655,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
// Make the group invisible again // Make the group invisible again
db.removeGroupVisibility(txn, contactId, groupId); db.removeGroupVisibility(txn, contactId, groupId);
assertEquals(INVISIBLE, db.getGroupVisibility(txn, contactId, groupId)); assertEquals(INVISIBLE, db.getGroupVisibility(txn, contactId, groupId));
assertEquals(emptyMap(), assertTrue(db.getGroupVisibility(txn, groupId).isEmpty());
db.getGroupVisibility(txn, groupId));
db.commitTransaction(txn); db.commitTransaction(txn);
db.close(); db.close();
@@ -2040,7 +2039,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertEquals(Long.MAX_VALUE, db.getNextSendTime(txn, contactId)); assertEquals(Long.MAX_VALUE, db.getNextSendTime(txn, contactId));
// Share the message - now it should be sendable immediately // Share the message - now it should be sendable immediately
db.setMessageShared(txn, messageId); db.setMessageShared(txn, messageId, true);
assertEquals(0, db.getNextSendTime(txn, contactId)); assertEquals(0, db.getNextSendTime(txn, contactId));
// Mark the message as requested - it should still be sendable // Mark the message as requested - it should still be sendable
@@ -2347,6 +2346,87 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
db.close(); db.close();
} }
@Test
public void testCleanupTimer() throws Exception {
long duration = 60_000;
long now = System.currentTimeMillis();
AtomicLong time = new AtomicLong(now);
Database<Connection> db =
open(false, new TestMessageFactory(), new SettableClock(time));
Connection txn = db.startTransaction();
// No messages should be due or scheduled for deletion
assertTrue(db.getMessagesToDelete(txn).isEmpty());
assertEquals(NO_CLEANUP_DEADLINE, db.getNextCleanupDeadline(txn));
// Add a group and a message
db.addGroup(txn, group);
db.addMessage(txn, message, DELIVERED, false, false, null);
// No messages should be due or scheduled for deletion
assertTrue(db.getMessagesToDelete(txn).isEmpty());
assertEquals(NO_CLEANUP_DEADLINE, db.getNextCleanupDeadline(txn));
// Set the message's cleanup timer duration
db.setCleanupTimerDuration(txn, messageId, duration);
// No messages should be due or scheduled for deletion
assertTrue(db.getMessagesToDelete(txn).isEmpty());
assertEquals(NO_CLEANUP_DEADLINE, db.getNextCleanupDeadline(txn));
// Start the message's cleanup timer
assertEquals(now + duration, db.startCleanupTimer(txn, messageId));
// The timer can't be started again
assertEquals(TIMER_NOT_STARTED, db.startCleanupTimer(txn, messageId));
// No messages should be due for deletion, but the message should be
// scheduled for deletion
assertTrue(db.getMessagesToDelete(txn).isEmpty());
assertEquals(now + duration, db.getNextCleanupDeadline(txn));
// Stop the timer
db.stopCleanupTimer(txn, messageId);
// No messages should be due or scheduled for deletion
assertTrue(db.getMessagesToDelete(txn).isEmpty());
assertEquals(NO_CLEANUP_DEADLINE, db.getNextCleanupDeadline(txn));
// Start the timer again
assertEquals(now + duration, db.startCleanupTimer(txn, messageId));
// No messages should be due for deletion, but the message should be
// scheduled for deletion
assertTrue(db.getMessagesToDelete(txn).isEmpty());
assertEquals(now + duration, db.getNextCleanupDeadline(txn));
// 1 ms before the timer expires, no messages should be due for
// deletion but the message should be scheduled for deletion
time.set(now + duration - 1);
assertTrue(db.getMessagesToDelete(txn).isEmpty());
assertEquals(now + duration, db.getNextCleanupDeadline(txn));
// When the timer expires, the message should be due and scheduled for
// deletion
time.set(now + duration);
assertEquals(singletonMap(groupId, singletonList(messageId)),
db.getMessagesToDelete(txn));
assertEquals(now + duration, db.getNextCleanupDeadline(txn));
// 1 ms after the timer expires, the message should be due and
// scheduled for deletion
time.set(now + duration + 1);
assertEquals(singletonMap(groupId, singletonList(messageId)),
db.getMessagesToDelete(txn));
assertEquals(now + duration, db.getNextCleanupDeadline(txn));
// Once the message has been deleted, it should no longer be due
// or scheduled for deletion
db.deleteMessage(txn, messageId);
assertTrue(db.getMessagesToDelete(txn).isEmpty());
assertEquals(NO_CLEANUP_DEADLINE, db.getNextCleanupDeadline(txn));
}
private Database<Connection> open(boolean resume) throws Exception { private Database<Connection> open(boolean resume) throws Exception {
return open(resume, new TestMessageFactory(), new SystemClock()); return open(resume, new TestMessageFactory(), new SystemClock());
} }

View File

@@ -11,8 +11,8 @@ import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.auto.Mock; import org.jmock.auto.Mock;
import org.jmock.imposters.ByteBuddyClassImposteriser;
import org.jmock.integration.junit4.JUnitRuleMockery; import org.jmock.integration.junit4.JUnitRuleMockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@@ -34,7 +34,7 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
@Rule @Rule
public JUnitRuleMockery context = new JUnitRuleMockery() {{ public JUnitRuleMockery context = new JUnitRuleMockery() {{
// So we can mock concrete classes like KeyAgreementTransport // So we can mock concrete classes like KeyAgreementTransport
setImposteriser(ByteBuddyClassImposteriser.INSTANCE); setImposteriser(ClassImposteriser.INSTANCE);
}}; }};
private final PublicKey alicePubKey = getAgreementPublicKey(); private final PublicKey alicePubKey = getAgreementPublicKey();

View File

@@ -14,7 +14,7 @@ import org.briarproject.bramble.api.record.RecordWriterFactory;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.CaptureArgumentAction; import org.briarproject.bramble.test.CaptureArgumentAction;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.imposters.ByteBuddyClassImposteriser; import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Test; import org.junit.Test;
import java.io.InputStream; import java.io.InputStream;
@@ -58,7 +58,7 @@ public class KeyAgreementTransportTest extends BrambleMockTestCase {
private KeyAgreementTransport kat; private KeyAgreementTransport kat;
public KeyAgreementTransportTest() { public KeyAgreementTransportTest() {
context.setImposteriser(ByteBuddyClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
inputStream = context.mock(InputStream.class); inputStream = context.mock(InputStream.class);
outputStream = context.mock(OutputStream.class); outputStream = context.mock(OutputStream.class);
} }

View File

@@ -25,7 +25,7 @@ import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.ImmediateExecutor; import org.briarproject.bramble.test.ImmediateExecutor;
import org.briarproject.bramble.test.RunAction; import org.briarproject.bramble.test.RunAction;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.imposters.ByteBuddyClassImposteriser; import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -69,7 +69,7 @@ public class PollerImplTest extends BrambleMockTestCase {
private PollerImpl poller; private PollerImpl poller;
public PollerImplTest() { public PollerImplTest() {
context.setImposteriser(ByteBuddyClassImposteriser.INSTANCE); context.setImposteriser(ClassImposteriser.INSTANCE);
random = context.mock(SecureRandom.class); random = context.mock(SecureRandom.class);
} }

View File

@@ -0,0 +1,122 @@
package org.briarproject.bramble.system;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.TaskScheduler;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.junit.Assert.fail;
/**
* A {@link TaskScheduler} for use in tests. The scheduler keeps all scheduled
* tasks in a queue until {@link #runTasks()} is called.
*/
@NotNullByDefault
class TestTaskScheduler implements TaskScheduler {
private final Queue<Task> queue = new PriorityBlockingQueue<>();
private final Clock clock;
TestTaskScheduler(Clock clock) {
this.clock = clock;
}
@Override
public Cancellable schedule(Runnable task, Executor executor, long delay,
TimeUnit unit) {
AtomicBoolean cancelled = new AtomicBoolean(false);
return schedule(task, executor, delay, unit, cancelled);
}
@Override
public Cancellable scheduleWithFixedDelay(Runnable task, Executor executor,
long delay, long interval, TimeUnit unit) {
AtomicBoolean cancelled = new AtomicBoolean(false);
return scheduleWithFixedDelay(task, executor, delay, interval, unit,
cancelled);
}
private Cancellable schedule(Runnable task, Executor executor, long delay,
TimeUnit unit, AtomicBoolean cancelled) {
long delayMillis = MILLISECONDS.convert(delay, unit);
long dueMillis = clock.currentTimeMillis() + delayMillis;
Task t = new Task(task, executor, dueMillis, cancelled);
queue.add(t);
return t;
}
private Cancellable scheduleWithFixedDelay(Runnable task, Executor executor,
long delay, long interval, TimeUnit unit, AtomicBoolean cancelled) {
// All executions of this periodic task share a cancelled flag
Runnable wrapped = () -> {
task.run();
scheduleWithFixedDelay(task, executor, interval, interval, unit,
cancelled);
};
return schedule(wrapped, executor, delay, unit, cancelled);
}
/**
* Runs any scheduled tasks that are due.
*/
void runTasks() throws InterruptedException {
long now = clock.currentTimeMillis();
while (true) {
Task t = queue.peek();
if (t == null || t.dueMillis > now) return;
t = queue.poll();
// Submit the task to its executor and wait for it to finish
if (!t.run().await(1, MINUTES)) fail();
}
}
private static class Task
implements Cancellable, Comparable<Task> {
private final Runnable task;
private final Executor executor;
private final long dueMillis;
private final AtomicBoolean cancelled;
private Task(Runnable task, Executor executor, long dueMillis,
AtomicBoolean cancelled) {
this.task = task;
this.executor = executor;
this.dueMillis = dueMillis;
this.cancelled = cancelled;
}
@SuppressWarnings("UseCompareMethod") // Animal Sniffer
@Override
public int compareTo(Task task) {
return Long.valueOf(dueMillis).compareTo(task.dueMillis);
}
/**
* Submits the task to its executor and returns a latch that will be
* released when the task finishes.
*/
public CountDownLatch run() {
if (cancelled.get()) return new CountDownLatch(0);
CountDownLatch latch = new CountDownLatch(1);
executor.execute(() -> {
task.run();
latch.countDown();
});
return latch;
}
@Override
public void cancel() {
cancelled.set(true);
}
}
}

View File

@@ -0,0 +1,98 @@
package org.briarproject.bramble.system;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.TaskScheduler;
import org.briarproject.bramble.test.SettableClock;
import org.briarproject.bramble.test.TimeTravel;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicLong;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class TimeTravelModule {
public static class EagerSingletons {
@Inject
TaskScheduler scheduler;
}
private final ScheduledExecutorService scheduledExecutorService;
private final Clock clock;
private final TaskScheduler taskScheduler;
private final TimeTravel timeTravel;
public TimeTravelModule() {
this(false);
}
public TimeTravelModule(boolean travel) {
// Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy =
new ScheduledThreadPoolExecutor.DiscardPolicy();
scheduledExecutorService =
new ScheduledThreadPoolExecutor(1, policy);
if (travel) {
// Use a SettableClock and TestTaskScheduler to allow time travel
AtomicLong time = new AtomicLong(System.currentTimeMillis());
clock = new SettableClock(time);
TestTaskScheduler testTaskScheduler = new TestTaskScheduler(clock);
taskScheduler = testTaskScheduler;
timeTravel = new TimeTravel() {
@Override
public void setCurrentTimeMillis(long now)
throws InterruptedException {
time.set(now);
testTaskScheduler.runTasks();
}
@Override
public void addCurrentTimeMillis(long add)
throws InterruptedException {
time.addAndGet(add);
testTaskScheduler.runTasks();
}
};
} else {
// Use the default clock and task scheduler
clock = new SystemClock();
taskScheduler = new TaskSchedulerImpl(scheduledExecutorService);
timeTravel = new TimeTravel() {
@Override
public void setCurrentTimeMillis(long now) {
throw new UnsupportedOperationException();
}
@Override
public void addCurrentTimeMillis(long add) {
throw new UnsupportedOperationException();
}
};
}
}
@Provides
Clock provideClock() {
return clock;
}
@Provides
@Singleton
TaskScheduler provideTaskScheduler(LifecycleManager lifecycleManager) {
lifecycleManager.registerForShutdown(scheduledExecutorService);
return taskScheduler;
}
@Provides
TimeTravel provideTimeTravel() {
return timeTravel;
}
}

View File

@@ -3,8 +3,8 @@ package org.briarproject.bramble.test;
import org.briarproject.bramble.api.FeatureFlags; import org.briarproject.bramble.api.FeatureFlags;
import org.briarproject.bramble.battery.DefaultBatteryManagerModule; import org.briarproject.bramble.battery.DefaultBatteryManagerModule;
import org.briarproject.bramble.event.DefaultEventExecutorModule; import org.briarproject.bramble.event.DefaultEventExecutorModule;
import org.briarproject.bramble.system.DefaultTaskSchedulerModule;
import org.briarproject.bramble.system.DefaultWakefulIoExecutorModule; import org.briarproject.bramble.system.DefaultWakefulIoExecutorModule;
import org.briarproject.bramble.system.TimeTravelModule;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
@@ -12,11 +12,11 @@ import dagger.Provides;
@Module(includes = { @Module(includes = {
DefaultBatteryManagerModule.class, DefaultBatteryManagerModule.class,
DefaultEventExecutorModule.class, DefaultEventExecutorModule.class,
DefaultTaskSchedulerModule.class,
DefaultWakefulIoExecutorModule.class, DefaultWakefulIoExecutorModule.class,
TestDatabaseConfigModule.class, TestDatabaseConfigModule.class,
TestPluginConfigModule.class, TestPluginConfigModule.class,
TestSecureRandomModule.class TestSecureRandomModule.class,
TimeTravelModule.class
}) })
public class BrambleCoreIntegrationTestModule { public class BrambleCoreIntegrationTestModule {
@@ -33,6 +33,11 @@ public class BrambleCoreIntegrationTestModule {
public boolean shouldEnableProfilePictures() { public boolean shouldEnableProfilePictures() {
return true; return true;
} }
@Override
public boolean shouldEnableDisappearingMessages() {
return true;
}
}; };
} }
} }

View File

@@ -38,7 +38,6 @@ import static org.briarproject.bramble.test.TestUtils.getContact;
import static org.briarproject.bramble.test.TestUtils.getGroup; import static org.briarproject.bramble.test.TestUtils.getGroup;
import static org.briarproject.bramble.test.TestUtils.getMessage; import static org.briarproject.bramble.test.TestUtils.getMessage;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.versioning.ClientVersioningConstants.GROUP_KEY_CONTACT_ID;
import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_LOCAL; import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_LOCAL;
import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_UPDATE_VERSION; import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_UPDATE_VERSION;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@@ -60,8 +59,6 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
private final ClientId clientId = getClientId(); private final ClientId clientId = getClientId();
private final long now = System.currentTimeMillis(); private final long now = System.currentTimeMillis();
private final Transaction txn = new Transaction(null, false); private final Transaction txn = new Transaction(null, false);
private final BdfDictionary groupMeta = BdfDictionary.of(
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt()));
private ClientVersioningManagerImpl createInstance() { private ClientVersioningManagerImpl createInstance() {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -123,8 +120,8 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
oneOf(db).addGroup(txn, contactGroup); oneOf(db).addGroup(txn, contactGroup);
oneOf(db).setGroupVisibility(txn, contact.getId(), oneOf(db).setGroupVisibility(txn, contact.getId(),
contactGroup.getId(), SHARED); contactGroup.getId(), SHARED);
oneOf(clientHelper).mergeGroupMetadata(txn, contactGroup.getId(), oneOf(clientHelper).setContactId(txn, contactGroup.getId(),
groupMeta); contact.getId());
oneOf(clock).currentTimeMillis(); oneOf(clock).currentTimeMillis();
will(returnValue(now)); will(returnValue(now));
oneOf(clientHelper).createMessage(contactGroup.getId(), now, oneOf(clientHelper).createMessage(contactGroup.getId(), now,
@@ -460,9 +457,8 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
oneOf(db).deleteMessage(txn, oldRemoteUpdateId); oneOf(db).deleteMessage(txn, oldRemoteUpdateId);
oneOf(db).deleteMessageMetadata(txn, oldRemoteUpdateId); oneOf(db).deleteMessageMetadata(txn, oldRemoteUpdateId);
// Get contact ID // Get contact ID
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, oneOf(clientHelper).getContactId(txn, contactGroup.getId());
contactGroup.getId()); will(returnValue(contact.getId()));
will(returnValue(groupMeta));
// No states or visibilities have changed // No states or visibilities have changed
}}); }});
@@ -492,10 +488,9 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
// Load the latest local update // Load the latest local update
oneOf(clientHelper).getMessageAsList(txn, oldLocalUpdateId); oneOf(clientHelper).getMessageAsList(txn, oldLocalUpdateId);
will(returnValue(oldLocalUpdateBody)); will(returnValue(oldLocalUpdateBody));
// Get client ID // Get contact ID
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, oneOf(clientHelper).getContactId(txn, contactGroup.getId());
contactGroup.getId()); will(returnValue(contact.getId()));
will(returnValue(groupMeta));
// No states or visibilities have changed // No states or visibilities have changed
}}); }});
@@ -546,8 +541,6 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
BdfDictionary newLocalUpdateMeta = BdfDictionary.of( BdfDictionary newLocalUpdateMeta = BdfDictionary.of(
new BdfEntry(MSG_KEY_UPDATE_VERSION, 2L), new BdfEntry(MSG_KEY_UPDATE_VERSION, 2L),
new BdfEntry(MSG_KEY_LOCAL, true)); new BdfEntry(MSG_KEY_LOCAL, true));
BdfDictionary groupMeta = BdfDictionary.of(
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt()));
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(clientHelper).toList(newRemoteUpdate); oneOf(clientHelper).toList(newRemoteUpdate);
@@ -577,9 +570,8 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate, oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate,
newLocalUpdateMeta, true, false); newLocalUpdateMeta, true, false);
// The client's visibility has changed // The client's visibility has changed
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, oneOf(clientHelper).getContactId(txn, contactGroup.getId());
contactGroup.getId()); will(returnValue(contact.getId()));
will(returnValue(groupMeta));
oneOf(db).getContact(txn, contact.getId()); oneOf(db).getContact(txn, contact.getId());
will(returnValue(contact)); will(returnValue(contact));
oneOf(hook).onClientVisibilityChanging(txn, contact, visibility); oneOf(hook).onClientVisibilityChanging(txn, contact, visibility);
@@ -619,8 +611,6 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
BdfDictionary newLocalUpdateMeta = BdfDictionary.of( BdfDictionary newLocalUpdateMeta = BdfDictionary.of(
new BdfEntry(MSG_KEY_UPDATE_VERSION, 2L), new BdfEntry(MSG_KEY_UPDATE_VERSION, 2L),
new BdfEntry(MSG_KEY_LOCAL, true)); new BdfEntry(MSG_KEY_LOCAL, true));
BdfDictionary groupMeta = BdfDictionary.of(
new BdfEntry(GROUP_KEY_CONTACT_ID, contact.getId().getInt()));
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(clientHelper).toList(newRemoteUpdate); oneOf(clientHelper).toList(newRemoteUpdate);
@@ -650,9 +640,8 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate, oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate,
newLocalUpdateMeta, true, false); newLocalUpdateMeta, true, false);
// The client's visibility has changed // The client's visibility has changed
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, oneOf(clientHelper).getContactId(txn, contactGroup.getId());
contactGroup.getId()); will(returnValue(contact.getId()));
will(returnValue(groupMeta));
oneOf(db).getContact(txn, contact.getId()); oneOf(db).getContact(txn, contact.getId());
will(returnValue(contact)); will(returnValue(contact));
oneOf(hook).onClientVisibilityChanging(txn, contact, INVISIBLE); oneOf(hook).onClientVisibilityChanging(txn, contact, INVISIBLE);

View File

@@ -1,7 +1,6 @@
dependencyVerification { dependencyVerification {
verify = [ verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f', 'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f',
'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a', 'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a',
@@ -15,18 +14,17 @@ dependencyVerification {
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99', 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6', 'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c', 'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90', 'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f', 'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a', 'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140', 'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.jodah:concurrentunit:0.4.2:concurrentunit-0.4.2.jar:5583078e1acf91734939e985bc9e7ee947b0e93a8eef679da6bb07bbeb47ced3',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd', 'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047', 'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb', 'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.bouncycastle:bcprov-jdk15on:1.65:bcprov-jdk15on-1.65.jar:e78f96eb59066c94c94fb2d6b5eb80f52feac6f5f9776898634f8addec6e2137',
'org.briarproject:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864', 'org.briarproject:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d', 'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a', 'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
@@ -34,18 +32,16 @@ dependencyVerification {
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53', 'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90', 'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52', 'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9', 'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21', 'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.hsqldb:hsqldb:2.3.5:hsqldb-2.3.5.jar:6676a6977ac98997a80f827ddbd3fe8ca1e0853dad1492512135fd1a222ccfad', 'org.hsqldb:hsqldb:2.3.5:hsqldb-2.3.5.jar:6676a6977ac98997a80f827ddbd3fe8ca1e0853dad1492512135fd1a222ccfad',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09', 'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b', 'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd', 'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04', 'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be', 'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d', 'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de', 'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.whispersystems:curve25519-java:0.5.0:curve25519-java-0.5.0.jar:0aadd43cf01d11e9b58f867b3c4f25c3194e8b0623d1953d32dfbfbee009e38d', 'org.whispersystems:curve25519-java:0.5.0:curve25519-java-0.5.0.jar:0aadd43cf01d11e9b58f867b3c4f25c3194e8b0623d1953d32dfbfbee009e38d',
] ]
} }

View File

@@ -16,16 +16,17 @@ dependencies {
implementation fileTree(dir: 'libs', include: '*.jar') implementation fileTree(dir: 'libs', include: '*.jar')
implementation 'net.java.dev.jna:jna:4.5.2' implementation 'net.java.dev.jna:jna:4.5.2'
implementation 'net.java.dev.jna:jna-platform:4.5.2' implementation 'net.java.dev.jna:jna-platform:4.5.2'
tor 'org.briarproject:tor:0.3.5.13-1@zip' tor 'org.briarproject:tor:0.3.5.13@zip'
tor 'org.briarproject:obfs4proxy:0.0.12-dev-40245c4a@zip' tor 'org.briarproject:obfs4proxy:0.0.12-dev-40245c4a@zip'
annotationProcessor 'com.google.dagger:dagger-compiler:2.24' annotationProcessor 'com.google.dagger:dagger-compiler:2.24'
testImplementation project(path: ':bramble-api', configuration: 'testOutput') testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation project(path: ':bramble-core', configuration: 'testOutput') testImplementation project(path: ':bramble-core', configuration: 'testOutput')
testImplementation "junit:junit:$junit_version" testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:$jmock_version" testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:$jmock_version" testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.24' testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.24'
} }

View File

@@ -8,9 +8,9 @@ import org.briarproject.bramble.system.JavaSystemModule;
import dagger.Module; import dagger.Module;
@Module(includes = { @Module(includes = {
CircumventionModule.class,
JavaNetworkModule.class, JavaNetworkModule.class,
JavaSystemModule.class, JavaSystemModule.class,
CircumventionModule.class,
SocksModule.class SocksModule.class
}) })
public class BrambleJavaModule { public class BrambleJavaModule {

View File

@@ -25,7 +25,6 @@ import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.OsUtils.isLinux; import static org.briarproject.bramble.util.OsUtils.isLinux;
@@ -97,15 +96,8 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
String architecture = null; String architecture = null;
if (isLinux()) { if (isLinux()) {
String arch = System.getProperty("os.arch"); String arch = System.getProperty("os.arch");
if (LOG.isLoggable(INFO)) {
LOG.info("System's os.arch is " + arch);
}
if (arch.equals("amd64")) { if (arch.equals("amd64")) {
architecture = "linux-x86_64"; architecture = "linux-x86_64";
} else if (arch.equals("aarch64")) {
architecture = "linux-aarch64";
} else if (arch.equals("arm")) {
architecture = "linux-armhf";
} }
} }
if (architecture == null) { if (architecture == null) {
@@ -113,10 +105,6 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
return null; return null;
} }
if (LOG.isLoggable(INFO)) {
LOG.info("The selected architecture for Tor is " + architecture);
}
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();

View File

@@ -1,7 +1,6 @@
dependencyVerification { dependencyVerification {
verify = [ verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f', 'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f',
'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a', 'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a',
@@ -18,26 +17,24 @@ dependencyVerification {
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f', 'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a', 'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
'net.java.dev.jna:jna-platform:4.5.2:jna-platform-4.5.2.jar:f1d00c167d8921c6e23c626ef9f1c3ae0be473c95c68ffa012bc7ae55a87e2d6', 'net.java.dev.jna:jna-platform:4.5.2:jna-platform-4.5.2.jar:f1d00c167d8921c6e23c626ef9f1c3ae0be473c95c68ffa012bc7ae55a87e2d6',
'net.java.dev.jna:jna:4.5.2:jna-4.5.2.jar:0c8eb7acf67261656d79005191debaba3b6bf5dd60a43735a245429381dbecff', 'net.java.dev.jna:jna:4.5.2:jna-4.5.2.jar:0c8eb7acf67261656d79005191debaba3b6bf5dd60a43735a245429381dbecff',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd', 'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047', 'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.briarproject:obfs4proxy:0.0.12-dev-40245c4a:obfs4proxy-0.0.12-dev-40245c4a.zip:172029e7058b3a83ac93ac4991a44bf76e16ce8d46f558f5836d57da3cb3a766', 'org.briarproject:obfs4proxy:0.0.12-dev-40245c4a:obfs4proxy-0.0.12-dev-40245c4a.zip:172029e7058b3a83ac93ac4991a44bf76e16ce8d46f558f5836d57da3cb3a766',
'org.briarproject:tor:0.3.5.13-1:tor-0.3.5.13-1.zip:ef35c16bf8dc1f4c75ed71d9f55e4514f383d124ec96b859aca647c990927c99', 'org.briarproject:tor:0.3.5.13:tor-0.3.5.13.zip:1c5f0b821ee2aadb0ea04aa96caab3ca0a08370cce8de81c2dfe04d172f8a2a0',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d', 'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a', 'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53', 'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9', 'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21', 'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050', 'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09', 'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b', 'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd', 'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04', 'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be', 'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
] ]
} }

View File

@@ -19,16 +19,12 @@ android {
compileSdkVersion 30 compileSdkVersion 30
buildToolsVersion '30.0.2' buildToolsVersion '30.0.2'
packagingOptions {
doNotStrip '**/*.so'
}
defaultConfig { defaultConfig {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 29 targetSdkVersion 29
versionCode 10218 versionCode 10216
versionName "1.2.18" versionName "1.2.16"
applicationId "org.briarproject.briar.socialbackup" applicationId "org.briarproject.briar.android"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
buildConfigField "String", "GitHash", buildConfigField "String", "GitHash",
@@ -106,7 +102,6 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'com.google.android.material:material:1.2.1' implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.recyclerview:recyclerview-selection:1.1.0-rc03' implementation 'androidx.recyclerview:recyclerview-selection:1.1.0-rc03'
implementation 'org.magmacollective.darkcrystal:dark-crystal-secret-sharing-wrapper:1.1.0'
implementation 'info.guardianproject.panic:panic:1.0' implementation 'info.guardianproject.panic:panic:1.0'
implementation 'info.guardianproject.trustedintents:trustedintents:0.2' implementation 'info.guardianproject.trustedintents:trustedintents:0.2'
@@ -137,12 +132,11 @@ dependencies {
testImplementation "androidx.arch.core:core-testing:2.1.0" testImplementation "androidx.arch.core:core-testing:2.1.0"
testImplementation "androidx.test.espresso:espresso-core:$espressoVersion" testImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
testImplementation 'org.robolectric:robolectric:4.3.1' testImplementation 'org.robolectric:robolectric:4.3.1'
testImplementation 'org.mockito:mockito-core:3.1.0'
testImplementation 'org.mockito:mockito-core:3.9.0' testImplementation 'junit:junit:4.13.1'
testImplementation "junit:junit:$junit_version" testImplementation "org.jmock:jmock:$jmockVersion"
testImplementation "org.jmock:jmock:$jmock_version" testImplementation "org.jmock:jmock-junit4:$jmockVersion"
testImplementation "org.jmock:jmock-junit4:$jmock_version" testImplementation "org.jmock:jmock-legacy:$jmockVersion"
testImplementation "org.jmock:jmock-imposters:$jmock_version"
testAnnotationProcessor "com.google.dagger:dagger-compiler:2.24" testAnnotationProcessor "com.google.dagger:dagger-compiler:2.24"
androidTestImplementation project(path: ':bramble-api', configuration: 'testOutput') androidTestImplementation project(path: ':bramble-api', configuration: 'testOutput')

View File

@@ -40,5 +40,3 @@
# Dependency injection annotations, needed for UI tests on older API levels # Dependency injection annotations, needed for UI tests on older API levels
-keep class javax.inject.** -keep class javax.inject.**
-keep class com.sun.jna.** { *; }

View File

@@ -3,6 +3,7 @@ package org.briarproject.briar.android;
import org.briarproject.bramble.BrambleAndroidModule; import org.briarproject.bramble.BrambleAndroidModule;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.account.BriarAccountModule; import org.briarproject.bramble.account.BriarAccountModule;
import org.briarproject.bramble.system.ClockModule;
import org.briarproject.briar.BriarCoreModule; import org.briarproject.briar.BriarCoreModule;
import org.briarproject.briar.android.attachment.AttachmentModule; import org.briarproject.briar.android.attachment.AttachmentModule;
import org.briarproject.briar.android.attachment.media.MediaModule; import org.briarproject.briar.android.attachment.media.MediaModule;
@@ -16,6 +17,7 @@ import dagger.Component;
@Component(modules = { @Component(modules = {
AppModule.class, AppModule.class,
AttachmentModule.class, AttachmentModule.class,
ClockModule.class,
MediaModule.class, MediaModule.class,
BriarCoreModule.class, BriarCoreModule.class,
BrambleAndroidModule.class, BrambleAndroidModule.class,

Some files were not shown because too many files have changed in this diff Show More