├── .gitignore
├── AsynchronousRatchetingTree
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── facebook
│ └── research
│ └── asynchronousratchetingtree
│ ├── GroupMessagingSetupPhase.java
│ ├── GroupMessagingState.java
│ ├── GroupMessagingTestImplementation.java
│ ├── KeyServer.java
│ ├── Main.java
│ ├── MessageDistributer.java
│ ├── Stopwatch.java
│ ├── TestResult.java
│ ├── Utils.java
│ ├── art
│ ├── ART.java
│ ├── ARTSetupPhase.java
│ ├── ARTState.java
│ ├── ARTTestImplementation.java
│ ├── message
│ │ ├── ARTMessageDistributer.java
│ │ ├── AuthenticatedMessage.java
│ │ ├── CiphertextMessage.java
│ │ ├── SetupMessage.java
│ │ ├── UpdateMessage.java
│ │ └── thrift
│ │ │ ├── ART.thrift
│ │ │ ├── AuthenticatedMessageStruct.java
│ │ │ ├── CiphertextMessageStruct.java
│ │ │ ├── NodeStruct.java
│ │ │ ├── SetupMessageStruct.java
│ │ │ └── UpdateMessageStruct.java
│ └── tree
│ │ ├── LeafNode.java
│ │ ├── Node.java
│ │ ├── ParentNode.java
│ │ ├── PublicLeafNode.java
│ │ ├── PublicParentNode.java
│ │ ├── SecretLeafNode.java
│ │ ├── SecretNode.java
│ │ └── SecretParentNode.java
│ ├── crypto
│ ├── Crypto.java
│ ├── DHKeyPair.java
│ ├── DHPubKey.java
│ └── SignedDHPubKey.java
│ └── dhratchet
│ ├── DHRatchet.java
│ ├── DHRatchetSetupPhase.java
│ ├── DHRatchetState.java
│ └── message
│ ├── DHRatchetMessage.java
│ ├── DHRatchetMessageDistributer.java
│ ├── DHRatchetSetupMessage.java
│ └── thrift
│ ├── DHRatchet.thrift
│ ├── DHRatchetMessageStruct.java
│ └── DHRatchetSetupMessageStruct.java
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | AsynchronousRatchetingTree/target
2 | .idea
3 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.facebook.research
5 | asynchronousratchetingtree
6 | jar
7 | 1.0-SNAPSHOT
8 | Asynchronous Ratcheting Tree
9 | https://eprint.iacr.org/2017/666
10 |
11 |
12 | 1.8
13 | 1.8
14 | UTF-8
15 |
16 |
17 |
18 |
19 | org.apache.thrift
20 | libthrift
21 | 0.10.0
22 | jar
23 |
24 |
25 | org.slf4j
26 | slf4j-simple
27 | 1.7.12
28 |
29 |
30 | org.zeromq
31 | curve25519-java
32 | 0.1.0
33 |
34 |
35 |
36 |
37 |
38 |
39 | org.apache.maven.plugins
40 | maven-shade-plugin
41 | 3.0.0
42 |
43 |
44 | package
45 |
46 | shade
47 |
48 |
49 |
50 |
51 | uber-${project.artifactId}-${project.version}
52 |
53 |
54 | com.facebook.research.asynchronousratchetingtree.Main
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | Attribution-NonCommercial 4.0 International
65 | https://creativecommons.org/licenses/by-nc/4.0/
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/GroupMessagingSetupPhase.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
12 |
13 | public interface GroupMessagingSetupPhase {
14 | void generateNecessaryPreKeys(TState[] states);
15 | void setupInitiator(GroupMessagingTestImplementation implementation, TState[] states, DHPubKey[] identities, KeyServer keyServer);
16 | int getBytesSentByInitiator();
17 | void setupAllOthers(GroupMessagingTestImplementation implementation, TState[] states, Integer[] active, DHPubKey[] identities, KeyServer keyServer);
18 | int getBytesSentByOthers();
19 | int getBytesReceivedByOthers();
20 | }
21 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/GroupMessagingState.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.crypto.DHKeyPair;
12 | import com.facebook.research.asynchronousratchetingtree.crypto.SignedDHPubKey;
13 |
14 | import java.util.HashMap;
15 | import java.util.Map;
16 |
17 | abstract public class GroupMessagingState {
18 | private int peerNum;
19 | private int peerCount;
20 | private DHKeyPair identityKeyPair;
21 | private Map preKeys = new HashMap<>();
22 | private Map signedPreKeys = new HashMap<>();
23 |
24 | public GroupMessagingState(int peerNum, int peerCount) {
25 | this.peerNum = peerNum;
26 | this.peerCount = peerCount;
27 | identityKeyPair = DHKeyPair.generate(true);
28 | }
29 |
30 | final public int getPeerNum() {
31 | return peerNum;
32 | }
33 |
34 | final public int getPeerCount() {
35 | return peerCount;
36 | }
37 |
38 | final public DHKeyPair getIdentityKeyPair() {
39 | return identityKeyPair;
40 | }
41 |
42 | final public DHKeyPair getPreKeyFor(int peerNum) {
43 | if (!preKeys.containsKey(peerNum)) {
44 | preKeys.put(peerNum, DHKeyPair.generate(false));
45 | }
46 | return preKeys.get(peerNum);
47 | }
48 |
49 | final public SignedDHPubKey getSignedDHPreKeyFor(int peerNum) {
50 | if (!signedPreKeys.containsKey(peerNum)) {
51 | byte[] pkBytes = getPreKeyFor(peerNum).getPubKeyBytes();
52 | byte[] signature = getIdentityKeyPair().sign(pkBytes);
53 | signedPreKeys.put(peerNum, new SignedDHPubKey(pkBytes, signature));
54 | }
55 | return signedPreKeys.get(peerNum);
56 | }
57 |
58 | abstract public byte[] getKeyWithPeer(int n);
59 | }
60 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/GroupMessagingTestImplementation.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
12 |
13 | public interface GroupMessagingTestImplementation {
14 | byte[] setupMessageForPeer(TThreadState state, DHPubKey[] peers, KeyServer keyServer, int peer);
15 | void processSetupMessage(TThreadState state, byte[] serialisedMessage, int participantNum);
16 | MessageDistributer sendMessage(TThreadState state, byte[] plaintext);
17 | byte[] receiveMessage(TThreadState state, byte[] serialisedMessage);
18 | }
19 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/KeyServer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.crypto.SignedDHPubKey;
12 |
13 | final public class KeyServer {
14 | GroupMessagingState[] states;
15 |
16 | public KeyServer(GroupMessagingState[] states) {
17 | this.states = states;
18 | }
19 |
20 | public SignedDHPubKey getSignedPreKey(GroupMessagingState state, int peerNum) {
21 | return states[peerNum].getSignedDHPreKeyFor(state.getPeerNum());
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/Main.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.art.ARTTestImplementation;
12 | import com.facebook.research.asynchronousratchetingtree.art.ARTSetupPhase;
13 | import com.facebook.research.asynchronousratchetingtree.art.ARTState;
14 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
15 | import com.facebook.research.asynchronousratchetingtree.dhratchet.DHRatchet;
16 | import com.facebook.research.asynchronousratchetingtree.dhratchet.DHRatchetSetupPhase;
17 | import com.facebook.research.asynchronousratchetingtree.dhratchet.DHRatchetState;
18 |
19 | import java.security.NoSuchAlgorithmException;
20 | import java.security.SecureRandom;
21 | import java.util.*;
22 | import javax.crypto.Cipher;
23 |
24 | public class Main {
25 | private static boolean debug = true;
26 |
27 | public static void main(String[] args) {
28 | checkForUnlimitedStrengthCrypto();
29 |
30 | // Run a test run first to warm up the JIT
31 | artTestRun(8, 8);
32 | dhTestRun(8, 8);
33 |
34 | List artResults = new LinkedList<>();
35 | List dhResults = new LinkedList<>();
36 |
37 | int test_size_limit = 1000;
38 | double multiplier = 1.5;
39 |
40 | // First run ART tests. Warm up the JIT with a few smallish values, and then start recording results.
41 | for (int i = 2; i < 20; i += 2) {
42 | artTestRun(i, i);
43 | }
44 | int lastNumber = 1;
45 | for (double i = 2.0; i <= test_size_limit; i *= multiplier) {
46 | int n = (int) i;
47 | if (n == lastNumber) {
48 | continue;
49 | }
50 | lastNumber = n;
51 | System.gc();
52 | artResults.add(artTestRun(n, n));
53 | }
54 |
55 | // Now run DH tests. Again, warm up the JIT with a few smallish values, and then start recording results.
56 | for (int i = 2; i < 20; i += 2) {
57 | dhTestRun(i, i);
58 | }
59 | lastNumber = 1;
60 | for (double i = 2.0; i <= test_size_limit; i *= multiplier) {
61 | int n = (int) i;
62 | if (n == lastNumber) {
63 | continue;
64 | }
65 | System.gc();
66 | dhResults.add(dhTestRun(n, n));
67 | }
68 |
69 | TestResult.outputHeaderLine();
70 | Iterator artIterator = artResults.iterator();
71 | while (artIterator.hasNext()) {
72 | TestResult r = artIterator.next();
73 | r.output();
74 | }
75 |
76 | Iterator dhIterator = dhResults.iterator();
77 | while (dhIterator.hasNext()) {
78 | TestResult r = dhIterator.next();
79 | r.output();
80 | }
81 | }
82 |
83 | private static TestResult artTestRun(int n, int activePeers) {
84 | ARTState[] states = new ARTState[n];
85 |
86 | for (int i = 0; i < n; i++) {
87 | states[i] = new ARTState(i, n);
88 | }
89 |
90 | return testRun(
91 | n,
92 | activePeers,
93 | states,
94 | new ARTSetupPhase(),
95 | new ARTTestImplementation()
96 | );
97 | }
98 |
99 | private static void checkForUnlimitedStrengthCrypto() {
100 | boolean hasEnoughCrypto = true;
101 | try {
102 | if (Cipher.getMaxAllowedKeyLength("AES") < 256) {
103 | hasEnoughCrypto = false;
104 | }
105 | } catch (NoSuchAlgorithmException e) {
106 | hasEnoughCrypto = false;
107 | }
108 | if (!hasEnoughCrypto) {
109 | Utils.except("Your JRE does not support unlimited-strength " +
110 | "cryptography and thus cannot run ART. See README.md " +
111 | "for Java Cryptography Extension (JCE) Unlimited " +
112 | "Strength Jurisdiction Policy Files installation " +
113 | "instructions.");
114 | }
115 | }
116 |
117 | private static TestResult dhTestRun(int n, int activePeers) {
118 | DHRatchetState[] states = new DHRatchetState[n];
119 |
120 | for (int i = 0; i < n; i++) {
121 | states[i] = new DHRatchetState(i, n);
122 | }
123 |
124 | return testRun(
125 | n,
126 | activePeers,
127 | states,
128 | new DHRatchetSetupPhase(),
129 | new DHRatchet()
130 | );
131 | }
132 |
133 | private static TestResult testRun(
134 | int n,
135 | int activeCount,
136 | TState[] states,
137 | GroupMessagingSetupPhase setupPhase,
138 | GroupMessagingTestImplementation implementation
139 | ) {
140 | String testName = implementation.getClass().getSimpleName();
141 | if (debug) Utils.print("\nStarting " + testName + " test run with " + n + " participants, of which " + activeCount + " active.\n");
142 | TestResult result = new TestResult(testName, n, activeCount);
143 |
144 | if (debug) Utils.print("Creating random messages and senders.");
145 | SecureRandom random = new SecureRandom();
146 | Set activeSet = new HashSet<>();
147 | activeSet.add(0); // We always want the initiator in the set.
148 | while (activeSet.size() < activeCount) {
149 | activeSet.add(random.nextInt(n));
150 | }
151 | Integer[] active = activeSet.toArray(new Integer[0]);
152 |
153 | int messagesToSend = 100;
154 | int messageLength = 32; // Message length 32 bytes, so we can compare as if we were just sending a symmetric key.
155 | int[] messageSenders = new int[messagesToSend];
156 | byte[][] messages = new byte[messagesToSend][messageLength];
157 | for (int i = 0; i < messagesToSend; i++) {
158 | // We're only interested in ratcheting events, so senders should always be
159 | // different from the previous sender.
160 | messageSenders[i] = active[random.nextInt(activeCount)];
161 | while (i != 0 && messageSenders[i] == messageSenders[i-1]) {
162 | messageSenders[i] = active[random.nextInt(activeCount)];
163 | }
164 | random.nextBytes(messages[i]);
165 | }
166 |
167 |
168 | // Create the necessary setup tooling in advance.
169 | DHPubKey[] identities = new DHPubKey[n];
170 | for (int i = 0; i < n ; i++) {
171 | identities[i] = states[i].getIdentityKeyPair().getPubKey();
172 | }
173 | KeyServer keyServer = new KeyServer(states);
174 |
175 | // Create and cache the necessary PreKeys in advance.
176 | setupPhase.generateNecessaryPreKeys(states);
177 |
178 | // We'll need two timers; as some interleaving events are counted.
179 | Stopwatch stopwatch1 = new Stopwatch();
180 | Stopwatch stopwatch2 = new Stopwatch();
181 |
182 | if (debug) Utils.print("Setting up session for initiator.");
183 | stopwatch1.startInterval();
184 | setupPhase.setupInitiator(implementation, states, identities, keyServer);
185 | stopwatch1.endInterval();
186 | if (debug) Utils.print("Took " + stopwatch1.getTotal() + " nanoseconds.");
187 | if (debug) Utils.print("Initiator sent " + setupPhase.getBytesSentByInitiator() + " bytes.");
188 | result.setInitiatorSetupTime(stopwatch1.getTotal());
189 | result.setInitiatorSetupBytes(setupPhase.getBytesSentByInitiator());
190 | stopwatch1.reset();
191 |
192 | if (debug) Utils.print("Setting up session for " + activeCount + " peers.");
193 | stopwatch1.startInterval();
194 | setupPhase.setupAllOthers(implementation, states, active, identities, keyServer);
195 | stopwatch1.endInterval();
196 | if (debug) Utils.print("Took " + stopwatch1.getTotal() + " nanoseconds.");
197 | if (debug) Utils.print("Others received " + setupPhase.getBytesReceivedByOthers() + " bytes.");
198 | if (debug) Utils.print("Others sent " + setupPhase.getBytesSentByOthers() + " bytes.");
199 | result.setOthersSetupTime(stopwatch1.getTotal());
200 | result.setOthersSetupBytesReceived(setupPhase.getBytesReceivedByOthers());
201 | result.setOthersSetupBytesSent(setupPhase.getBytesSentByOthers());
202 | stopwatch1.reset();
203 |
204 | // Use stopwatch1 for sender, stopwatch2 for receiving.
205 | if (debug) Utils.print("Sending " + messagesToSend + " messages.");
206 | int totalSendSizes = 0;
207 | int totalReceiveSizes = 0;
208 | for (int i = 0; i < messagesToSend; i++) {
209 | int sender = messageSenders[i];
210 | byte[] message = messages[i];
211 | stopwatch1.startInterval();
212 | MessageDistributer messageDistributer = implementation.sendMessage(states[sender], message);
213 | stopwatch1.endInterval();
214 |
215 | totalSendSizes += messageDistributer.totalSize();
216 |
217 | for (int j = 0; j < activeCount; j++) {
218 | int receiver = active[j];
219 | if (receiver == sender) {
220 | continue;
221 | }
222 | byte[] received = messageDistributer.getUpdateMessageForParticipantNum(receiver);
223 | totalReceiveSizes += received.length;
224 | stopwatch2.startInterval();
225 | byte[] decrypted = implementation.receiveMessage(states[receiver], received);
226 | stopwatch2.endInterval();
227 | if (!Arrays.equals(message, decrypted)) {
228 | Utils.except("Message doesn't match.");
229 | }
230 | }
231 | }
232 | if (debug) Utils.print("Total sending time " + stopwatch1.getTotal() + " nanoseconds.");
233 | if (debug) Utils.print("Total receiving time " + stopwatch2.getTotal() + " nanoseconds.");
234 | if (debug) Utils.print("Total bytes sent: " + totalSendSizes + ".");
235 | if (debug) Utils.print("Total bytes received: " + totalReceiveSizes + ".");
236 | result.setSendingTime(stopwatch1.getTotal());
237 | result.setReceivingTime(stopwatch2.getTotal());
238 | result.setBytesSent(totalSendSizes);
239 | result.setBytesReceived(totalReceiveSizes);
240 |
241 | if (debug) Utils.print("Ended test run with " + n + " participants.\n---------------\n");
242 |
243 | return result;
244 | }
245 | }
246 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/MessageDistributer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree;
10 |
11 | public interface MessageDistributer {
12 | public byte[] getUpdateMessageForParticipantNum(int participantNum);
13 | public int totalSize();
14 | }
15 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/Stopwatch.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree;
10 |
11 | public class Stopwatch {
12 | private long nanos;
13 | private long intervalStart;
14 |
15 | public Stopwatch() {
16 | reset();
17 | }
18 |
19 | public void startInterval() {
20 | intervalStart = System.nanoTime();
21 | }
22 |
23 | public void endInterval() {
24 | long intervalEnd = System.nanoTime();
25 | nanos += intervalEnd - intervalStart;
26 | }
27 |
28 | public long getTotal() {
29 | return nanos;
30 | }
31 |
32 | public void reset() {
33 | nanos = 0;
34 | intervalStart = -1;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/TestResult.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree;
10 |
11 | public class TestResult {
12 | private String type;
13 | private int groupSize;
14 | private int activeUsers;
15 | private long initiatorSetupTime;
16 | private int initiatorSetupBytes;
17 | private long othersSetupTime;
18 | private int othersSetupBytesSent;
19 | private int othersSetupBytesReceived;
20 | private long sendingTime;
21 | private long receivingTime;
22 | private int bytesSent;
23 | private int bytesReceived;
24 |
25 | public TestResult(String type, int groupSize, int activeUsers) {
26 | this.type = type;
27 | this.groupSize = groupSize;
28 | this.activeUsers = activeUsers;
29 | }
30 |
31 | public void setInitiatorSetupTime(long initiatorSetupTime) {
32 | this.initiatorSetupTime = initiatorSetupTime;
33 | }
34 |
35 | public void setInitiatorSetupBytes(int initiatorSetupBytes) {
36 | this.initiatorSetupBytes = initiatorSetupBytes;
37 | }
38 |
39 | public void setOthersSetupTime(long othersSetupTime) {
40 | this.othersSetupTime = othersSetupTime;
41 | }
42 |
43 | public void setOthersSetupBytesSent(int othersSetupBytesSent) {
44 | this.othersSetupBytesSent = othersSetupBytesSent;
45 | }
46 |
47 | public void setOthersSetupBytesReceived(int othersSetupBytesReceived) {
48 | this.othersSetupBytesReceived = othersSetupBytesReceived;
49 | }
50 |
51 | public void setSendingTime(long sendingTime) {
52 | this.sendingTime = sendingTime;
53 | }
54 |
55 | public void setReceivingTime(long receivingTime) {
56 | this.receivingTime = receivingTime;
57 | }
58 |
59 | public void setBytesSent(int bytesSent) {
60 | this.bytesSent = bytesSent;
61 | }
62 |
63 | public void setBytesReceived(int bytesReceived) {
64 | this.bytesReceived = bytesReceived;
65 | }
66 |
67 | public static void outputHeaderLine() {
68 | String[] columns = new String[] {
69 | "type",
70 | "participants",
71 | "active_participants",
72 | "init_setup_time",
73 | "init_setup_bytes",
74 | "others_setup_time",
75 | "others_setup_bytes_sent",
76 | "others_setup_bytes_received",
77 | "send_time",
78 | "receive_time",
79 | "bytes_sent",
80 | "bytes_received"
81 | };
82 | System.out.println(String.join(",", columns));
83 | }
84 |
85 | public void output() {
86 | String[] columns = new String[] {
87 | type,
88 | String.valueOf(groupSize),
89 | String.valueOf(activeUsers),
90 | String.valueOf(initiatorSetupTime),
91 | String.valueOf(initiatorSetupBytes),
92 | String.valueOf(othersSetupTime),
93 | String.valueOf(othersSetupBytesSent),
94 | String.valueOf(othersSetupBytesReceived),
95 | String.valueOf(sendingTime),
96 | String.valueOf(receivingTime),
97 | String.valueOf(bytesSent),
98 | String.valueOf(bytesReceived)
99 | };
100 | System.out.println(String.join(",", columns));
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/Utils.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.art.message.thrift.NodeStruct;
12 | import com.facebook.research.asynchronousratchetingtree.art.tree.Node;
13 | import org.apache.thrift.TBase;
14 | import org.apache.thrift.TDeserializer;
15 | import org.apache.thrift.TException;
16 | import org.apache.thrift.TSerializer;
17 | import org.apache.thrift.protocol.TCompactProtocol;
18 | import org.apache.thrift.protocol.TSimpleJSONProtocol;
19 |
20 | import javax.xml.bind.DatatypeConverter;
21 | import java.text.SimpleDateFormat;
22 | import java.util.Date;
23 |
24 | final public class Utils {
25 | public static void print(String a, Object... args) {
26 | SimpleDateFormat f = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss.SSS");
27 | System.out.printf("[" + f.format(new Date()) + "] " + a + "\n", args);
28 | }
29 |
30 | public static void printHex(byte[] a) {
31 | print(DatatypeConverter.printHexBinary(a));
32 | }
33 |
34 | public static void printTree(Node tree) {
35 | NodeStruct struct = Node.toThrift(tree);
36 | TSerializer serialiser = new TSerializer(new TSimpleJSONProtocol.Factory());
37 | try {
38 | Utils.print(new String(serialiser.serialize(hexifyNodeStruct(struct))));
39 | } catch (TException e) {
40 | Utils.except(e);
41 | }
42 | }
43 |
44 | public static NodeStruct hexifyNodeStruct(NodeStruct tree) {
45 | if (tree == null) {
46 | return null;
47 | }
48 | NodeStruct result = new NodeStruct();
49 | result.setPublicKey(DatatypeConverter.printHexBinary(tree.getPublicKey()).getBytes());
50 | result.setLeft(hexifyNodeStruct(tree.getLeft()));
51 | result.setRight(hexifyNodeStruct(tree.getRight()));
52 | return result;
53 | }
54 |
55 | /**
56 | * Throw a RuntimeException to simplify the example code by avoiding Java's explicit error handling.
57 | * Yet another reason that this could should absolutely never be used as-is.
58 | * The method throws, but also has the exception as its return type, so we can make the compiler happy by throwing
59 | * the output, or just call it raw.
60 | */
61 | public static RuntimeException except(Exception e) {
62 | print(e.getClass().getSimpleName());
63 | print(e.getMessage());
64 | e.printStackTrace();
65 | throw new RuntimeException();
66 | }
67 |
68 | public static RuntimeException except(String s) {
69 | print(s);
70 | throw new RuntimeException();
71 | }
72 |
73 | public static byte[] serialise(TBase thrift) {
74 | TSerializer serialiser = new TSerializer(new TCompactProtocol.Factory());
75 | try {
76 | return serialiser.serialize(thrift);
77 | } catch (TException e) {
78 | throw Utils.except(e);
79 | }
80 | }
81 |
82 | public static void deserialise(TObject object, byte[] data) {
83 | TDeserializer deserialiser = new TDeserializer(new TCompactProtocol.Factory());
84 | try {
85 | deserialiser.deserialize(object, data);
86 | } catch (TException e) {
87 | Utils.except(e);
88 | }
89 | }
90 |
91 | public static long startBenchmark() {
92 | return new Date().toInstant().toEpochMilli();
93 | }
94 |
95 | public static long getBenchmarkDelta(long start) {
96 | return new Date().toInstant().toEpochMilli() - start;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/ART.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.Utils;
12 | import com.facebook.research.asynchronousratchetingtree.art.message.AuthenticatedMessage;
13 | import com.facebook.research.asynchronousratchetingtree.art.message.SetupMessage;
14 | import com.facebook.research.asynchronousratchetingtree.art.message.UpdateMessage;
15 | import com.facebook.research.asynchronousratchetingtree.art.tree.*;
16 | import com.facebook.research.asynchronousratchetingtree.crypto.Crypto;
17 | import com.facebook.research.asynchronousratchetingtree.crypto.DHKeyPair;
18 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
19 |
20 | import java.util.*;
21 |
22 | public class ART {
23 | public static AuthenticatedMessage setupGroup(ARTState state, DHPubKey[] peers, Map preKeys) {
24 | int numPeers = peers.length;
25 |
26 | DHKeyPair selfLeaf = DHKeyPair.generate(false);
27 | DHKeyPair keyExchangeKeyPair = DHKeyPair.generate(false);
28 |
29 | DHKeyPair[] leaves = new DHKeyPair[numPeers];
30 | leaves[0] = selfLeaf;
31 |
32 | for (int i = 1; i < numPeers; i++) { // generate leaf keys for each agent
33 | leaves[i] = DHKeyPair.fromBytes(
34 | Crypto.keyExchangeInitiate(
35 | state.getIdentityKeyPair(),
36 | peers[i],
37 | keyExchangeKeyPair,
38 | preKeys.get(i)
39 | ),
40 | false
41 | );
42 | }
43 | SecretNode tree = createTree(leaves);
44 | state.setIdentities(peers);
45 | state.setTree(tree);
46 |
47 | SetupMessage sm = new SetupMessage(
48 | peers,
49 | preKeys,
50 | keyExchangeKeyPair.getPubKey(),
51 | tree
52 | );
53 | byte[] serialisedSetupMessage = sm.serialise();
54 | byte[] signature = state.getIdentityKeyPair().sign(serialisedSetupMessage);
55 | deriveStageKey(state);
56 |
57 | return new AuthenticatedMessage(serialisedSetupMessage, signature);
58 | }
59 |
60 | public static void processSetupMessage(ARTState state, AuthenticatedMessage signedMessage, int leafNum) {
61 | SetupMessage message = new SetupMessage(signedMessage.getMessage());
62 | boolean verified = message.getIdentities()[0].verify(signedMessage.getMessage(), signedMessage.getAuthenticator());
63 | if (!verified) {
64 | Utils.except("Signature verification failed on the setup message.");
65 | }
66 |
67 | if (!Arrays.equals(state.getPreKeyFor(0).getPubKey().getPubKeyBytes(), message.getEphemeralKeys().get(leafNum).getPubKeyBytes())) {
68 | Utils.except("Used the wrong ephemeral key.");
69 | }
70 | SecretLeafNode leaf = new SecretLeafNode(
71 | DHKeyPair.fromBytes(
72 | Crypto.keyExchangeReceive(state.getIdentityKeyPair(), message.getIdentities()[0], state.getPreKeyFor(0), message.getKeyExchangeKey()),
73 | false
74 | )
75 | );
76 | state.setTree(
77 | updateTreeWithSecretLeaf(
78 | message.getTree(),
79 | state.getPeerNum(),
80 | leaf
81 | )
82 | );
83 | state.setIdentities(
84 | message.getIdentities()
85 | );
86 | deriveStageKey(state);
87 | }
88 |
89 | public static AuthenticatedMessage updateKey(ARTState state) {
90 | SecretLeafNode newNode = new SecretLeafNode(DHKeyPair.generate(false));
91 | SecretNode newTree = updateTreeWithSecretLeaf(state.getTree(), state.getPeerNum(), newNode);
92 | state.setTree(newTree);
93 | UpdateMessage m = new UpdateMessage(
94 | state.getPeerNum(),
95 | pathNodeKeys(state.getTree(), state.getPeerNum())
96 | );
97 | byte[] serialisedUpdateMessage = m.serialise();
98 | byte[] mac = Crypto.hmacSha256(serialisedUpdateMessage, state.getStageKey());
99 | deriveStageKey(state);
100 | return new AuthenticatedMessage(serialisedUpdateMessage, mac);
101 | }
102 |
103 | public static void processUpdateMessage(ARTState state, AuthenticatedMessage message) {
104 | byte[] mac = Crypto.hmacSha256(message.getMessage(), state.getStageKey());
105 | if (!Arrays.equals(mac, message.getAuthenticator())) {
106 | Utils.except("MAC is incorrect for update message.");
107 | }
108 | UpdateMessage updateMessage = new UpdateMessage(message.getMessage());
109 | Node tree = state.getTree();
110 | tree = updateTreeWithPublicPath(tree, updateMessage.getLeafNum(), updateMessage.getPath(), 0);
111 | state.setTree((SecretNode) tree);
112 | deriveStageKey(state);
113 | }
114 |
115 | private static SecretNode createTree(DHKeyPair[] leaves) {
116 | int n = leaves.length;
117 | if (n == 0) {
118 | Utils.except("No leaves");
119 | }
120 | if (n == 1) {
121 | return new SecretLeafNode(leaves[0]);
122 | }
123 | int l = leftTreeSize(n);
124 | SecretNode left = createTree(Arrays.copyOfRange(leaves, 0, l));
125 | Node right = createTree(Arrays.copyOfRange(leaves, l, n));
126 | return new SecretParentNode(left, right);
127 | }
128 |
129 | private static void deriveStageKey(ARTState state) {
130 | state.setStageKey(
131 | Crypto.artKDF(
132 | state.getStageKey(),
133 | ((SecretParentNode)state.getTree()).getRawSecretKey(),
134 | state.getIdentities(),
135 | state.getTree()
136 | )
137 | );
138 | }
139 |
140 | private static SecretNode updateTreeWithSecretLeaf(Node tree, int i, SecretLeafNode newLeaf) {
141 | int l = leftTreeSize(tree.numLeaves());
142 | if (tree.numLeaves() == 1) {
143 | return newLeaf;
144 | }
145 | SecretParentNode result;
146 | ParentNode treeParent = (ParentNode)tree;
147 |
148 | if (i < l) {
149 | result = new SecretParentNode(
150 | updateTreeWithSecretLeaf(treeParent.getLeft(), i, newLeaf),
151 | treeParent.getRight()
152 | );
153 | } else {
154 | result = new SecretParentNode(
155 | treeParent.getLeft(),
156 | updateTreeWithSecretLeaf(treeParent.getRight(), i - l, newLeaf)
157 | );
158 | }
159 | return result;
160 | }
161 |
162 | private static Node updateTreeWithPublicPath(Node tree, int i, DHPubKey[] newPath, int pathIndex) {
163 | int l = leftTreeSize(tree.numLeaves());
164 | if (newPath.length - 1 == pathIndex) {
165 | return new PublicLeafNode(newPath[pathIndex]);
166 | }
167 |
168 | ParentNode result;
169 | ParentNode treeAsParent = (ParentNode) tree;
170 | Node newLeft;
171 | Node newRight;
172 |
173 | if (i < l) {
174 | newLeft = updateTreeWithPublicPath(treeAsParent.getLeft(), i, newPath, pathIndex + 1);
175 | newRight = treeAsParent.getRight();
176 | } else {
177 | newLeft = treeAsParent.getLeft();
178 | newRight = updateTreeWithPublicPath(treeAsParent.getRight(), i - l, newPath, pathIndex + 1);
179 | }
180 |
181 | if (newLeft instanceof SecretNode) {
182 | result = new SecretParentNode((SecretNode)newLeft, newRight);
183 | } else if (newRight instanceof SecretNode) {
184 | result = new SecretParentNode(newLeft, (SecretNode)newRight);
185 | } else {
186 | result = new PublicParentNode(
187 | newPath[pathIndex],
188 | newLeft,
189 | newRight
190 | );
191 | }
192 |
193 | if (!Arrays.equals(result.getPubKey().getPubKeyBytes(), newPath[pathIndex].getPubKeyBytes())) {
194 | Utils.printTree(result);
195 | Utils.except("Update operation inconsistent with provided path.");
196 | }
197 |
198 | return result;
199 | }
200 |
201 | protected static DHPubKey[] pathNodeKeys(Node tree, int i) {
202 | List keys = new ArrayList();
203 |
204 | while (tree.numLeaves() > 1) {
205 | int l = leftTreeSize(tree.numLeaves());
206 | ParentNode parentNode = (ParentNode) tree;
207 | keys.add(tree.getPubKey());
208 | if (i < l) {
209 | tree = parentNode.getLeft();
210 | } else {
211 | tree = parentNode.getRight();
212 | i -= l;
213 | }
214 | }
215 | keys.add(tree.getPubKey());
216 | return keys.toArray(new DHPubKey[] {});
217 | }
218 |
219 | private static int leftTreeSize(int numLeaves) {
220 | return (int)Math.pow(2, Math.ceil(Math.log(numLeaves) / Math.log(2)) - 1);
221 | }
222 | }
223 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/ARTSetupPhase.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.GroupMessagingSetupPhase;
12 | import com.facebook.research.asynchronousratchetingtree.GroupMessagingTestImplementation;
13 | import com.facebook.research.asynchronousratchetingtree.KeyServer;
14 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
15 |
16 | public class ARTSetupPhase implements GroupMessagingSetupPhase {
17 | private byte[] setupMessage;
18 | private int bytesReceivedByOthers = 0;
19 |
20 | @Override
21 | public void generateNecessaryPreKeys(ARTState[] states) {
22 | // We only need PreKeys for the initiator.
23 | for (int i = 1; i < states.length; i++) {
24 | states[i].getSignedDHPreKeyFor(0);
25 | }
26 | }
27 |
28 | @Override
29 | public void setupInitiator(GroupMessagingTestImplementation implementation, ARTState[] states, DHPubKey[] identities, KeyServer keyServer) {
30 | int n = states.length;
31 |
32 | // Setup message is the same for all peers, so let's just do it once.
33 | setupMessage = implementation.setupMessageForPeer(
34 | states[0],
35 | identities,
36 | keyServer,
37 | 1
38 | );
39 | }
40 |
41 | @Override
42 | public int getBytesSentByInitiator() {
43 | return setupMessage.length;
44 | }
45 |
46 | @Override
47 | public void setupAllOthers(GroupMessagingTestImplementation implementation, ARTState[] states, Integer[] active, DHPubKey[] identities, KeyServer keyServer) {
48 | for (int i = 0; i < active.length; i++) {
49 | int which = active[i];
50 | if (which == 0) { // Don't import the setup message to the initiator itself.
51 | continue;
52 | }
53 | bytesReceivedByOthers += setupMessage.length;
54 | implementation.processSetupMessage(states[which], setupMessage, which);
55 | }
56 | }
57 |
58 | @Override
59 | public int getBytesSentByOthers() {
60 | return 0;
61 | }
62 |
63 | @Override
64 | public int getBytesReceivedByOthers() {
65 | return bytesReceivedByOthers;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/ARTState.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.GroupMessagingState;
12 | import com.facebook.research.asynchronousratchetingtree.Utils;
13 | import com.facebook.research.asynchronousratchetingtree.art.tree.SecretParentNode;
14 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
15 | import com.facebook.research.asynchronousratchetingtree.art.tree.SecretNode;
16 |
17 | public class ARTState extends GroupMessagingState {
18 | private SecretParentNode tree;
19 | private DHPubKey[] identities;
20 | private byte[] stageKey = new byte[0];
21 | private byte[] setupMessage;
22 |
23 | public ARTState(int peerNum, int peerCount) {
24 | super(peerNum, peerCount);
25 | }
26 |
27 | public SecretNode getTree() {
28 | return tree;
29 | }
30 |
31 | public void setSetupMessage(byte[] setupMessage) {
32 | this.setupMessage = setupMessage;
33 | }
34 |
35 | public byte[] getSetupMessage() {
36 | return setupMessage;
37 | }
38 |
39 | public byte[] getKeyWithPeer(int n) {
40 | return getStageKey();
41 | }
42 |
43 | public DHPubKey[] getIdentities() {
44 | return identities;
45 | }
46 |
47 | public void setIdentities(DHPubKey[] identities) {
48 | this.identities = identities;
49 | }
50 |
51 | public byte[] getStageKey() {
52 | return stageKey;
53 | }
54 |
55 | public void setStageKey(byte[] stageKey) {
56 | this.stageKey = stageKey;
57 | }
58 |
59 | public void setTree(SecretNode tree) {
60 | if (!(tree instanceof SecretParentNode)) {
61 | Utils.except("Tree cannot be a leaf.");
62 | }
63 | this.tree = (SecretParentNode) tree;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/ARTTestImplementation.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.KeyServer;
12 | import com.facebook.research.asynchronousratchetingtree.Utils;
13 | import com.facebook.research.asynchronousratchetingtree.art.message.*;
14 | import com.facebook.research.asynchronousratchetingtree.GroupMessagingTestImplementation;
15 | import com.facebook.research.asynchronousratchetingtree.MessageDistributer;
16 | import com.facebook.research.asynchronousratchetingtree.art.message.CiphertextMessage;
17 | import com.facebook.research.asynchronousratchetingtree.crypto.Crypto;
18 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
19 | import com.facebook.research.asynchronousratchetingtree.crypto.SignedDHPubKey;
20 | import com.facebook.research.asynchronousratchetingtree.art.message.ARTMessageDistributer;
21 | import com.facebook.research.asynchronousratchetingtree.art.message.AuthenticatedMessage;
22 |
23 | import java.util.*;
24 |
25 | final public class ARTTestImplementation implements GroupMessagingTestImplementation {
26 | public byte[] setupMessageForPeer(ARTState state, DHPubKey[] peers, KeyServer keyServer, int peer) {
27 | byte[] setupMessageSerialised = state.getSetupMessage();
28 | if (setupMessageSerialised == null) {
29 | Map preKeys = new HashMap<>();
30 | for (int i = 1; i < peers.length; i++) {
31 | SignedDHPubKey signedPreKey = keyServer.getSignedPreKey(state, i);
32 | if (!peers[i].verify(signedPreKey.getPubKeyBytes(), signedPreKey.getSignature())) {
33 | Utils.except("PreKey signature check failed.");
34 | }
35 | preKeys.put(i, signedPreKey);
36 | }
37 | AuthenticatedMessage setupMessage = ART.setupGroup(state, peers, preKeys);
38 | setupMessageSerialised = setupMessage.serialise();
39 | state.setSetupMessage(setupMessageSerialised);
40 | }
41 | return setupMessageSerialised;
42 | }
43 |
44 | public void processSetupMessage(ARTState state, byte[] serialisedMessage, int leafNum) {
45 | AuthenticatedMessage message = new AuthenticatedMessage(serialisedMessage);
46 | ART.processSetupMessage(state, message, leafNum);
47 | }
48 |
49 | public MessageDistributer sendMessage(ARTState state, byte[] plaintext) {
50 | AuthenticatedMessage updateMessage = ART.updateKey(state);
51 |
52 | // All peers have the same key, so the "withPeer(0)" aspect of this is a no-op.
53 | byte[] key = state.getKeyWithPeer(0);
54 | byte[] ciphertext = Crypto.encrypt(plaintext, key);
55 |
56 | CiphertextMessage message = new CiphertextMessage(updateMessage, ciphertext);
57 | return new ARTMessageDistributer(message);
58 | }
59 |
60 | public byte[] receiveMessage(ARTState state, byte[] serialisedMessage) {
61 | CiphertextMessage message = new CiphertextMessage(serialisedMessage);
62 | ART.processUpdateMessage(state, message.getAuthenticatedMessage());
63 |
64 | // All peers have the same key, so the "withPeer(0)" aspect of this is a no-op.
65 | byte[] key = state.getKeyWithPeer(0);
66 | return Crypto.decrypt(message.getCiphertext(), key);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/message/ARTMessageDistributer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art.message;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.MessageDistributer;
12 |
13 | public class ARTMessageDistributer implements MessageDistributer {
14 | private byte[] serialised;
15 |
16 | public ARTMessageDistributer(CiphertextMessage updateMessage) {
17 | serialised = updateMessage.serialise();
18 | }
19 |
20 | @Override
21 | public byte[] getUpdateMessageForParticipantNum(int participantNum) {
22 | return serialised;
23 | }
24 |
25 | @Override
26 | public int totalSize() {
27 | return serialised.length;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/message/AuthenticatedMessage.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art.message;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.Utils;
12 | import com.facebook.research.asynchronousratchetingtree.art.message.thrift.AuthenticatedMessageStruct;
13 |
14 | public class AuthenticatedMessage {
15 | private byte[] message;
16 | private byte[] authenticator;
17 |
18 | public AuthenticatedMessage(
19 | byte[] message,
20 | byte[] authenticator
21 | ) {
22 | this.message = message;
23 | this.authenticator = authenticator;
24 | }
25 |
26 | public AuthenticatedMessage(byte[] thriftSerialised) {
27 | AuthenticatedMessageStruct struct = new AuthenticatedMessageStruct();
28 | Utils.deserialise(struct, thriftSerialised);
29 |
30 | message = struct.getMessage();
31 | authenticator = struct.getAuthenticator();
32 | }
33 |
34 | public AuthenticatedMessage(AuthenticatedMessageStruct struct) {
35 | message = struct.getMessage();
36 | authenticator = struct.getAuthenticator();
37 | }
38 |
39 | public byte[] getMessage() {
40 | return message;
41 | }
42 |
43 | public byte[] getAuthenticator() {
44 | return authenticator;
45 | }
46 |
47 | public AuthenticatedMessageStruct getThriftStruct() {
48 | AuthenticatedMessageStruct struct = new AuthenticatedMessageStruct();
49 | struct.setMessage(message);
50 | struct.setAuthenticator(authenticator);
51 | return struct;
52 | }
53 |
54 | public byte[] serialise() {
55 | return Utils.serialise(getThriftStruct());
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/message/CiphertextMessage.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art.message;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.Utils;
12 | import com.facebook.research.asynchronousratchetingtree.art.message.thrift.CiphertextMessageStruct;
13 |
14 | public class CiphertextMessage {
15 | private AuthenticatedMessage authenticatedMessage;
16 | private byte[] ciphertext;
17 |
18 | public CiphertextMessage(AuthenticatedMessage authenticatedMessage, byte[] ciphertext) {
19 | this.authenticatedMessage = authenticatedMessage;
20 | this.ciphertext = ciphertext;
21 | }
22 |
23 | public CiphertextMessage(byte[] thriftSerialised) {
24 | CiphertextMessageStruct struct = new CiphertextMessageStruct();
25 | Utils.deserialise(struct, thriftSerialised);
26 | authenticatedMessage = new AuthenticatedMessage(struct.getAuthenticatedMessage());
27 | ciphertext = struct.getCiphertext();
28 | }
29 |
30 | public AuthenticatedMessage getAuthenticatedMessage() {
31 | return authenticatedMessage;
32 | }
33 |
34 | public byte[] getCiphertext() {
35 | return ciphertext;
36 | }
37 |
38 | public byte[] serialise() {
39 | CiphertextMessageStruct struct = new CiphertextMessageStruct();
40 | struct.setAuthenticatedMessage(authenticatedMessage.getThriftStruct());
41 | struct.setCiphertext(ciphertext);
42 | return Utils.serialise(struct);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/message/SetupMessage.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art.message;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.art.message.thrift.SetupMessageStruct;
12 | import com.facebook.research.asynchronousratchetingtree.art.tree.Node;
13 | import com.facebook.research.asynchronousratchetingtree.Utils;
14 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
15 |
16 | import java.util.*;
17 |
18 | public class SetupMessage {
19 | private DHPubKey[] identities;
20 | private Map ephemeralKeys;
21 | private DHPubKey keyExchangeKey;
22 | private Node tree;
23 |
24 | public SetupMessage(DHPubKey[] identities, Map ephemeralKeys, DHPubKey keyExchangeKey, Node tree) {
25 | this.identities = identities;
26 | this.ephemeralKeys = ephemeralKeys;
27 | this.keyExchangeKey = keyExchangeKey;
28 | this.tree = tree;
29 | }
30 |
31 | public SetupMessage(byte[] thriftSerialised) {
32 | SetupMessageStruct struct = new SetupMessageStruct();
33 | Utils.deserialise(struct, thriftSerialised);
34 |
35 | identities = new DHPubKey[struct.getIdentitiesSize()];
36 | for (int i = 0; i < identities.length; i++) {
37 | identities[i] = DHPubKey.pubKey(
38 | Base64.getDecoder().decode(struct.getIdentities().get(i))
39 | );
40 | }
41 |
42 | ephemeralKeys = new HashMap<>();
43 | for (int i = 1; i < identities.length; i++) {
44 | ephemeralKeys.put(
45 | i,
46 | DHPubKey.pubKey(
47 | Base64.getDecoder().decode(struct.getEphemeralKeys().get(i))
48 | )
49 | );
50 | }
51 |
52 | keyExchangeKey = DHPubKey.pubKey(struct.getKeyExchangeKey());
53 | tree = Node.fromThrift(struct.getTree());
54 | }
55 |
56 | public DHPubKey[] getIdentities() {
57 | return identities;
58 | }
59 |
60 | public Map getEphemeralKeys() {
61 | return ephemeralKeys;
62 | }
63 |
64 | public DHPubKey getKeyExchangeKey() {
65 | return keyExchangeKey;
66 | }
67 |
68 | public Node getTree() {
69 | return tree;
70 | }
71 |
72 | public byte[] serialise() {
73 | List identities = new ArrayList<>();
74 | Map ephemeralKeys = new HashMap<>();
75 |
76 | for (int i = 0; i < this.identities.length; i++) {
77 | identities.add(Base64.getEncoder().encodeToString(this.identities[i].getPubKeyBytes()));
78 | }
79 |
80 | for (int i = 1; i < this.identities.length; i++) {
81 | ephemeralKeys.put(i, Base64.getEncoder().encodeToString(this.ephemeralKeys.get(i).getPubKeyBytes()));
82 | }
83 |
84 | SetupMessageStruct struct = new SetupMessageStruct();
85 | struct.setIdentities(identities);
86 | struct.setEphemeralKeys(ephemeralKeys);
87 | struct.setKeyExchangeKey(keyExchangeKey.getPubKeyBytes());
88 | struct.setTree(Node.toThrift(tree));
89 |
90 | return Utils.serialise(struct);
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/message/UpdateMessage.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art.message;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.Utils;
12 | import com.facebook.research.asynchronousratchetingtree.art.message.thrift.UpdateMessageStruct;
13 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
14 |
15 | import java.util.ArrayList;
16 | import java.util.Base64;
17 | import java.util.List;
18 |
19 | public class UpdateMessage {
20 | int leafNum;
21 | DHPubKey[] path;
22 |
23 | public UpdateMessage(int leafNum, DHPubKey[] path) {
24 | this.leafNum = leafNum;
25 | this.path = path;
26 | }
27 |
28 | public UpdateMessage(byte[] thriftSerialised) {
29 | UpdateMessageStruct struct = new UpdateMessageStruct();
30 | Utils.deserialise(struct, thriftSerialised);
31 |
32 | leafNum = struct.getLeafNum();
33 | path = new DHPubKey[struct.getPathSize()];
34 | for (int i = 0; i < path.length; i++) {
35 | path[i] = DHPubKey.pubKey(
36 | Base64.getDecoder().decode(struct.getPath().get(i))
37 | );
38 | }
39 | }
40 |
41 | public int getLeafNum() {
42 | return leafNum;
43 | }
44 |
45 | public DHPubKey[] getPath() {
46 | return path;
47 | }
48 |
49 | public byte[] serialise() {
50 | List path = new ArrayList<>();
51 | for (int i = 0; i < this.path.length; i++) {
52 | path.add(Base64.getEncoder().encodeToString(this.path[i].getPubKeyBytes()));
53 | }
54 | UpdateMessageStruct struct = new UpdateMessageStruct();
55 | struct.setLeafNum(leafNum);
56 | struct.setPath(path);
57 | return Utils.serialise(struct);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/message/thrift/ART.thrift:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017-present, Facebook, Inc.
2 | # All rights reserved.
3 | #
4 | # This source code is licensed under the license found in the
5 | # LICENSE file in the root directory of this source tree.
6 | #
7 | # Compile this file using the Thrift compiler, from the current directory, with the following command:
8 | # thrift -r --gen java -out ../../../../../../../ ART.thrift
9 |
10 | namespace java com.facebook.research.asynchronousratchetingtree.art.message.thrift
11 |
12 | struct SetupMessageStruct {
13 | 1: i32 leafNum,
14 | 2: list identities,
15 | 3: map ephemeralKeys,
16 | 4: binary keyExchangeKey,
17 | 5: NodeStruct tree,
18 | }
19 |
20 | struct NodeStruct {
21 | 1: binary publicKey,
22 | 2: optional NodeStruct left,
23 | 3: optional NodeStruct right,
24 | }
25 |
26 | struct UpdateMessageStruct {
27 | 1: i32 leafNum,
28 | 2: list path,
29 | }
30 |
31 | struct CiphertextMessageStruct {
32 | 1: AuthenticatedMessageStruct authenticatedMessage,
33 | 2: binary ciphertext,
34 | }
35 |
36 | struct AuthenticatedMessageStruct {
37 | 1: binary message,
38 | 2: binary authenticator,
39 | }
40 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/message/thrift/AuthenticatedMessageStruct.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Autogenerated by Thrift Compiler (0.10.0)
3 | *
4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5 | * @generated
6 | */
7 | package com.facebook.research.asynchronousratchetingtree.art.message.thrift;
8 |
9 | @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
10 | @javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)", date = "2018-01-05")
11 | public class AuthenticatedMessageStruct implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable {
12 | private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("AuthenticatedMessageStruct");
13 |
14 | private static final org.apache.thrift.protocol.TField MESSAGE_FIELD_DESC = new org.apache.thrift.protocol.TField("message", org.apache.thrift.protocol.TType.STRING, (short)1);
15 | private static final org.apache.thrift.protocol.TField AUTHENTICATOR_FIELD_DESC = new org.apache.thrift.protocol.TField("authenticator", org.apache.thrift.protocol.TType.STRING, (short)2);
16 |
17 | private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new AuthenticatedMessageStructStandardSchemeFactory();
18 | private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new AuthenticatedMessageStructTupleSchemeFactory();
19 |
20 | public java.nio.ByteBuffer message; // required
21 | public java.nio.ByteBuffer authenticator; // required
22 |
23 | /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
24 | public enum _Fields implements org.apache.thrift.TFieldIdEnum {
25 | MESSAGE((short)1, "message"),
26 | AUTHENTICATOR((short)2, "authenticator");
27 |
28 | private static final java.util.Map byName = new java.util.HashMap();
29 |
30 | static {
31 | for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
32 | byName.put(field.getFieldName(), field);
33 | }
34 | }
35 |
36 | /**
37 | * Find the _Fields constant that matches fieldId, or null if its not found.
38 | */
39 | public static _Fields findByThriftId(int fieldId) {
40 | switch(fieldId) {
41 | case 1: // MESSAGE
42 | return MESSAGE;
43 | case 2: // AUTHENTICATOR
44 | return AUTHENTICATOR;
45 | default:
46 | return null;
47 | }
48 | }
49 |
50 | /**
51 | * Find the _Fields constant that matches fieldId, throwing an exception
52 | * if it is not found.
53 | */
54 | public static _Fields findByThriftIdOrThrow(int fieldId) {
55 | _Fields fields = findByThriftId(fieldId);
56 | if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!");
57 | return fields;
58 | }
59 |
60 | /**
61 | * Find the _Fields constant that matches name, or null if its not found.
62 | */
63 | public static _Fields findByName(java.lang.String name) {
64 | return byName.get(name);
65 | }
66 |
67 | private final short _thriftId;
68 | private final java.lang.String _fieldName;
69 |
70 | _Fields(short thriftId, java.lang.String fieldName) {
71 | _thriftId = thriftId;
72 | _fieldName = fieldName;
73 | }
74 |
75 | public short getThriftFieldId() {
76 | return _thriftId;
77 | }
78 |
79 | public java.lang.String getFieldName() {
80 | return _fieldName;
81 | }
82 | }
83 |
84 | // isset id assignments
85 | public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
86 | static {
87 | java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
88 | tmpMap.put(_Fields.MESSAGE, new org.apache.thrift.meta_data.FieldMetaData("message", org.apache.thrift.TFieldRequirementType.DEFAULT,
89 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING , true)));
90 | tmpMap.put(_Fields.AUTHENTICATOR, new org.apache.thrift.meta_data.FieldMetaData("authenticator", org.apache.thrift.TFieldRequirementType.DEFAULT,
91 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING , true)));
92 | metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
93 | org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(AuthenticatedMessageStruct.class, metaDataMap);
94 | }
95 |
96 | public AuthenticatedMessageStruct() {
97 | }
98 |
99 | public AuthenticatedMessageStruct(
100 | java.nio.ByteBuffer message,
101 | java.nio.ByteBuffer authenticator)
102 | {
103 | this();
104 | this.message = org.apache.thrift.TBaseHelper.copyBinary(message);
105 | this.authenticator = org.apache.thrift.TBaseHelper.copyBinary(authenticator);
106 | }
107 |
108 | /**
109 | * Performs a deep copy on other.
110 | */
111 | public AuthenticatedMessageStruct(AuthenticatedMessageStruct other) {
112 | if (other.isSetMessage()) {
113 | this.message = org.apache.thrift.TBaseHelper.copyBinary(other.message);
114 | }
115 | if (other.isSetAuthenticator()) {
116 | this.authenticator = org.apache.thrift.TBaseHelper.copyBinary(other.authenticator);
117 | }
118 | }
119 |
120 | public AuthenticatedMessageStruct deepCopy() {
121 | return new AuthenticatedMessageStruct(this);
122 | }
123 |
124 | @Override
125 | public void clear() {
126 | this.message = null;
127 | this.authenticator = null;
128 | }
129 |
130 | public byte[] getMessage() {
131 | setMessage(org.apache.thrift.TBaseHelper.rightSize(message));
132 | return message == null ? null : message.array();
133 | }
134 |
135 | public java.nio.ByteBuffer bufferForMessage() {
136 | return org.apache.thrift.TBaseHelper.copyBinary(message);
137 | }
138 |
139 | public AuthenticatedMessageStruct setMessage(byte[] message) {
140 | this.message = message == null ? (java.nio.ByteBuffer)null : java.nio.ByteBuffer.wrap(message.clone());
141 | return this;
142 | }
143 |
144 | public AuthenticatedMessageStruct setMessage(java.nio.ByteBuffer message) {
145 | this.message = org.apache.thrift.TBaseHelper.copyBinary(message);
146 | return this;
147 | }
148 |
149 | public void unsetMessage() {
150 | this.message = null;
151 | }
152 |
153 | /** Returns true if field message is set (has been assigned a value) and false otherwise */
154 | public boolean isSetMessage() {
155 | return this.message != null;
156 | }
157 |
158 | public void setMessageIsSet(boolean value) {
159 | if (!value) {
160 | this.message = null;
161 | }
162 | }
163 |
164 | public byte[] getAuthenticator() {
165 | setAuthenticator(org.apache.thrift.TBaseHelper.rightSize(authenticator));
166 | return authenticator == null ? null : authenticator.array();
167 | }
168 |
169 | public java.nio.ByteBuffer bufferForAuthenticator() {
170 | return org.apache.thrift.TBaseHelper.copyBinary(authenticator);
171 | }
172 |
173 | public AuthenticatedMessageStruct setAuthenticator(byte[] authenticator) {
174 | this.authenticator = authenticator == null ? (java.nio.ByteBuffer)null : java.nio.ByteBuffer.wrap(authenticator.clone());
175 | return this;
176 | }
177 |
178 | public AuthenticatedMessageStruct setAuthenticator(java.nio.ByteBuffer authenticator) {
179 | this.authenticator = org.apache.thrift.TBaseHelper.copyBinary(authenticator);
180 | return this;
181 | }
182 |
183 | public void unsetAuthenticator() {
184 | this.authenticator = null;
185 | }
186 |
187 | /** Returns true if field authenticator is set (has been assigned a value) and false otherwise */
188 | public boolean isSetAuthenticator() {
189 | return this.authenticator != null;
190 | }
191 |
192 | public void setAuthenticatorIsSet(boolean value) {
193 | if (!value) {
194 | this.authenticator = null;
195 | }
196 | }
197 |
198 | public void setFieldValue(_Fields field, java.lang.Object value) {
199 | switch (field) {
200 | case MESSAGE:
201 | if (value == null) {
202 | unsetMessage();
203 | } else {
204 | if (value instanceof byte[]) {
205 | setMessage((byte[])value);
206 | } else {
207 | setMessage((java.nio.ByteBuffer)value);
208 | }
209 | }
210 | break;
211 |
212 | case AUTHENTICATOR:
213 | if (value == null) {
214 | unsetAuthenticator();
215 | } else {
216 | if (value instanceof byte[]) {
217 | setAuthenticator((byte[])value);
218 | } else {
219 | setAuthenticator((java.nio.ByteBuffer)value);
220 | }
221 | }
222 | break;
223 |
224 | }
225 | }
226 |
227 | public java.lang.Object getFieldValue(_Fields field) {
228 | switch (field) {
229 | case MESSAGE:
230 | return getMessage();
231 |
232 | case AUTHENTICATOR:
233 | return getAuthenticator();
234 |
235 | }
236 | throw new java.lang.IllegalStateException();
237 | }
238 |
239 | /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
240 | public boolean isSet(_Fields field) {
241 | if (field == null) {
242 | throw new java.lang.IllegalArgumentException();
243 | }
244 |
245 | switch (field) {
246 | case MESSAGE:
247 | return isSetMessage();
248 | case AUTHENTICATOR:
249 | return isSetAuthenticator();
250 | }
251 | throw new java.lang.IllegalStateException();
252 | }
253 |
254 | @Override
255 | public boolean equals(java.lang.Object that) {
256 | if (that == null)
257 | return false;
258 | if (that instanceof AuthenticatedMessageStruct)
259 | return this.equals((AuthenticatedMessageStruct)that);
260 | return false;
261 | }
262 |
263 | public boolean equals(AuthenticatedMessageStruct that) {
264 | if (that == null)
265 | return false;
266 | if (this == that)
267 | return true;
268 |
269 | boolean this_present_message = true && this.isSetMessage();
270 | boolean that_present_message = true && that.isSetMessage();
271 | if (this_present_message || that_present_message) {
272 | if (!(this_present_message && that_present_message))
273 | return false;
274 | if (!this.message.equals(that.message))
275 | return false;
276 | }
277 |
278 | boolean this_present_authenticator = true && this.isSetAuthenticator();
279 | boolean that_present_authenticator = true && that.isSetAuthenticator();
280 | if (this_present_authenticator || that_present_authenticator) {
281 | if (!(this_present_authenticator && that_present_authenticator))
282 | return false;
283 | if (!this.authenticator.equals(that.authenticator))
284 | return false;
285 | }
286 |
287 | return true;
288 | }
289 |
290 | @Override
291 | public int hashCode() {
292 | int hashCode = 1;
293 |
294 | hashCode = hashCode * 8191 + ((isSetMessage()) ? 131071 : 524287);
295 | if (isSetMessage())
296 | hashCode = hashCode * 8191 + message.hashCode();
297 |
298 | hashCode = hashCode * 8191 + ((isSetAuthenticator()) ? 131071 : 524287);
299 | if (isSetAuthenticator())
300 | hashCode = hashCode * 8191 + authenticator.hashCode();
301 |
302 | return hashCode;
303 | }
304 |
305 | @Override
306 | public int compareTo(AuthenticatedMessageStruct other) {
307 | if (!getClass().equals(other.getClass())) {
308 | return getClass().getName().compareTo(other.getClass().getName());
309 | }
310 |
311 | int lastComparison = 0;
312 |
313 | lastComparison = java.lang.Boolean.valueOf(isSetMessage()).compareTo(other.isSetMessage());
314 | if (lastComparison != 0) {
315 | return lastComparison;
316 | }
317 | if (isSetMessage()) {
318 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.message, other.message);
319 | if (lastComparison != 0) {
320 | return lastComparison;
321 | }
322 | }
323 | lastComparison = java.lang.Boolean.valueOf(isSetAuthenticator()).compareTo(other.isSetAuthenticator());
324 | if (lastComparison != 0) {
325 | return lastComparison;
326 | }
327 | if (isSetAuthenticator()) {
328 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.authenticator, other.authenticator);
329 | if (lastComparison != 0) {
330 | return lastComparison;
331 | }
332 | }
333 | return 0;
334 | }
335 |
336 | public _Fields fieldForId(int fieldId) {
337 | return _Fields.findByThriftId(fieldId);
338 | }
339 |
340 | public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
341 | scheme(iprot).read(iprot, this);
342 | }
343 |
344 | public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
345 | scheme(oprot).write(oprot, this);
346 | }
347 |
348 | @Override
349 | public java.lang.String toString() {
350 | java.lang.StringBuilder sb = new java.lang.StringBuilder("AuthenticatedMessageStruct(");
351 | boolean first = true;
352 |
353 | sb.append("message:");
354 | if (this.message == null) {
355 | sb.append("null");
356 | } else {
357 | org.apache.thrift.TBaseHelper.toString(this.message, sb);
358 | }
359 | first = false;
360 | if (!first) sb.append(", ");
361 | sb.append("authenticator:");
362 | if (this.authenticator == null) {
363 | sb.append("null");
364 | } else {
365 | org.apache.thrift.TBaseHelper.toString(this.authenticator, sb);
366 | }
367 | first = false;
368 | sb.append(")");
369 | return sb.toString();
370 | }
371 |
372 | public void validate() throws org.apache.thrift.TException {
373 | // check for required fields
374 | // check for sub-struct validity
375 | }
376 |
377 | private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
378 | try {
379 | write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
380 | } catch (org.apache.thrift.TException te) {
381 | throw new java.io.IOException(te);
382 | }
383 | }
384 |
385 | private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException {
386 | try {
387 | read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
388 | } catch (org.apache.thrift.TException te) {
389 | throw new java.io.IOException(te);
390 | }
391 | }
392 |
393 | private static class AuthenticatedMessageStructStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
394 | public AuthenticatedMessageStructStandardScheme getScheme() {
395 | return new AuthenticatedMessageStructStandardScheme();
396 | }
397 | }
398 |
399 | private static class AuthenticatedMessageStructStandardScheme extends org.apache.thrift.scheme.StandardScheme {
400 |
401 | public void read(org.apache.thrift.protocol.TProtocol iprot, AuthenticatedMessageStruct struct) throws org.apache.thrift.TException {
402 | org.apache.thrift.protocol.TField schemeField;
403 | iprot.readStructBegin();
404 | while (true)
405 | {
406 | schemeField = iprot.readFieldBegin();
407 | if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
408 | break;
409 | }
410 | switch (schemeField.id) {
411 | case 1: // MESSAGE
412 | if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
413 | struct.message = iprot.readBinary();
414 | struct.setMessageIsSet(true);
415 | } else {
416 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
417 | }
418 | break;
419 | case 2: // AUTHENTICATOR
420 | if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
421 | struct.authenticator = iprot.readBinary();
422 | struct.setAuthenticatorIsSet(true);
423 | } else {
424 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
425 | }
426 | break;
427 | default:
428 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
429 | }
430 | iprot.readFieldEnd();
431 | }
432 | iprot.readStructEnd();
433 |
434 | // check for required fields of primitive type, which can't be checked in the validate method
435 | struct.validate();
436 | }
437 |
438 | public void write(org.apache.thrift.protocol.TProtocol oprot, AuthenticatedMessageStruct struct) throws org.apache.thrift.TException {
439 | struct.validate();
440 |
441 | oprot.writeStructBegin(STRUCT_DESC);
442 | if (struct.message != null) {
443 | oprot.writeFieldBegin(MESSAGE_FIELD_DESC);
444 | oprot.writeBinary(struct.message);
445 | oprot.writeFieldEnd();
446 | }
447 | if (struct.authenticator != null) {
448 | oprot.writeFieldBegin(AUTHENTICATOR_FIELD_DESC);
449 | oprot.writeBinary(struct.authenticator);
450 | oprot.writeFieldEnd();
451 | }
452 | oprot.writeFieldStop();
453 | oprot.writeStructEnd();
454 | }
455 |
456 | }
457 |
458 | private static class AuthenticatedMessageStructTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
459 | public AuthenticatedMessageStructTupleScheme getScheme() {
460 | return new AuthenticatedMessageStructTupleScheme();
461 | }
462 | }
463 |
464 | private static class AuthenticatedMessageStructTupleScheme extends org.apache.thrift.scheme.TupleScheme {
465 |
466 | @Override
467 | public void write(org.apache.thrift.protocol.TProtocol prot, AuthenticatedMessageStruct struct) throws org.apache.thrift.TException {
468 | org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
469 | java.util.BitSet optionals = new java.util.BitSet();
470 | if (struct.isSetMessage()) {
471 | optionals.set(0);
472 | }
473 | if (struct.isSetAuthenticator()) {
474 | optionals.set(1);
475 | }
476 | oprot.writeBitSet(optionals, 2);
477 | if (struct.isSetMessage()) {
478 | oprot.writeBinary(struct.message);
479 | }
480 | if (struct.isSetAuthenticator()) {
481 | oprot.writeBinary(struct.authenticator);
482 | }
483 | }
484 |
485 | @Override
486 | public void read(org.apache.thrift.protocol.TProtocol prot, AuthenticatedMessageStruct struct) throws org.apache.thrift.TException {
487 | org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
488 | java.util.BitSet incoming = iprot.readBitSet(2);
489 | if (incoming.get(0)) {
490 | struct.message = iprot.readBinary();
491 | struct.setMessageIsSet(true);
492 | }
493 | if (incoming.get(1)) {
494 | struct.authenticator = iprot.readBinary();
495 | struct.setAuthenticatorIsSet(true);
496 | }
497 | }
498 | }
499 |
500 | private static S scheme(org.apache.thrift.protocol.TProtocol proto) {
501 | return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme();
502 | }
503 | }
504 |
505 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/message/thrift/CiphertextMessageStruct.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Autogenerated by Thrift Compiler (0.10.0)
3 | *
4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5 | * @generated
6 | */
7 | package com.facebook.research.asynchronousratchetingtree.art.message.thrift;
8 |
9 | @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
10 | @javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)", date = "2018-01-05")
11 | public class CiphertextMessageStruct implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable {
12 | private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("CiphertextMessageStruct");
13 |
14 | private static final org.apache.thrift.protocol.TField AUTHENTICATED_MESSAGE_FIELD_DESC = new org.apache.thrift.protocol.TField("authenticatedMessage", org.apache.thrift.protocol.TType.STRUCT, (short)1);
15 | private static final org.apache.thrift.protocol.TField CIPHERTEXT_FIELD_DESC = new org.apache.thrift.protocol.TField("ciphertext", org.apache.thrift.protocol.TType.STRING, (short)2);
16 |
17 | private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new CiphertextMessageStructStandardSchemeFactory();
18 | private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new CiphertextMessageStructTupleSchemeFactory();
19 |
20 | public AuthenticatedMessageStruct authenticatedMessage; // required
21 | public java.nio.ByteBuffer ciphertext; // required
22 |
23 | /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
24 | public enum _Fields implements org.apache.thrift.TFieldIdEnum {
25 | AUTHENTICATED_MESSAGE((short)1, "authenticatedMessage"),
26 | CIPHERTEXT((short)2, "ciphertext");
27 |
28 | private static final java.util.Map byName = new java.util.HashMap();
29 |
30 | static {
31 | for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
32 | byName.put(field.getFieldName(), field);
33 | }
34 | }
35 |
36 | /**
37 | * Find the _Fields constant that matches fieldId, or null if its not found.
38 | */
39 | public static _Fields findByThriftId(int fieldId) {
40 | switch(fieldId) {
41 | case 1: // AUTHENTICATED_MESSAGE
42 | return AUTHENTICATED_MESSAGE;
43 | case 2: // CIPHERTEXT
44 | return CIPHERTEXT;
45 | default:
46 | return null;
47 | }
48 | }
49 |
50 | /**
51 | * Find the _Fields constant that matches fieldId, throwing an exception
52 | * if it is not found.
53 | */
54 | public static _Fields findByThriftIdOrThrow(int fieldId) {
55 | _Fields fields = findByThriftId(fieldId);
56 | if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!");
57 | return fields;
58 | }
59 |
60 | /**
61 | * Find the _Fields constant that matches name, or null if its not found.
62 | */
63 | public static _Fields findByName(java.lang.String name) {
64 | return byName.get(name);
65 | }
66 |
67 | private final short _thriftId;
68 | private final java.lang.String _fieldName;
69 |
70 | _Fields(short thriftId, java.lang.String fieldName) {
71 | _thriftId = thriftId;
72 | _fieldName = fieldName;
73 | }
74 |
75 | public short getThriftFieldId() {
76 | return _thriftId;
77 | }
78 |
79 | public java.lang.String getFieldName() {
80 | return _fieldName;
81 | }
82 | }
83 |
84 | // isset id assignments
85 | public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
86 | static {
87 | java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
88 | tmpMap.put(_Fields.AUTHENTICATED_MESSAGE, new org.apache.thrift.meta_data.FieldMetaData("authenticatedMessage", org.apache.thrift.TFieldRequirementType.DEFAULT,
89 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT , "AuthenticatedMessageStruct")));
90 | tmpMap.put(_Fields.CIPHERTEXT, new org.apache.thrift.meta_data.FieldMetaData("ciphertext", org.apache.thrift.TFieldRequirementType.DEFAULT,
91 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING , true)));
92 | metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
93 | org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(CiphertextMessageStruct.class, metaDataMap);
94 | }
95 |
96 | public CiphertextMessageStruct() {
97 | }
98 |
99 | public CiphertextMessageStruct(
100 | AuthenticatedMessageStruct authenticatedMessage,
101 | java.nio.ByteBuffer ciphertext)
102 | {
103 | this();
104 | this.authenticatedMessage = authenticatedMessage;
105 | this.ciphertext = org.apache.thrift.TBaseHelper.copyBinary(ciphertext);
106 | }
107 |
108 | /**
109 | * Performs a deep copy on other.
110 | */
111 | public CiphertextMessageStruct(CiphertextMessageStruct other) {
112 | if (other.isSetAuthenticatedMessage()) {
113 | this.authenticatedMessage = new AuthenticatedMessageStruct(other.authenticatedMessage);
114 | }
115 | if (other.isSetCiphertext()) {
116 | this.ciphertext = org.apache.thrift.TBaseHelper.copyBinary(other.ciphertext);
117 | }
118 | }
119 |
120 | public CiphertextMessageStruct deepCopy() {
121 | return new CiphertextMessageStruct(this);
122 | }
123 |
124 | @Override
125 | public void clear() {
126 | this.authenticatedMessage = null;
127 | this.ciphertext = null;
128 | }
129 |
130 | public AuthenticatedMessageStruct getAuthenticatedMessage() {
131 | return this.authenticatedMessage;
132 | }
133 |
134 | public CiphertextMessageStruct setAuthenticatedMessage(AuthenticatedMessageStruct authenticatedMessage) {
135 | this.authenticatedMessage = authenticatedMessage;
136 | return this;
137 | }
138 |
139 | public void unsetAuthenticatedMessage() {
140 | this.authenticatedMessage = null;
141 | }
142 |
143 | /** Returns true if field authenticatedMessage is set (has been assigned a value) and false otherwise */
144 | public boolean isSetAuthenticatedMessage() {
145 | return this.authenticatedMessage != null;
146 | }
147 |
148 | public void setAuthenticatedMessageIsSet(boolean value) {
149 | if (!value) {
150 | this.authenticatedMessage = null;
151 | }
152 | }
153 |
154 | public byte[] getCiphertext() {
155 | setCiphertext(org.apache.thrift.TBaseHelper.rightSize(ciphertext));
156 | return ciphertext == null ? null : ciphertext.array();
157 | }
158 |
159 | public java.nio.ByteBuffer bufferForCiphertext() {
160 | return org.apache.thrift.TBaseHelper.copyBinary(ciphertext);
161 | }
162 |
163 | public CiphertextMessageStruct setCiphertext(byte[] ciphertext) {
164 | this.ciphertext = ciphertext == null ? (java.nio.ByteBuffer)null : java.nio.ByteBuffer.wrap(ciphertext.clone());
165 | return this;
166 | }
167 |
168 | public CiphertextMessageStruct setCiphertext(java.nio.ByteBuffer ciphertext) {
169 | this.ciphertext = org.apache.thrift.TBaseHelper.copyBinary(ciphertext);
170 | return this;
171 | }
172 |
173 | public void unsetCiphertext() {
174 | this.ciphertext = null;
175 | }
176 |
177 | /** Returns true if field ciphertext is set (has been assigned a value) and false otherwise */
178 | public boolean isSetCiphertext() {
179 | return this.ciphertext != null;
180 | }
181 |
182 | public void setCiphertextIsSet(boolean value) {
183 | if (!value) {
184 | this.ciphertext = null;
185 | }
186 | }
187 |
188 | public void setFieldValue(_Fields field, java.lang.Object value) {
189 | switch (field) {
190 | case AUTHENTICATED_MESSAGE:
191 | if (value == null) {
192 | unsetAuthenticatedMessage();
193 | } else {
194 | setAuthenticatedMessage((AuthenticatedMessageStruct)value);
195 | }
196 | break;
197 |
198 | case CIPHERTEXT:
199 | if (value == null) {
200 | unsetCiphertext();
201 | } else {
202 | if (value instanceof byte[]) {
203 | setCiphertext((byte[])value);
204 | } else {
205 | setCiphertext((java.nio.ByteBuffer)value);
206 | }
207 | }
208 | break;
209 |
210 | }
211 | }
212 |
213 | public java.lang.Object getFieldValue(_Fields field) {
214 | switch (field) {
215 | case AUTHENTICATED_MESSAGE:
216 | return getAuthenticatedMessage();
217 |
218 | case CIPHERTEXT:
219 | return getCiphertext();
220 |
221 | }
222 | throw new java.lang.IllegalStateException();
223 | }
224 |
225 | /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
226 | public boolean isSet(_Fields field) {
227 | if (field == null) {
228 | throw new java.lang.IllegalArgumentException();
229 | }
230 |
231 | switch (field) {
232 | case AUTHENTICATED_MESSAGE:
233 | return isSetAuthenticatedMessage();
234 | case CIPHERTEXT:
235 | return isSetCiphertext();
236 | }
237 | throw new java.lang.IllegalStateException();
238 | }
239 |
240 | @Override
241 | public boolean equals(java.lang.Object that) {
242 | if (that == null)
243 | return false;
244 | if (that instanceof CiphertextMessageStruct)
245 | return this.equals((CiphertextMessageStruct)that);
246 | return false;
247 | }
248 |
249 | public boolean equals(CiphertextMessageStruct that) {
250 | if (that == null)
251 | return false;
252 | if (this == that)
253 | return true;
254 |
255 | boolean this_present_authenticatedMessage = true && this.isSetAuthenticatedMessage();
256 | boolean that_present_authenticatedMessage = true && that.isSetAuthenticatedMessage();
257 | if (this_present_authenticatedMessage || that_present_authenticatedMessage) {
258 | if (!(this_present_authenticatedMessage && that_present_authenticatedMessage))
259 | return false;
260 | if (!this.authenticatedMessage.equals(that.authenticatedMessage))
261 | return false;
262 | }
263 |
264 | boolean this_present_ciphertext = true && this.isSetCiphertext();
265 | boolean that_present_ciphertext = true && that.isSetCiphertext();
266 | if (this_present_ciphertext || that_present_ciphertext) {
267 | if (!(this_present_ciphertext && that_present_ciphertext))
268 | return false;
269 | if (!this.ciphertext.equals(that.ciphertext))
270 | return false;
271 | }
272 |
273 | return true;
274 | }
275 |
276 | @Override
277 | public int hashCode() {
278 | int hashCode = 1;
279 |
280 | hashCode = hashCode * 8191 + ((isSetAuthenticatedMessage()) ? 131071 : 524287);
281 | if (isSetAuthenticatedMessage())
282 | hashCode = hashCode * 8191 + authenticatedMessage.hashCode();
283 |
284 | hashCode = hashCode * 8191 + ((isSetCiphertext()) ? 131071 : 524287);
285 | if (isSetCiphertext())
286 | hashCode = hashCode * 8191 + ciphertext.hashCode();
287 |
288 | return hashCode;
289 | }
290 |
291 | @Override
292 | public int compareTo(CiphertextMessageStruct other) {
293 | if (!getClass().equals(other.getClass())) {
294 | return getClass().getName().compareTo(other.getClass().getName());
295 | }
296 |
297 | int lastComparison = 0;
298 |
299 | lastComparison = java.lang.Boolean.valueOf(isSetAuthenticatedMessage()).compareTo(other.isSetAuthenticatedMessage());
300 | if (lastComparison != 0) {
301 | return lastComparison;
302 | }
303 | if (isSetAuthenticatedMessage()) {
304 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.authenticatedMessage, other.authenticatedMessage);
305 | if (lastComparison != 0) {
306 | return lastComparison;
307 | }
308 | }
309 | lastComparison = java.lang.Boolean.valueOf(isSetCiphertext()).compareTo(other.isSetCiphertext());
310 | if (lastComparison != 0) {
311 | return lastComparison;
312 | }
313 | if (isSetCiphertext()) {
314 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.ciphertext, other.ciphertext);
315 | if (lastComparison != 0) {
316 | return lastComparison;
317 | }
318 | }
319 | return 0;
320 | }
321 |
322 | public _Fields fieldForId(int fieldId) {
323 | return _Fields.findByThriftId(fieldId);
324 | }
325 |
326 | public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
327 | scheme(iprot).read(iprot, this);
328 | }
329 |
330 | public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
331 | scheme(oprot).write(oprot, this);
332 | }
333 |
334 | @Override
335 | public java.lang.String toString() {
336 | java.lang.StringBuilder sb = new java.lang.StringBuilder("CiphertextMessageStruct(");
337 | boolean first = true;
338 |
339 | sb.append("authenticatedMessage:");
340 | if (this.authenticatedMessage == null) {
341 | sb.append("null");
342 | } else {
343 | sb.append(this.authenticatedMessage);
344 | }
345 | first = false;
346 | if (!first) sb.append(", ");
347 | sb.append("ciphertext:");
348 | if (this.ciphertext == null) {
349 | sb.append("null");
350 | } else {
351 | org.apache.thrift.TBaseHelper.toString(this.ciphertext, sb);
352 | }
353 | first = false;
354 | sb.append(")");
355 | return sb.toString();
356 | }
357 |
358 | public void validate() throws org.apache.thrift.TException {
359 | // check for required fields
360 | // check for sub-struct validity
361 | }
362 |
363 | private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
364 | try {
365 | write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
366 | } catch (org.apache.thrift.TException te) {
367 | throw new java.io.IOException(te);
368 | }
369 | }
370 |
371 | private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException {
372 | try {
373 | read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
374 | } catch (org.apache.thrift.TException te) {
375 | throw new java.io.IOException(te);
376 | }
377 | }
378 |
379 | private static class CiphertextMessageStructStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
380 | public CiphertextMessageStructStandardScheme getScheme() {
381 | return new CiphertextMessageStructStandardScheme();
382 | }
383 | }
384 |
385 | private static class CiphertextMessageStructStandardScheme extends org.apache.thrift.scheme.StandardScheme {
386 |
387 | public void read(org.apache.thrift.protocol.TProtocol iprot, CiphertextMessageStruct struct) throws org.apache.thrift.TException {
388 | org.apache.thrift.protocol.TField schemeField;
389 | iprot.readStructBegin();
390 | while (true)
391 | {
392 | schemeField = iprot.readFieldBegin();
393 | if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
394 | break;
395 | }
396 | switch (schemeField.id) {
397 | case 1: // AUTHENTICATED_MESSAGE
398 | if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
399 | struct.authenticatedMessage = new AuthenticatedMessageStruct();
400 | struct.authenticatedMessage.read(iprot);
401 | struct.setAuthenticatedMessageIsSet(true);
402 | } else {
403 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
404 | }
405 | break;
406 | case 2: // CIPHERTEXT
407 | if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
408 | struct.ciphertext = iprot.readBinary();
409 | struct.setCiphertextIsSet(true);
410 | } else {
411 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
412 | }
413 | break;
414 | default:
415 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
416 | }
417 | iprot.readFieldEnd();
418 | }
419 | iprot.readStructEnd();
420 |
421 | // check for required fields of primitive type, which can't be checked in the validate method
422 | struct.validate();
423 | }
424 |
425 | public void write(org.apache.thrift.protocol.TProtocol oprot, CiphertextMessageStruct struct) throws org.apache.thrift.TException {
426 | struct.validate();
427 |
428 | oprot.writeStructBegin(STRUCT_DESC);
429 | if (struct.authenticatedMessage != null) {
430 | oprot.writeFieldBegin(AUTHENTICATED_MESSAGE_FIELD_DESC);
431 | struct.authenticatedMessage.write(oprot);
432 | oprot.writeFieldEnd();
433 | }
434 | if (struct.ciphertext != null) {
435 | oprot.writeFieldBegin(CIPHERTEXT_FIELD_DESC);
436 | oprot.writeBinary(struct.ciphertext);
437 | oprot.writeFieldEnd();
438 | }
439 | oprot.writeFieldStop();
440 | oprot.writeStructEnd();
441 | }
442 |
443 | }
444 |
445 | private static class CiphertextMessageStructTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
446 | public CiphertextMessageStructTupleScheme getScheme() {
447 | return new CiphertextMessageStructTupleScheme();
448 | }
449 | }
450 |
451 | private static class CiphertextMessageStructTupleScheme extends org.apache.thrift.scheme.TupleScheme {
452 |
453 | @Override
454 | public void write(org.apache.thrift.protocol.TProtocol prot, CiphertextMessageStruct struct) throws org.apache.thrift.TException {
455 | org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
456 | java.util.BitSet optionals = new java.util.BitSet();
457 | if (struct.isSetAuthenticatedMessage()) {
458 | optionals.set(0);
459 | }
460 | if (struct.isSetCiphertext()) {
461 | optionals.set(1);
462 | }
463 | oprot.writeBitSet(optionals, 2);
464 | if (struct.isSetAuthenticatedMessage()) {
465 | struct.authenticatedMessage.write(oprot);
466 | }
467 | if (struct.isSetCiphertext()) {
468 | oprot.writeBinary(struct.ciphertext);
469 | }
470 | }
471 |
472 | @Override
473 | public void read(org.apache.thrift.protocol.TProtocol prot, CiphertextMessageStruct struct) throws org.apache.thrift.TException {
474 | org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
475 | java.util.BitSet incoming = iprot.readBitSet(2);
476 | if (incoming.get(0)) {
477 | struct.authenticatedMessage = new AuthenticatedMessageStruct();
478 | struct.authenticatedMessage.read(iprot);
479 | struct.setAuthenticatedMessageIsSet(true);
480 | }
481 | if (incoming.get(1)) {
482 | struct.ciphertext = iprot.readBinary();
483 | struct.setCiphertextIsSet(true);
484 | }
485 | }
486 | }
487 |
488 | private static S scheme(org.apache.thrift.protocol.TProtocol proto) {
489 | return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme();
490 | }
491 | }
492 |
493 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/message/thrift/NodeStruct.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Autogenerated by Thrift Compiler (0.10.0)
3 | *
4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5 | * @generated
6 | */
7 | package com.facebook.research.asynchronousratchetingtree.art.message.thrift;
8 |
9 | @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
10 | @javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)", date = "2018-01-05")
11 | public class NodeStruct implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable {
12 | private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("NodeStruct");
13 |
14 | private static final org.apache.thrift.protocol.TField PUBLIC_KEY_FIELD_DESC = new org.apache.thrift.protocol.TField("publicKey", org.apache.thrift.protocol.TType.STRING, (short)1);
15 | private static final org.apache.thrift.protocol.TField LEFT_FIELD_DESC = new org.apache.thrift.protocol.TField("left", org.apache.thrift.protocol.TType.STRUCT, (short)2);
16 | private static final org.apache.thrift.protocol.TField RIGHT_FIELD_DESC = new org.apache.thrift.protocol.TField("right", org.apache.thrift.protocol.TType.STRUCT, (short)3);
17 |
18 | private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new NodeStructStandardSchemeFactory();
19 | private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new NodeStructTupleSchemeFactory();
20 |
21 | public java.nio.ByteBuffer publicKey; // required
22 | public NodeStruct left; // optional
23 | public NodeStruct right; // optional
24 |
25 | /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
26 | public enum _Fields implements org.apache.thrift.TFieldIdEnum {
27 | PUBLIC_KEY((short)1, "publicKey"),
28 | LEFT((short)2, "left"),
29 | RIGHT((short)3, "right");
30 |
31 | private static final java.util.Map byName = new java.util.HashMap();
32 |
33 | static {
34 | for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
35 | byName.put(field.getFieldName(), field);
36 | }
37 | }
38 |
39 | /**
40 | * Find the _Fields constant that matches fieldId, or null if its not found.
41 | */
42 | public static _Fields findByThriftId(int fieldId) {
43 | switch(fieldId) {
44 | case 1: // PUBLIC_KEY
45 | return PUBLIC_KEY;
46 | case 2: // LEFT
47 | return LEFT;
48 | case 3: // RIGHT
49 | return RIGHT;
50 | default:
51 | return null;
52 | }
53 | }
54 |
55 | /**
56 | * Find the _Fields constant that matches fieldId, throwing an exception
57 | * if it is not found.
58 | */
59 | public static _Fields findByThriftIdOrThrow(int fieldId) {
60 | _Fields fields = findByThriftId(fieldId);
61 | if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!");
62 | return fields;
63 | }
64 |
65 | /**
66 | * Find the _Fields constant that matches name, or null if its not found.
67 | */
68 | public static _Fields findByName(java.lang.String name) {
69 | return byName.get(name);
70 | }
71 |
72 | private final short _thriftId;
73 | private final java.lang.String _fieldName;
74 |
75 | _Fields(short thriftId, java.lang.String fieldName) {
76 | _thriftId = thriftId;
77 | _fieldName = fieldName;
78 | }
79 |
80 | public short getThriftFieldId() {
81 | return _thriftId;
82 | }
83 |
84 | public java.lang.String getFieldName() {
85 | return _fieldName;
86 | }
87 | }
88 |
89 | // isset id assignments
90 | private static final _Fields optionals[] = {_Fields.LEFT,_Fields.RIGHT};
91 | public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
92 | static {
93 | java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
94 | tmpMap.put(_Fields.PUBLIC_KEY, new org.apache.thrift.meta_data.FieldMetaData("publicKey", org.apache.thrift.TFieldRequirementType.DEFAULT,
95 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING , true)));
96 | tmpMap.put(_Fields.LEFT, new org.apache.thrift.meta_data.FieldMetaData("left", org.apache.thrift.TFieldRequirementType.OPTIONAL,
97 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT , "NodeStruct")));
98 | tmpMap.put(_Fields.RIGHT, new org.apache.thrift.meta_data.FieldMetaData("right", org.apache.thrift.TFieldRequirementType.OPTIONAL,
99 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT , "NodeStruct")));
100 | metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
101 | org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(NodeStruct.class, metaDataMap);
102 | }
103 |
104 | public NodeStruct() {
105 | }
106 |
107 | public NodeStruct(
108 | java.nio.ByteBuffer publicKey)
109 | {
110 | this();
111 | this.publicKey = org.apache.thrift.TBaseHelper.copyBinary(publicKey);
112 | }
113 |
114 | /**
115 | * Performs a deep copy on other.
116 | */
117 | public NodeStruct(NodeStruct other) {
118 | if (other.isSetPublicKey()) {
119 | this.publicKey = org.apache.thrift.TBaseHelper.copyBinary(other.publicKey);
120 | }
121 | if (other.isSetLeft()) {
122 | this.left = new NodeStruct(other.left);
123 | }
124 | if (other.isSetRight()) {
125 | this.right = new NodeStruct(other.right);
126 | }
127 | }
128 |
129 | public NodeStruct deepCopy() {
130 | return new NodeStruct(this);
131 | }
132 |
133 | @Override
134 | public void clear() {
135 | this.publicKey = null;
136 | this.left = null;
137 | this.right = null;
138 | }
139 |
140 | public byte[] getPublicKey() {
141 | setPublicKey(org.apache.thrift.TBaseHelper.rightSize(publicKey));
142 | return publicKey == null ? null : publicKey.array();
143 | }
144 |
145 | public java.nio.ByteBuffer bufferForPublicKey() {
146 | return org.apache.thrift.TBaseHelper.copyBinary(publicKey);
147 | }
148 |
149 | public NodeStruct setPublicKey(byte[] publicKey) {
150 | this.publicKey = publicKey == null ? (java.nio.ByteBuffer)null : java.nio.ByteBuffer.wrap(publicKey.clone());
151 | return this;
152 | }
153 |
154 | public NodeStruct setPublicKey(java.nio.ByteBuffer publicKey) {
155 | this.publicKey = org.apache.thrift.TBaseHelper.copyBinary(publicKey);
156 | return this;
157 | }
158 |
159 | public void unsetPublicKey() {
160 | this.publicKey = null;
161 | }
162 |
163 | /** Returns true if field publicKey is set (has been assigned a value) and false otherwise */
164 | public boolean isSetPublicKey() {
165 | return this.publicKey != null;
166 | }
167 |
168 | public void setPublicKeyIsSet(boolean value) {
169 | if (!value) {
170 | this.publicKey = null;
171 | }
172 | }
173 |
174 | public NodeStruct getLeft() {
175 | return this.left;
176 | }
177 |
178 | public NodeStruct setLeft(NodeStruct left) {
179 | this.left = left;
180 | return this;
181 | }
182 |
183 | public void unsetLeft() {
184 | this.left = null;
185 | }
186 |
187 | /** Returns true if field left is set (has been assigned a value) and false otherwise */
188 | public boolean isSetLeft() {
189 | return this.left != null;
190 | }
191 |
192 | public void setLeftIsSet(boolean value) {
193 | if (!value) {
194 | this.left = null;
195 | }
196 | }
197 |
198 | public NodeStruct getRight() {
199 | return this.right;
200 | }
201 |
202 | public NodeStruct setRight(NodeStruct right) {
203 | this.right = right;
204 | return this;
205 | }
206 |
207 | public void unsetRight() {
208 | this.right = null;
209 | }
210 |
211 | /** Returns true if field right is set (has been assigned a value) and false otherwise */
212 | public boolean isSetRight() {
213 | return this.right != null;
214 | }
215 |
216 | public void setRightIsSet(boolean value) {
217 | if (!value) {
218 | this.right = null;
219 | }
220 | }
221 |
222 | public void setFieldValue(_Fields field, java.lang.Object value) {
223 | switch (field) {
224 | case PUBLIC_KEY:
225 | if (value == null) {
226 | unsetPublicKey();
227 | } else {
228 | if (value instanceof byte[]) {
229 | setPublicKey((byte[])value);
230 | } else {
231 | setPublicKey((java.nio.ByteBuffer)value);
232 | }
233 | }
234 | break;
235 |
236 | case LEFT:
237 | if (value == null) {
238 | unsetLeft();
239 | } else {
240 | setLeft((NodeStruct)value);
241 | }
242 | break;
243 |
244 | case RIGHT:
245 | if (value == null) {
246 | unsetRight();
247 | } else {
248 | setRight((NodeStruct)value);
249 | }
250 | break;
251 |
252 | }
253 | }
254 |
255 | public java.lang.Object getFieldValue(_Fields field) {
256 | switch (field) {
257 | case PUBLIC_KEY:
258 | return getPublicKey();
259 |
260 | case LEFT:
261 | return getLeft();
262 |
263 | case RIGHT:
264 | return getRight();
265 |
266 | }
267 | throw new java.lang.IllegalStateException();
268 | }
269 |
270 | /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
271 | public boolean isSet(_Fields field) {
272 | if (field == null) {
273 | throw new java.lang.IllegalArgumentException();
274 | }
275 |
276 | switch (field) {
277 | case PUBLIC_KEY:
278 | return isSetPublicKey();
279 | case LEFT:
280 | return isSetLeft();
281 | case RIGHT:
282 | return isSetRight();
283 | }
284 | throw new java.lang.IllegalStateException();
285 | }
286 |
287 | @Override
288 | public boolean equals(java.lang.Object that) {
289 | if (that == null)
290 | return false;
291 | if (that instanceof NodeStruct)
292 | return this.equals((NodeStruct)that);
293 | return false;
294 | }
295 |
296 | public boolean equals(NodeStruct that) {
297 | if (that == null)
298 | return false;
299 | if (this == that)
300 | return true;
301 |
302 | boolean this_present_publicKey = true && this.isSetPublicKey();
303 | boolean that_present_publicKey = true && that.isSetPublicKey();
304 | if (this_present_publicKey || that_present_publicKey) {
305 | if (!(this_present_publicKey && that_present_publicKey))
306 | return false;
307 | if (!this.publicKey.equals(that.publicKey))
308 | return false;
309 | }
310 |
311 | boolean this_present_left = true && this.isSetLeft();
312 | boolean that_present_left = true && that.isSetLeft();
313 | if (this_present_left || that_present_left) {
314 | if (!(this_present_left && that_present_left))
315 | return false;
316 | if (!this.left.equals(that.left))
317 | return false;
318 | }
319 |
320 | boolean this_present_right = true && this.isSetRight();
321 | boolean that_present_right = true && that.isSetRight();
322 | if (this_present_right || that_present_right) {
323 | if (!(this_present_right && that_present_right))
324 | return false;
325 | if (!this.right.equals(that.right))
326 | return false;
327 | }
328 |
329 | return true;
330 | }
331 |
332 | @Override
333 | public int hashCode() {
334 | int hashCode = 1;
335 |
336 | hashCode = hashCode * 8191 + ((isSetPublicKey()) ? 131071 : 524287);
337 | if (isSetPublicKey())
338 | hashCode = hashCode * 8191 + publicKey.hashCode();
339 |
340 | hashCode = hashCode * 8191 + ((isSetLeft()) ? 131071 : 524287);
341 | if (isSetLeft())
342 | hashCode = hashCode * 8191 + left.hashCode();
343 |
344 | hashCode = hashCode * 8191 + ((isSetRight()) ? 131071 : 524287);
345 | if (isSetRight())
346 | hashCode = hashCode * 8191 + right.hashCode();
347 |
348 | return hashCode;
349 | }
350 |
351 | @Override
352 | public int compareTo(NodeStruct other) {
353 | if (!getClass().equals(other.getClass())) {
354 | return getClass().getName().compareTo(other.getClass().getName());
355 | }
356 |
357 | int lastComparison = 0;
358 |
359 | lastComparison = java.lang.Boolean.valueOf(isSetPublicKey()).compareTo(other.isSetPublicKey());
360 | if (lastComparison != 0) {
361 | return lastComparison;
362 | }
363 | if (isSetPublicKey()) {
364 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.publicKey, other.publicKey);
365 | if (lastComparison != 0) {
366 | return lastComparison;
367 | }
368 | }
369 | lastComparison = java.lang.Boolean.valueOf(isSetLeft()).compareTo(other.isSetLeft());
370 | if (lastComparison != 0) {
371 | return lastComparison;
372 | }
373 | if (isSetLeft()) {
374 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.left, other.left);
375 | if (lastComparison != 0) {
376 | return lastComparison;
377 | }
378 | }
379 | lastComparison = java.lang.Boolean.valueOf(isSetRight()).compareTo(other.isSetRight());
380 | if (lastComparison != 0) {
381 | return lastComparison;
382 | }
383 | if (isSetRight()) {
384 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.right, other.right);
385 | if (lastComparison != 0) {
386 | return lastComparison;
387 | }
388 | }
389 | return 0;
390 | }
391 |
392 | public _Fields fieldForId(int fieldId) {
393 | return _Fields.findByThriftId(fieldId);
394 | }
395 |
396 | public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
397 | scheme(iprot).read(iprot, this);
398 | }
399 |
400 | public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
401 | scheme(oprot).write(oprot, this);
402 | }
403 |
404 | @Override
405 | public java.lang.String toString() {
406 | java.lang.StringBuilder sb = new java.lang.StringBuilder("NodeStruct(");
407 | boolean first = true;
408 |
409 | sb.append("publicKey:");
410 | if (this.publicKey == null) {
411 | sb.append("null");
412 | } else {
413 | org.apache.thrift.TBaseHelper.toString(this.publicKey, sb);
414 | }
415 | first = false;
416 | if (isSetLeft()) {
417 | if (!first) sb.append(", ");
418 | sb.append("left:");
419 | if (this.left == null) {
420 | sb.append("null");
421 | } else {
422 | sb.append(this.left);
423 | }
424 | first = false;
425 | }
426 | if (isSetRight()) {
427 | if (!first) sb.append(", ");
428 | sb.append("right:");
429 | if (this.right == null) {
430 | sb.append("null");
431 | } else {
432 | sb.append(this.right);
433 | }
434 | first = false;
435 | }
436 | sb.append(")");
437 | return sb.toString();
438 | }
439 |
440 | public void validate() throws org.apache.thrift.TException {
441 | // check for required fields
442 | // check for sub-struct validity
443 | }
444 |
445 | private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
446 | try {
447 | write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
448 | } catch (org.apache.thrift.TException te) {
449 | throw new java.io.IOException(te);
450 | }
451 | }
452 |
453 | private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException {
454 | try {
455 | read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
456 | } catch (org.apache.thrift.TException te) {
457 | throw new java.io.IOException(te);
458 | }
459 | }
460 |
461 | private static class NodeStructStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
462 | public NodeStructStandardScheme getScheme() {
463 | return new NodeStructStandardScheme();
464 | }
465 | }
466 |
467 | private static class NodeStructStandardScheme extends org.apache.thrift.scheme.StandardScheme {
468 |
469 | public void read(org.apache.thrift.protocol.TProtocol iprot, NodeStruct struct) throws org.apache.thrift.TException {
470 | org.apache.thrift.protocol.TField schemeField;
471 | iprot.readStructBegin();
472 | while (true)
473 | {
474 | schemeField = iprot.readFieldBegin();
475 | if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
476 | break;
477 | }
478 | switch (schemeField.id) {
479 | case 1: // PUBLIC_KEY
480 | if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
481 | struct.publicKey = iprot.readBinary();
482 | struct.setPublicKeyIsSet(true);
483 | } else {
484 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
485 | }
486 | break;
487 | case 2: // LEFT
488 | if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
489 | struct.left = new NodeStruct();
490 | struct.left.read(iprot);
491 | struct.setLeftIsSet(true);
492 | } else {
493 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
494 | }
495 | break;
496 | case 3: // RIGHT
497 | if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
498 | struct.right = new NodeStruct();
499 | struct.right.read(iprot);
500 | struct.setRightIsSet(true);
501 | } else {
502 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
503 | }
504 | break;
505 | default:
506 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
507 | }
508 | iprot.readFieldEnd();
509 | }
510 | iprot.readStructEnd();
511 |
512 | // check for required fields of primitive type, which can't be checked in the validate method
513 | struct.validate();
514 | }
515 |
516 | public void write(org.apache.thrift.protocol.TProtocol oprot, NodeStruct struct) throws org.apache.thrift.TException {
517 | struct.validate();
518 |
519 | oprot.writeStructBegin(STRUCT_DESC);
520 | if (struct.publicKey != null) {
521 | oprot.writeFieldBegin(PUBLIC_KEY_FIELD_DESC);
522 | oprot.writeBinary(struct.publicKey);
523 | oprot.writeFieldEnd();
524 | }
525 | if (struct.left != null) {
526 | if (struct.isSetLeft()) {
527 | oprot.writeFieldBegin(LEFT_FIELD_DESC);
528 | struct.left.write(oprot);
529 | oprot.writeFieldEnd();
530 | }
531 | }
532 | if (struct.right != null) {
533 | if (struct.isSetRight()) {
534 | oprot.writeFieldBegin(RIGHT_FIELD_DESC);
535 | struct.right.write(oprot);
536 | oprot.writeFieldEnd();
537 | }
538 | }
539 | oprot.writeFieldStop();
540 | oprot.writeStructEnd();
541 | }
542 |
543 | }
544 |
545 | private static class NodeStructTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
546 | public NodeStructTupleScheme getScheme() {
547 | return new NodeStructTupleScheme();
548 | }
549 | }
550 |
551 | private static class NodeStructTupleScheme extends org.apache.thrift.scheme.TupleScheme {
552 |
553 | @Override
554 | public void write(org.apache.thrift.protocol.TProtocol prot, NodeStruct struct) throws org.apache.thrift.TException {
555 | org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
556 | java.util.BitSet optionals = new java.util.BitSet();
557 | if (struct.isSetPublicKey()) {
558 | optionals.set(0);
559 | }
560 | if (struct.isSetLeft()) {
561 | optionals.set(1);
562 | }
563 | if (struct.isSetRight()) {
564 | optionals.set(2);
565 | }
566 | oprot.writeBitSet(optionals, 3);
567 | if (struct.isSetPublicKey()) {
568 | oprot.writeBinary(struct.publicKey);
569 | }
570 | if (struct.isSetLeft()) {
571 | struct.left.write(oprot);
572 | }
573 | if (struct.isSetRight()) {
574 | struct.right.write(oprot);
575 | }
576 | }
577 |
578 | @Override
579 | public void read(org.apache.thrift.protocol.TProtocol prot, NodeStruct struct) throws org.apache.thrift.TException {
580 | org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
581 | java.util.BitSet incoming = iprot.readBitSet(3);
582 | if (incoming.get(0)) {
583 | struct.publicKey = iprot.readBinary();
584 | struct.setPublicKeyIsSet(true);
585 | }
586 | if (incoming.get(1)) {
587 | struct.left = new NodeStruct();
588 | struct.left.read(iprot);
589 | struct.setLeftIsSet(true);
590 | }
591 | if (incoming.get(2)) {
592 | struct.right = new NodeStruct();
593 | struct.right.read(iprot);
594 | struct.setRightIsSet(true);
595 | }
596 | }
597 | }
598 |
599 | private static S scheme(org.apache.thrift.protocol.TProtocol proto) {
600 | return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme();
601 | }
602 | }
603 |
604 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/message/thrift/UpdateMessageStruct.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Autogenerated by Thrift Compiler (0.10.0)
3 | *
4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5 | * @generated
6 | */
7 | package com.facebook.research.asynchronousratchetingtree.art.message.thrift;
8 |
9 | @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
10 | @javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)", date = "2018-01-05")
11 | public class UpdateMessageStruct implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable {
12 | private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("UpdateMessageStruct");
13 |
14 | private static final org.apache.thrift.protocol.TField LEAF_NUM_FIELD_DESC = new org.apache.thrift.protocol.TField("leafNum", org.apache.thrift.protocol.TType.I32, (short)1);
15 | private static final org.apache.thrift.protocol.TField PATH_FIELD_DESC = new org.apache.thrift.protocol.TField("path", org.apache.thrift.protocol.TType.LIST, (short)2);
16 |
17 | private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new UpdateMessageStructStandardSchemeFactory();
18 | private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new UpdateMessageStructTupleSchemeFactory();
19 |
20 | public int leafNum; // required
21 | public java.util.List path; // required
22 |
23 | /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
24 | public enum _Fields implements org.apache.thrift.TFieldIdEnum {
25 | LEAF_NUM((short)1, "leafNum"),
26 | PATH((short)2, "path");
27 |
28 | private static final java.util.Map byName = new java.util.HashMap();
29 |
30 | static {
31 | for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
32 | byName.put(field.getFieldName(), field);
33 | }
34 | }
35 |
36 | /**
37 | * Find the _Fields constant that matches fieldId, or null if its not found.
38 | */
39 | public static _Fields findByThriftId(int fieldId) {
40 | switch(fieldId) {
41 | case 1: // LEAF_NUM
42 | return LEAF_NUM;
43 | case 2: // PATH
44 | return PATH;
45 | default:
46 | return null;
47 | }
48 | }
49 |
50 | /**
51 | * Find the _Fields constant that matches fieldId, throwing an exception
52 | * if it is not found.
53 | */
54 | public static _Fields findByThriftIdOrThrow(int fieldId) {
55 | _Fields fields = findByThriftId(fieldId);
56 | if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!");
57 | return fields;
58 | }
59 |
60 | /**
61 | * Find the _Fields constant that matches name, or null if its not found.
62 | */
63 | public static _Fields findByName(java.lang.String name) {
64 | return byName.get(name);
65 | }
66 |
67 | private final short _thriftId;
68 | private final java.lang.String _fieldName;
69 |
70 | _Fields(short thriftId, java.lang.String fieldName) {
71 | _thriftId = thriftId;
72 | _fieldName = fieldName;
73 | }
74 |
75 | public short getThriftFieldId() {
76 | return _thriftId;
77 | }
78 |
79 | public java.lang.String getFieldName() {
80 | return _fieldName;
81 | }
82 | }
83 |
84 | // isset id assignments
85 | private static final int __LEAFNUM_ISSET_ID = 0;
86 | private byte __isset_bitfield = 0;
87 | public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
88 | static {
89 | java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
90 | tmpMap.put(_Fields.LEAF_NUM, new org.apache.thrift.meta_data.FieldMetaData("leafNum", org.apache.thrift.TFieldRequirementType.DEFAULT,
91 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
92 | tmpMap.put(_Fields.PATH, new org.apache.thrift.meta_data.FieldMetaData("path", org.apache.thrift.TFieldRequirementType.DEFAULT,
93 | new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST,
94 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
95 | metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
96 | org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(UpdateMessageStruct.class, metaDataMap);
97 | }
98 |
99 | public UpdateMessageStruct() {
100 | }
101 |
102 | public UpdateMessageStruct(
103 | int leafNum,
104 | java.util.List path)
105 | {
106 | this();
107 | this.leafNum = leafNum;
108 | setLeafNumIsSet(true);
109 | this.path = path;
110 | }
111 |
112 | /**
113 | * Performs a deep copy on other.
114 | */
115 | public UpdateMessageStruct(UpdateMessageStruct other) {
116 | __isset_bitfield = other.__isset_bitfield;
117 | this.leafNum = other.leafNum;
118 | if (other.isSetPath()) {
119 | java.util.List __this__path = new java.util.ArrayList(other.path);
120 | this.path = __this__path;
121 | }
122 | }
123 |
124 | public UpdateMessageStruct deepCopy() {
125 | return new UpdateMessageStruct(this);
126 | }
127 |
128 | @Override
129 | public void clear() {
130 | setLeafNumIsSet(false);
131 | this.leafNum = 0;
132 | this.path = null;
133 | }
134 |
135 | public int getLeafNum() {
136 | return this.leafNum;
137 | }
138 |
139 | public UpdateMessageStruct setLeafNum(int leafNum) {
140 | this.leafNum = leafNum;
141 | setLeafNumIsSet(true);
142 | return this;
143 | }
144 |
145 | public void unsetLeafNum() {
146 | __isset_bitfield = org.apache.thrift.EncodingUtils.clearBit(__isset_bitfield, __LEAFNUM_ISSET_ID);
147 | }
148 |
149 | /** Returns true if field leafNum is set (has been assigned a value) and false otherwise */
150 | public boolean isSetLeafNum() {
151 | return org.apache.thrift.EncodingUtils.testBit(__isset_bitfield, __LEAFNUM_ISSET_ID);
152 | }
153 |
154 | public void setLeafNumIsSet(boolean value) {
155 | __isset_bitfield = org.apache.thrift.EncodingUtils.setBit(__isset_bitfield, __LEAFNUM_ISSET_ID, value);
156 | }
157 |
158 | public int getPathSize() {
159 | return (this.path == null) ? 0 : this.path.size();
160 | }
161 |
162 | public java.util.Iterator getPathIterator() {
163 | return (this.path == null) ? null : this.path.iterator();
164 | }
165 |
166 | public void addToPath(java.lang.String elem) {
167 | if (this.path == null) {
168 | this.path = new java.util.ArrayList();
169 | }
170 | this.path.add(elem);
171 | }
172 |
173 | public java.util.List getPath() {
174 | return this.path;
175 | }
176 |
177 | public UpdateMessageStruct setPath(java.util.List path) {
178 | this.path = path;
179 | return this;
180 | }
181 |
182 | public void unsetPath() {
183 | this.path = null;
184 | }
185 |
186 | /** Returns true if field path is set (has been assigned a value) and false otherwise */
187 | public boolean isSetPath() {
188 | return this.path != null;
189 | }
190 |
191 | public void setPathIsSet(boolean value) {
192 | if (!value) {
193 | this.path = null;
194 | }
195 | }
196 |
197 | public void setFieldValue(_Fields field, java.lang.Object value) {
198 | switch (field) {
199 | case LEAF_NUM:
200 | if (value == null) {
201 | unsetLeafNum();
202 | } else {
203 | setLeafNum((java.lang.Integer)value);
204 | }
205 | break;
206 |
207 | case PATH:
208 | if (value == null) {
209 | unsetPath();
210 | } else {
211 | setPath((java.util.List)value);
212 | }
213 | break;
214 |
215 | }
216 | }
217 |
218 | public java.lang.Object getFieldValue(_Fields field) {
219 | switch (field) {
220 | case LEAF_NUM:
221 | return getLeafNum();
222 |
223 | case PATH:
224 | return getPath();
225 |
226 | }
227 | throw new java.lang.IllegalStateException();
228 | }
229 |
230 | /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
231 | public boolean isSet(_Fields field) {
232 | if (field == null) {
233 | throw new java.lang.IllegalArgumentException();
234 | }
235 |
236 | switch (field) {
237 | case LEAF_NUM:
238 | return isSetLeafNum();
239 | case PATH:
240 | return isSetPath();
241 | }
242 | throw new java.lang.IllegalStateException();
243 | }
244 |
245 | @Override
246 | public boolean equals(java.lang.Object that) {
247 | if (that == null)
248 | return false;
249 | if (that instanceof UpdateMessageStruct)
250 | return this.equals((UpdateMessageStruct)that);
251 | return false;
252 | }
253 |
254 | public boolean equals(UpdateMessageStruct that) {
255 | if (that == null)
256 | return false;
257 | if (this == that)
258 | return true;
259 |
260 | boolean this_present_leafNum = true;
261 | boolean that_present_leafNum = true;
262 | if (this_present_leafNum || that_present_leafNum) {
263 | if (!(this_present_leafNum && that_present_leafNum))
264 | return false;
265 | if (this.leafNum != that.leafNum)
266 | return false;
267 | }
268 |
269 | boolean this_present_path = true && this.isSetPath();
270 | boolean that_present_path = true && that.isSetPath();
271 | if (this_present_path || that_present_path) {
272 | if (!(this_present_path && that_present_path))
273 | return false;
274 | if (!this.path.equals(that.path))
275 | return false;
276 | }
277 |
278 | return true;
279 | }
280 |
281 | @Override
282 | public int hashCode() {
283 | int hashCode = 1;
284 |
285 | hashCode = hashCode * 8191 + leafNum;
286 |
287 | hashCode = hashCode * 8191 + ((isSetPath()) ? 131071 : 524287);
288 | if (isSetPath())
289 | hashCode = hashCode * 8191 + path.hashCode();
290 |
291 | return hashCode;
292 | }
293 |
294 | @Override
295 | public int compareTo(UpdateMessageStruct other) {
296 | if (!getClass().equals(other.getClass())) {
297 | return getClass().getName().compareTo(other.getClass().getName());
298 | }
299 |
300 | int lastComparison = 0;
301 |
302 | lastComparison = java.lang.Boolean.valueOf(isSetLeafNum()).compareTo(other.isSetLeafNum());
303 | if (lastComparison != 0) {
304 | return lastComparison;
305 | }
306 | if (isSetLeafNum()) {
307 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.leafNum, other.leafNum);
308 | if (lastComparison != 0) {
309 | return lastComparison;
310 | }
311 | }
312 | lastComparison = java.lang.Boolean.valueOf(isSetPath()).compareTo(other.isSetPath());
313 | if (lastComparison != 0) {
314 | return lastComparison;
315 | }
316 | if (isSetPath()) {
317 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.path, other.path);
318 | if (lastComparison != 0) {
319 | return lastComparison;
320 | }
321 | }
322 | return 0;
323 | }
324 |
325 | public _Fields fieldForId(int fieldId) {
326 | return _Fields.findByThriftId(fieldId);
327 | }
328 |
329 | public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
330 | scheme(iprot).read(iprot, this);
331 | }
332 |
333 | public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
334 | scheme(oprot).write(oprot, this);
335 | }
336 |
337 | @Override
338 | public java.lang.String toString() {
339 | java.lang.StringBuilder sb = new java.lang.StringBuilder("UpdateMessageStruct(");
340 | boolean first = true;
341 |
342 | sb.append("leafNum:");
343 | sb.append(this.leafNum);
344 | first = false;
345 | if (!first) sb.append(", ");
346 | sb.append("path:");
347 | if (this.path == null) {
348 | sb.append("null");
349 | } else {
350 | sb.append(this.path);
351 | }
352 | first = false;
353 | sb.append(")");
354 | return sb.toString();
355 | }
356 |
357 | public void validate() throws org.apache.thrift.TException {
358 | // check for required fields
359 | // check for sub-struct validity
360 | }
361 |
362 | private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
363 | try {
364 | write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
365 | } catch (org.apache.thrift.TException te) {
366 | throw new java.io.IOException(te);
367 | }
368 | }
369 |
370 | private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException {
371 | try {
372 | // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
373 | __isset_bitfield = 0;
374 | read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
375 | } catch (org.apache.thrift.TException te) {
376 | throw new java.io.IOException(te);
377 | }
378 | }
379 |
380 | private static class UpdateMessageStructStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
381 | public UpdateMessageStructStandardScheme getScheme() {
382 | return new UpdateMessageStructStandardScheme();
383 | }
384 | }
385 |
386 | private static class UpdateMessageStructStandardScheme extends org.apache.thrift.scheme.StandardScheme {
387 |
388 | public void read(org.apache.thrift.protocol.TProtocol iprot, UpdateMessageStruct struct) throws org.apache.thrift.TException {
389 | org.apache.thrift.protocol.TField schemeField;
390 | iprot.readStructBegin();
391 | while (true)
392 | {
393 | schemeField = iprot.readFieldBegin();
394 | if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
395 | break;
396 | }
397 | switch (schemeField.id) {
398 | case 1: // LEAF_NUM
399 | if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
400 | struct.leafNum = iprot.readI32();
401 | struct.setLeafNumIsSet(true);
402 | } else {
403 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
404 | }
405 | break;
406 | case 2: // PATH
407 | if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
408 | {
409 | org.apache.thrift.protocol.TList _list18 = iprot.readListBegin();
410 | struct.path = new java.util.ArrayList(_list18.size);
411 | java.lang.String _elem19;
412 | for (int _i20 = 0; _i20 < _list18.size; ++_i20)
413 | {
414 | _elem19 = iprot.readString();
415 | struct.path.add(_elem19);
416 | }
417 | iprot.readListEnd();
418 | }
419 | struct.setPathIsSet(true);
420 | } else {
421 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
422 | }
423 | break;
424 | default:
425 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
426 | }
427 | iprot.readFieldEnd();
428 | }
429 | iprot.readStructEnd();
430 |
431 | // check for required fields of primitive type, which can't be checked in the validate method
432 | struct.validate();
433 | }
434 |
435 | public void write(org.apache.thrift.protocol.TProtocol oprot, UpdateMessageStruct struct) throws org.apache.thrift.TException {
436 | struct.validate();
437 |
438 | oprot.writeStructBegin(STRUCT_DESC);
439 | oprot.writeFieldBegin(LEAF_NUM_FIELD_DESC);
440 | oprot.writeI32(struct.leafNum);
441 | oprot.writeFieldEnd();
442 | if (struct.path != null) {
443 | oprot.writeFieldBegin(PATH_FIELD_DESC);
444 | {
445 | oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.path.size()));
446 | for (java.lang.String _iter21 : struct.path)
447 | {
448 | oprot.writeString(_iter21);
449 | }
450 | oprot.writeListEnd();
451 | }
452 | oprot.writeFieldEnd();
453 | }
454 | oprot.writeFieldStop();
455 | oprot.writeStructEnd();
456 | }
457 |
458 | }
459 |
460 | private static class UpdateMessageStructTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
461 | public UpdateMessageStructTupleScheme getScheme() {
462 | return new UpdateMessageStructTupleScheme();
463 | }
464 | }
465 |
466 | private static class UpdateMessageStructTupleScheme extends org.apache.thrift.scheme.TupleScheme {
467 |
468 | @Override
469 | public void write(org.apache.thrift.protocol.TProtocol prot, UpdateMessageStruct struct) throws org.apache.thrift.TException {
470 | org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
471 | java.util.BitSet optionals = new java.util.BitSet();
472 | if (struct.isSetLeafNum()) {
473 | optionals.set(0);
474 | }
475 | if (struct.isSetPath()) {
476 | optionals.set(1);
477 | }
478 | oprot.writeBitSet(optionals, 2);
479 | if (struct.isSetLeafNum()) {
480 | oprot.writeI32(struct.leafNum);
481 | }
482 | if (struct.isSetPath()) {
483 | {
484 | oprot.writeI32(struct.path.size());
485 | for (java.lang.String _iter22 : struct.path)
486 | {
487 | oprot.writeString(_iter22);
488 | }
489 | }
490 | }
491 | }
492 |
493 | @Override
494 | public void read(org.apache.thrift.protocol.TProtocol prot, UpdateMessageStruct struct) throws org.apache.thrift.TException {
495 | org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
496 | java.util.BitSet incoming = iprot.readBitSet(2);
497 | if (incoming.get(0)) {
498 | struct.leafNum = iprot.readI32();
499 | struct.setLeafNumIsSet(true);
500 | }
501 | if (incoming.get(1)) {
502 | {
503 | org.apache.thrift.protocol.TList _list23 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
504 | struct.path = new java.util.ArrayList(_list23.size);
505 | java.lang.String _elem24;
506 | for (int _i25 = 0; _i25 < _list23.size; ++_i25)
507 | {
508 | _elem24 = iprot.readString();
509 | struct.path.add(_elem24);
510 | }
511 | }
512 | struct.setPathIsSet(true);
513 | }
514 | }
515 | }
516 |
517 | private static S scheme(org.apache.thrift.protocol.TProtocol proto) {
518 | return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme();
519 | }
520 | }
521 |
522 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/tree/LeafNode.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art.tree;
10 |
11 | abstract public class LeafNode implements Node {
12 | final public int numLeaves() {
13 | return 1;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/tree/Node.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art.tree;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.art.message.thrift.NodeStruct;
12 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
13 |
14 | public interface Node {
15 | DHPubKey getPubKey();
16 | int numLeaves();
17 |
18 | static Node fromThrift(NodeStruct thrift) {
19 | if (thrift == null) {
20 | return null;
21 | }
22 | DHPubKey pubKey = DHPubKey.pubKey(thrift.getPublicKey());
23 | NodeStruct left = thrift.getLeft();
24 | NodeStruct right = thrift.getRight();
25 |
26 | if (left == null && right == null) {
27 | return new PublicLeafNode(pubKey);
28 | }
29 |
30 | return new PublicParentNode(
31 | pubKey,
32 | fromThrift(left),
33 | fromThrift(right)
34 | );
35 | }
36 |
37 | static NodeStruct toThrift(Node tree) {
38 | if (tree == null) {
39 | return null;
40 | }
41 | NodeStruct struct = new NodeStruct();
42 | struct.setPublicKey(tree.getPubKey().getPubKeyBytes());
43 | if (tree instanceof ParentNode) {
44 | struct.setLeft(Node.toThrift(((ParentNode) tree).getLeft()));
45 | struct.setRight(Node.toThrift(((ParentNode) tree).getRight()));
46 | }
47 | return struct;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/tree/ParentNode.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art.tree;
10 |
11 | abstract public class ParentNode implements Node {
12 | protected Node left;
13 | protected Node right;
14 |
15 | public int numLeaves() {
16 | return left.numLeaves() + right.numLeaves();
17 | }
18 |
19 | public Node getLeft() {
20 | return left;
21 | }
22 |
23 | public Node getRight() {
24 | return right;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/tree/PublicLeafNode.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art.tree;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
12 |
13 | public class PublicLeafNode extends LeafNode {
14 | private DHPubKey pubKey;
15 |
16 | public PublicLeafNode(DHPubKey pubKey) {
17 | this.pubKey = pubKey;
18 | }
19 |
20 | public DHPubKey getPubKey() {
21 | return pubKey;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/tree/PublicParentNode.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art.tree;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
12 |
13 | public class PublicParentNode extends ParentNode {
14 | private DHPubKey pubKey;
15 |
16 | public PublicParentNode(DHPubKey pubKey, Node left, Node right) {
17 | this.pubKey = pubKey;
18 | this.left = left;
19 | this.right = right;
20 | }
21 |
22 | public DHPubKey getPubKey() {
23 | return pubKey;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/tree/SecretLeafNode.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art.tree;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
12 | import com.facebook.research.asynchronousratchetingtree.crypto.DHKeyPair;
13 |
14 | final public class SecretLeafNode extends LeafNode implements SecretNode {
15 | private DHKeyPair keyPair;
16 |
17 | public SecretLeafNode(DHKeyPair keyPair) {
18 | this.keyPair = keyPair;
19 | }
20 |
21 | public DHPubKey getPubKey() {
22 | return keyPair.getPubKey();
23 | }
24 |
25 | public DHKeyPair getKeyPair() {
26 | return keyPair;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/tree/SecretNode.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art.tree;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.crypto.DHKeyPair;
12 |
13 | public interface SecretNode extends Node {
14 | public DHKeyPair getKeyPair();
15 | }
16 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/art/tree/SecretParentNode.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.art.tree;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.crypto.Crypto;
12 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
13 | import com.facebook.research.asynchronousratchetingtree.crypto.DHKeyPair;
14 |
15 | public class SecretParentNode extends ParentNode implements SecretNode {
16 | private DHKeyPair keyPair;
17 |
18 | public SecretParentNode(SecretNode left, Node right) {
19 | this.left = left;
20 | this.right = right;
21 | byte[] dhOutput = left.getKeyPair().exchange(right.getPubKey());
22 | // Derive both a private ECDH key and an AES-128 encryption key.
23 | byte[] key = Crypto.hkdf(dhOutput, new byte[0], new byte[0], 32);
24 |
25 | keyPair = DHKeyPair.fromBytes(key, false);
26 | }
27 |
28 | public SecretParentNode(Node left, SecretNode right) {
29 | this.left = left;
30 | this.right = right;
31 | this.keyPair = DHKeyPair.fromBytes(right.getKeyPair().exchange(left.getPubKey()), false);
32 | byte[] dhOutput = right.getKeyPair().exchange(left.getPubKey());
33 | // Derive both a private ECDH key and an AES-128 encryption key.
34 | byte[] key = Crypto.hkdf(dhOutput, new byte[0], new byte[0], 32);
35 |
36 | keyPair = DHKeyPair.fromBytes(key, false);
37 | }
38 |
39 | public DHPubKey getPubKey() {
40 | return keyPair.getPubKey();
41 | }
42 |
43 | public DHKeyPair getKeyPair() {
44 | return keyPair;
45 | }
46 |
47 | public byte[] getRawSecretKey() {
48 | return keyPair.getPrivKeyBytes();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/crypto/Crypto.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.crypto;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.Utils;
12 | import com.facebook.research.asynchronousratchetingtree.art.tree.Node;
13 | import djb.Curve25519;
14 |
15 | import javax.crypto.Cipher;
16 | import javax.crypto.Mac;
17 | import javax.crypto.spec.GCMParameterSpec;
18 | import javax.crypto.spec.SecretKeySpec;
19 | import java.security.Key;
20 | import java.security.MessageDigest;
21 | import java.security.NoSuchAlgorithmException;
22 | import java.security.SecureRandom;
23 | import java.util.Arrays;
24 |
25 | /**
26 | * This crypto class is put together simply to make coding the rest of the example program easier. Please never actually
27 | * use it in production.
28 | */
29 | public class Crypto {
30 | final public static int HASH_LENGTH = 32;
31 |
32 | public static MessageDigest startSHA256() {
33 | MessageDigest md;
34 | try {
35 | md = MessageDigest.getInstance("SHA-256");
36 | } catch (NoSuchAlgorithmException e) {
37 | throw Utils.except(e);
38 | }
39 | return md;
40 | }
41 |
42 | public static byte[] hmacSha256(byte[] data, byte[] key) {
43 | Mac mac;
44 | try {
45 | mac = Mac.getInstance("HmacSHA256");
46 | mac.init(new SecretKeySpec(key, "HmacSHA256"));
47 | } catch (Exception e) {
48 | throw Utils.except(e);
49 | }
50 | mac.update(data);
51 | return mac.doFinal();
52 | }
53 |
54 | public static byte[] hkdf(byte[] input_keying_material, byte[] salt, byte[] info, int num_bytes) {
55 | // Extract step
56 | byte[] pseudo_random_key = hmacSha256(salt, input_keying_material);
57 |
58 | // Expand step
59 | byte[] output_bytes = new byte[num_bytes];
60 | byte[] t = new byte[0];
61 | for (byte i = 0; i < (num_bytes + 31) / 32; i++) {
62 | byte[] tInput = new byte[t.length + info.length + 1];
63 | System.arraycopy(t, 0, tInput, 0, t.length);
64 | System.arraycopy(info, 0, tInput, t.length, info.length);
65 | tInput[tInput.length - 1] = i;
66 |
67 | t = hmacSha256(pseudo_random_key, tInput);
68 | int num_to_copy = num_bytes - (i * 32);
69 | if (num_to_copy > 32) {
70 | num_to_copy = 32;
71 | }
72 |
73 | System.arraycopy(t, 0, output_bytes, i * 32, num_to_copy);
74 | }
75 | return output_bytes;
76 | }
77 |
78 | public static byte[] artKDF(
79 | byte[] lastStageKey,
80 | byte[] treeKey,
81 | DHPubKey[] identities,
82 | Node tree
83 | ) {
84 | byte[] serialisedTree = Utils.serialise(Node.toThrift(tree));
85 | byte[] ikm = new byte[lastStageKey.length + treeKey.length + serialisedTree.length];
86 | System.arraycopy(lastStageKey, 0, ikm, 0, lastStageKey.length);
87 | System.arraycopy(treeKey, 0, ikm, lastStageKey.length, treeKey.length);
88 | System.arraycopy(serialisedTree, 0, ikm, lastStageKey.length + treeKey.length, serialisedTree.length);
89 |
90 | byte[] info = new byte[identities.length * Curve25519.KEY_SIZE];
91 | for (int i = 0; i < identities.length; i++) {
92 | System.arraycopy(identities[i].getPubKeyBytes(), 0, info, i * Curve25519.KEY_SIZE, Curve25519.KEY_SIZE);
93 | }
94 | return hkdf(ikm, new byte[0], info, 16);
95 | }
96 |
97 | public static byte[] randomBytes(int n) {
98 | byte[] result = new byte[n];
99 | SecureRandom rng = new SecureRandom();
100 | rng.nextBytes(result);
101 | return result;
102 | }
103 |
104 | public static byte[] encrypt(byte[] message, byte[] keyBytes) {
105 | Cipher cipher;
106 | Key key;
107 | try {
108 | cipher = Cipher.getInstance("AES/GCM/NoPadding");
109 | byte[] nonce = randomBytes(12);
110 | GCMParameterSpec paramSpec = new GCMParameterSpec(16 * 8, nonce);
111 |
112 | key = new SecretKeySpec(keyBytes, "AES");
113 | cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
114 |
115 | int len = cipher.getOutputSize(message.length);
116 | byte[] result = new byte[len + 12];
117 | System.arraycopy(nonce, 0, result, 0, 12);
118 |
119 | cipher.doFinal(
120 | message,
121 | 0,
122 | message.length,
123 | result,
124 | 12
125 | );
126 | return result;
127 | } catch (Exception e) {
128 | throw Utils.except(e);
129 | }
130 | }
131 |
132 | public static byte[] decrypt(byte[] encrypted, byte[] keyBytes) {
133 | Cipher cipher;
134 | Key key;
135 | try {
136 | cipher = Cipher.getInstance("AES/GCM/NoPadding");
137 |
138 | byte[] nonce = Arrays.copyOfRange(encrypted, 0, 12);
139 | byte[] ciphertext = Arrays.copyOfRange(encrypted, 12, encrypted.length);
140 | GCMParameterSpec paramSpec = new GCMParameterSpec(16 * 8, nonce);
141 |
142 | key = new SecretKeySpec(keyBytes, "AES");
143 | cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
144 |
145 | return cipher.doFinal(ciphertext);
146 | } catch (Exception e) {
147 | throw Utils.except(e);
148 | }
149 | }
150 |
151 | public static byte[] keyExchangeInitiate(
152 | DHKeyPair selfIdentity,
153 | DHPubKey remoteIdentity,
154 | DHKeyPair keyExchangeKeyPair,
155 | DHPubKey remoteEphemeralKey
156 | ) {
157 | MessageDigest md = Crypto.startSHA256();
158 | md.update(selfIdentity.exchange(remoteIdentity));
159 | md.update(selfIdentity.exchange(remoteEphemeralKey));
160 | md.update(keyExchangeKeyPair.exchange(remoteIdentity));
161 | md.update(keyExchangeKeyPair.exchange(remoteEphemeralKey));
162 | return md.digest();
163 | }
164 |
165 | public static byte[] keyExchangeReceive(
166 | DHKeyPair selfIdentity,
167 | DHPubKey remoteIdentity,
168 | DHKeyPair ephemeralKey,
169 | DHPubKey keyExchangeKey
170 | ) {
171 | MessageDigest md = Crypto.startSHA256();
172 | md.update(selfIdentity.exchange(remoteIdentity));
173 | md.update(ephemeralKey.exchange(remoteIdentity));
174 | md.update(selfIdentity.exchange(keyExchangeKey));
175 | md.update(ephemeralKey.exchange(keyExchangeKey));
176 | return md.digest();
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/crypto/DHKeyPair.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.crypto;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.Utils;
12 | import djb.Curve25519;
13 |
14 | import java.security.MessageDigest;
15 |
16 | public class DHKeyPair extends DHPubKey {
17 | private byte[] priv;
18 | private byte[] privSign;
19 |
20 | protected DHKeyPair(byte[] pub, byte[] priv, byte[] privSign) {
21 | super(pub);
22 | this.priv = priv;
23 | this.privSign = privSign;
24 | }
25 |
26 | public static DHKeyPair generate(boolean allowSignatures) {
27 | return DHKeyPair.fromBytes(Crypto.randomBytes(Curve25519.KEY_SIZE), allowSignatures);
28 | }
29 |
30 | public static DHKeyPair fromBytes(byte[] priv, boolean allowSignatures) {
31 | byte[] pub = new byte[Curve25519.KEY_SIZE];
32 | byte[] privSign;
33 | if (allowSignatures) {
34 | privSign = new byte[Curve25519.KEY_SIZE];
35 | Curve25519.keygen(pub, privSign, priv);
36 | } else {
37 | privSign = null;
38 | Curve25519.keygen(pub, null, priv);
39 | }
40 | return new DHKeyPair(pub, priv, privSign);
41 | }
42 |
43 | public byte[] getPrivKeyBytes() {
44 | return priv;
45 | }
46 |
47 | public DHPubKey getPubKey() {
48 | return pubKey(getPubKeyBytes());
49 | }
50 |
51 | public byte[] exchange(DHPubKey bob) {
52 | byte[] result = new byte[Curve25519.KEY_SIZE];
53 | Curve25519.curve(result, getPrivKeyBytes(), bob.getPubKeyBytes());
54 | return result;
55 | }
56 |
57 | /**
58 | * The Curve25519 library that we use implements KCDSA. The API provided accepts the first curve point
59 | * as an argument, and returns the second part of the signature. The first part is a hash of the public
60 | * curve point, so we append this ourselves.
61 | * In DHPubKey, we then verify signatures by hashing the input data similarly, and checking that the
62 | * output of the verification method equals the first part of the signature.
63 | * http://grouper.ieee.org/groups/1363/P1363a/contributions/kcdsa1363.pdf
64 | */
65 | public byte[] sign(byte[] data) {
66 | if (privSign == null) {
67 | Utils.except("Non-signing key cannot be used for signing.");
68 | }
69 | boolean success = false;
70 | byte[] sig_second_part = new byte[0];
71 | byte[] sig_first_part = new byte[0];
72 |
73 | // Signature generation can fail, in which case we need to try a different Curve point.
74 | while (!success) {
75 | byte[] privCurvePoint = Crypto.randomBytes(Curve25519.KEY_SIZE);
76 | byte[] pubCurvePoint = new byte[Curve25519.KEY_SIZE];
77 | Curve25519.keygen(pubCurvePoint, null, privCurvePoint);
78 | sig_first_part = Crypto.startSHA256().digest(pubCurvePoint);
79 |
80 | MessageDigest md = Crypto.startSHA256();
81 | md.update(data);
82 | md.update(getPubKeyBytes());
83 | byte[] digest = md.digest();
84 |
85 | sig_second_part = new byte[Curve25519.KEY_SIZE];
86 | success = Curve25519.sign(
87 | sig_second_part,
88 | digest,
89 | privCurvePoint,
90 | privSign
91 | );
92 | }
93 |
94 | byte[] sig = new byte[Crypto.HASH_LENGTH + Curve25519.KEY_SIZE];
95 | System.arraycopy(sig_first_part, 0, sig, 0, Crypto.HASH_LENGTH);
96 | System.arraycopy(sig_second_part, 0, sig, Crypto.HASH_LENGTH, Curve25519.KEY_SIZE);
97 |
98 | return sig;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/crypto/DHPubKey.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.crypto;
10 |
11 | import djb.Curve25519;
12 |
13 | import java.security.MessageDigest;
14 | import java.util.Arrays;
15 |
16 | public class DHPubKey {
17 | private byte[] pub;
18 |
19 | protected DHPubKey(byte[] pub) {
20 | this.pub = pub;
21 | }
22 |
23 | public static DHPubKey pubKey(byte[] pub) {
24 | if (pub == null || pub.length == 0) {
25 | return null;
26 | }
27 | return new DHPubKey(pub);
28 | }
29 |
30 | public byte[] getPubKeyBytes() {
31 | return pub;
32 | }
33 |
34 | public boolean verify(byte[] data, byte[] sig) {
35 | byte[] sig_first_part = Arrays.copyOfRange(sig, 0, Crypto.HASH_LENGTH);
36 | byte[] sig_second_part = Arrays.copyOfRange(sig, Crypto.HASH_LENGTH, sig.length);
37 |
38 | MessageDigest md = Crypto.startSHA256();
39 | md.update(data);
40 | md.update(getPubKeyBytes());
41 | byte[] digest = md.digest();
42 |
43 | byte[] output = new byte[Curve25519.KEY_SIZE];
44 | Curve25519.verify(
45 | output,
46 | sig_second_part,
47 | digest,
48 | getPubKeyBytes()
49 | );
50 |
51 | return Arrays.equals(
52 | Crypto.startSHA256().digest(output),
53 | sig_first_part
54 | );
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/crypto/SignedDHPubKey.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.crypto;
10 |
11 | public class SignedDHPubKey extends DHPubKey {
12 | private byte[] signature;
13 |
14 | public SignedDHPubKey(byte[] pubKey, byte[] signature) {
15 | super(pubKey);
16 | this.signature = signature;
17 | }
18 |
19 | public byte[] getSignature() {
20 | return signature;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/dhratchet/DHRatchet.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.dhratchet;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.KeyServer;
12 | import com.facebook.research.asynchronousratchetingtree.GroupMessagingTestImplementation;
13 | import com.facebook.research.asynchronousratchetingtree.MessageDistributer;
14 | import com.facebook.research.asynchronousratchetingtree.Utils;
15 | import com.facebook.research.asynchronousratchetingtree.crypto.Crypto;
16 | import com.facebook.research.asynchronousratchetingtree.crypto.DHKeyPair;
17 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
18 | import com.facebook.research.asynchronousratchetingtree.crypto.SignedDHPubKey;
19 | import com.facebook.research.asynchronousratchetingtree.dhratchet.message.DHRatchetMessageDistributer;
20 | import com.facebook.research.asynchronousratchetingtree.dhratchet.message.DHRatchetSetupMessage;
21 | import com.facebook.research.asynchronousratchetingtree.dhratchet.message.DHRatchetMessage;
22 |
23 | public class DHRatchet implements GroupMessagingTestImplementation {
24 | @Override
25 | public byte[] setupMessageForPeer(DHRatchetState state, DHPubKey[] peers, KeyServer keyServer, int i) {
26 | DHKeyPair identityKeyPair = state.getIdentityKeyPair();
27 |
28 | SignedDHPubKey signedPreKey = keyServer.getSignedPreKey(state, i);
29 | if (!peers[i].verify(signedPreKey.getPubKeyBytes(), signedPreKey.getSignature())) {
30 | Utils.except("PreKey signature check failed.");
31 | }
32 |
33 | DHKeyPair ratchetKey = DHKeyPair.generate(false);
34 | state.setRootKey(
35 | i,
36 | Crypto.keyExchangeInitiate(
37 | identityKeyPair,
38 | peers[i],
39 | ratchetKey,
40 | keyServer.getSignedPreKey(state, i)
41 | )
42 | );
43 | state.setSelfRatchetKey(i, ratchetKey);
44 | state.setRatchetFlag(i, false);
45 | state.setIsSetup(i);
46 |
47 | DHRatchetSetupMessage setupMessage = new DHRatchetSetupMessage(
48 | state.getPeerNum(),
49 | identityKeyPair.getPubKey(),
50 | ratchetKey.getPubKey()
51 | );
52 | return setupMessage.serialise();
53 | }
54 |
55 | @Override
56 | public void processSetupMessage(DHRatchetState state, byte[] serialisedMessage, int participantNum) {
57 | DHRatchetSetupMessage message = new DHRatchetSetupMessage(serialisedMessage);
58 | int peerNum = message.getPeerNum();
59 | state.setRootKey(
60 | peerNum,
61 | Crypto.keyExchangeReceive(
62 | state.getIdentityKeyPair(),
63 | message.getIdentity(),
64 | state.getPreKeyFor(peerNum),
65 | message.getEphemeralKey()
66 | )
67 | );
68 | state.setRemoteRatchetKey(peerNum, message.getEphemeralKey());
69 | state.setRatchetFlag(peerNum, true);
70 | state.setIsSetup(peerNum);
71 | }
72 |
73 | @Override
74 | public MessageDistributer sendMessage(DHRatchetState state, byte[] plaintext) {
75 | byte[][] messages = new byte[state.getPeerCount()][];
76 | for (int i = 0; i < state.getPeerCount(); i++) {
77 | if (i == state.getPeerNum()) {
78 | continue;
79 | }
80 | byte[] rootKey = state.getRootKey(i);
81 | if (state.getRatchetFlag(i)) {
82 | DHKeyPair selfRatchetKey = DHKeyPair.generate(false);
83 | state.setSelfRatchetKey(i, selfRatchetKey);
84 | rootKey = Crypto.hmacSha256(
85 | rootKey,
86 | selfRatchetKey.exchange(state.getRemoteRatchetKey(i))
87 | );
88 | state.setRootKey(i, rootKey);
89 | state.setRatchetFlag(i, false);
90 | }
91 |
92 | byte[] ciphertext = Crypto.encrypt(plaintext, rootKey);
93 | DHRatchetMessage message = new DHRatchetMessage(
94 | state.getPeerNum(),
95 | state.getSelfRatchetKey(i).getPubKey(),
96 | ciphertext
97 | );
98 | messages[i] = message.serialise();
99 | }
100 | return new DHRatchetMessageDistributer(messages);
101 | }
102 |
103 | @Override
104 | public byte[] receiveMessage(DHRatchetState state, byte[] serialisedMessage) {
105 | DHRatchetMessage message = new DHRatchetMessage(serialisedMessage);
106 | int i = message.getPeerNum();
107 | byte[] rootKey = state.getRootKey(i);
108 |
109 | if (!state.getRatchetFlag(i)) {
110 | DHKeyPair selfRatchetKey = state.getSelfRatchetKey(i);
111 | DHPubKey remoteRatchetKey = message.getRatchetKey();
112 |
113 | rootKey = Crypto.hmacSha256(
114 | rootKey,
115 | selfRatchetKey.exchange(remoteRatchetKey)
116 | );
117 | state.setRootKey(i, rootKey);
118 | state.setRemoteRatchetKey(
119 | i,
120 | remoteRatchetKey
121 | );
122 | state.setRatchetFlag(i, true);
123 | }
124 |
125 | return Crypto.decrypt(message.getCiphertext(), rootKey);
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/dhratchet/DHRatchetSetupPhase.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.dhratchet;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.GroupMessagingSetupPhase;
12 | import com.facebook.research.asynchronousratchetingtree.GroupMessagingTestImplementation;
13 | import com.facebook.research.asynchronousratchetingtree.KeyServer;
14 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
15 |
16 | public class DHRatchetSetupPhase implements GroupMessagingSetupPhase {
17 | private byte[][] setupMessages;
18 | private int bytesReceivedByOthers = 0;
19 | private int bytesSentByOthers = 0;
20 |
21 | @Override
22 | public void generateNecessaryPreKeys(DHRatchetState[] states) {
23 | // We need PreKeys from each user to each user with a lower ID than them.
24 | for (int i = 0; i < states.length; i++) {
25 | for (int j = i + 1; j < states.length; j++) {
26 | states[j].getSignedDHPreKeyFor(i);
27 | }
28 | }
29 | }
30 |
31 | @Override
32 | public void setupInitiator(GroupMessagingTestImplementation implementation, DHRatchetState[] states, DHPubKey[] identities, KeyServer keyServer) {
33 | int n = states.length;
34 | setupMessages = new byte[n][];
35 | for (int i = 1; i < n; i++) {
36 | setupMessages[i] = implementation.setupMessageForPeer(states[0], identities, keyServer, i);
37 | }
38 | }
39 |
40 | @Override
41 | public int getBytesSentByInitiator() {
42 | int total = 0;
43 | for (int i = 1; i < setupMessages.length; i++) {
44 | total += setupMessages[i].length;
45 | }
46 | return total;
47 | }
48 |
49 | /**
50 | * Here we aim to scale the total number of key exchanges performed proportionate to the number of active users.
51 | * This involves ensuring that every active user has done a key exchange for each of the others, and that they have
52 | * all done an unreciprocated key exchange with all other users.
53 | */
54 | @Override
55 | public void setupAllOthers(GroupMessagingTestImplementation implementation, DHRatchetState[] states, Integer[] active, DHPubKey[] identities, KeyServer keyServer) {
56 | int n = states.length;
57 |
58 | // We need all active users to create and import each others' setup messages.
59 | for (int i = 0; i < active.length; i++) {
60 | int sender = active[i];
61 | if (sender == 0) {
62 | continue;
63 | }
64 | // First let's import the initiator's state.
65 | bytesReceivedByOthers += setupMessages[sender].length;
66 | implementation.processSetupMessage(states[sender], setupMessages[sender], sender);
67 |
68 | for (int j = i + 1; j < active.length; j++) {
69 | int receiver = active[j];
70 | if (receiver == 0) {
71 | continue;
72 | }
73 | byte[] setupMessage = implementation.setupMessageForPeer(states[sender], identities, keyServer, receiver);
74 | bytesSentByOthers += setupMessage.length;
75 | bytesReceivedByOthers += setupMessage.length;
76 | implementation.processSetupMessage(states[receiver], setupMessage, receiver);
77 | }
78 | }
79 |
80 | // Active users should still create state for inactive ones, it just shouldn't be imported.
81 | for (int i = 0; i < active.length; i++) {
82 | int sender = active[i];
83 | for (int j = 0; j < n; j++) {
84 | if (states[sender].getIsSetup(j)) {
85 | continue;
86 | }
87 | byte[] setupMessage = implementation.setupMessageForPeer(states[sender], identities, keyServer, j);
88 | bytesSentByOthers += setupMessage.length;
89 | bytesReceivedByOthers += setupMessage.length;
90 | implementation.processSetupMessage(states[j], setupMessage, j);
91 | }
92 | }
93 | }
94 |
95 | @Override
96 | public int getBytesSentByOthers() {
97 | return bytesSentByOthers;
98 | }
99 |
100 | @Override
101 | public int getBytesReceivedByOthers() {
102 | return bytesReceivedByOthers;
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/dhratchet/DHRatchetState.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.dhratchet;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.GroupMessagingState;
12 | import com.facebook.research.asynchronousratchetingtree.crypto.Crypto;
13 | import com.facebook.research.asynchronousratchetingtree.crypto.DHKeyPair;
14 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
15 |
16 | public class DHRatchetState extends GroupMessagingState {
17 | private byte[][] rootKeys;
18 | private DHKeyPair[] selfRatchetKeys;
19 | private DHPubKey[] remoteRatchetKeys;
20 | private boolean[] ratchetFlags;
21 | private boolean[] isSetup;
22 |
23 | public DHRatchetState(int peerNum, int peerCount) {
24 | super(peerNum, peerCount);
25 | rootKeys = new byte[peerCount][];
26 | selfRatchetKeys = new DHKeyPair[peerCount];
27 | remoteRatchetKeys = new DHPubKey[peerCount];
28 | ratchetFlags = new boolean[peerCount];
29 | isSetup = new boolean[peerCount];
30 | }
31 |
32 | public void setRootKey(int i, byte[] rootKey) {
33 | rootKeys[i] = rootKey;
34 | }
35 |
36 | public byte[] getRootKey(int i) {
37 | return rootKeys[i];
38 | }
39 |
40 | public void setSelfRatchetKey(int i, DHKeyPair ratchetKey) {
41 | selfRatchetKeys[i] = ratchetKey;
42 | }
43 |
44 | public DHKeyPair getSelfRatchetKey(int i) {
45 | return selfRatchetKeys[i];
46 | }
47 |
48 | public void setRemoteRatchetKey(int i, DHPubKey ratchetKey) {
49 | remoteRatchetKeys[i] = ratchetKey;
50 | }
51 |
52 | public DHPubKey getRemoteRatchetKey(int i) {
53 | return remoteRatchetKeys[i];
54 | }
55 |
56 | public void setRatchetFlag(int i, boolean flag) {
57 | ratchetFlags[i] = flag;
58 | }
59 |
60 | public boolean getRatchetFlag(int i) {
61 | return ratchetFlags[i];
62 | }
63 |
64 | public byte[] getKeyWithPeer(int n) {
65 | return Crypto.hkdf(rootKeys[n], new byte[0], new byte[0], 16);
66 | }
67 |
68 | public void setIsSetup(int i) {
69 | isSetup[i] = true;
70 | }
71 |
72 | public boolean getIsSetup(int i) {
73 | return isSetup[i];
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/dhratchet/message/DHRatchetMessage.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.dhratchet.message;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.Utils;
12 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
13 | import com.facebook.research.asynchronousratchetingtree.dhratchet.message.thrift.DHRatchetMessageStruct;
14 |
15 | public class DHRatchetMessage {
16 | private int peerNum;
17 | private DHPubKey ratchetKey;
18 | private byte[] ciphertext;
19 |
20 | public DHRatchetMessage(
21 | int peerNum,
22 | DHPubKey ratchetKey,
23 | byte[] ciphertext
24 | ) {
25 | this.peerNum = peerNum;
26 | this.ratchetKey = ratchetKey;
27 | this.ciphertext = ciphertext;
28 | }
29 |
30 | public DHRatchetMessage(byte[] thriftSerialised) {
31 | DHRatchetMessageStruct struct = new DHRatchetMessageStruct();
32 | Utils.deserialise(struct, thriftSerialised);
33 | peerNum = struct.peerNum;
34 | ratchetKey = DHPubKey.pubKey(struct.getRatchetKey());
35 | ciphertext = struct.getCiphertext();
36 | }
37 |
38 | public int getPeerNum() {
39 | return peerNum;
40 | }
41 |
42 | public DHPubKey getRatchetKey() {
43 | return ratchetKey;
44 | }
45 |
46 | public byte[] getCiphertext() {
47 | return ciphertext;
48 | }
49 |
50 | public byte[] serialise() {
51 | DHRatchetMessageStruct struct = new DHRatchetMessageStruct();
52 | struct.setPeerNum(peerNum);
53 | struct.setRatchetKey(ratchetKey.getPubKeyBytes());
54 | struct.setCiphertext(ciphertext);
55 | return Utils.serialise(struct);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/dhratchet/message/DHRatchetMessageDistributer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.dhratchet.message;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.MessageDistributer;
12 |
13 | public class DHRatchetMessageDistributer implements MessageDistributer {
14 | private byte[][] updateMessages;
15 |
16 | public DHRatchetMessageDistributer(byte[][] updateMessages) {
17 | this.updateMessages = updateMessages;
18 | }
19 |
20 | @Override
21 | public byte[] getUpdateMessageForParticipantNum(int participantNum) {
22 | return updateMessages[participantNum];
23 | }
24 |
25 | @Override
26 | public int totalSize() {
27 | int size = 0;
28 | for (int i = 0; i < updateMessages.length; i++) {
29 | if (updateMessages[i] == null) {
30 | continue;
31 | }
32 | size += updateMessages[i].length;
33 | }
34 | return size;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/dhratchet/message/DHRatchetSetupMessage.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the license found in the
6 | * LICENSE file in the root directory of this source tree.
7 | */
8 |
9 | package com.facebook.research.asynchronousratchetingtree.dhratchet.message;
10 |
11 | import com.facebook.research.asynchronousratchetingtree.Utils;
12 | import com.facebook.research.asynchronousratchetingtree.crypto.DHPubKey;
13 | import com.facebook.research.asynchronousratchetingtree.dhratchet.message.thrift.DHRatchetSetupMessageStruct;
14 |
15 | public class DHRatchetSetupMessage {
16 | private int peerNum;
17 | private DHPubKey identity;
18 | private DHPubKey ephemeralKey;
19 |
20 | public DHRatchetSetupMessage(
21 | int peerNum,
22 | DHPubKey identity,
23 | DHPubKey ephemeralKey
24 | ) {
25 | this.peerNum = peerNum;
26 | this.identity = identity;
27 | this.ephemeralKey = ephemeralKey;
28 | }
29 |
30 | public DHRatchetSetupMessage(byte[] thriftSerialised) {
31 | DHRatchetSetupMessageStruct struct = new DHRatchetSetupMessageStruct();
32 | Utils.deserialise(struct, thriftSerialised);
33 | peerNum = struct.getPeerNum();
34 | identity = DHPubKey.pubKey(struct.getIdentityKey());
35 | ephemeralKey = DHPubKey.pubKey(struct.getEphemeralKey());
36 | }
37 |
38 | public int getPeerNum() {
39 | return peerNum;
40 | }
41 |
42 | public DHPubKey getIdentity() {
43 | return identity;
44 | }
45 |
46 | public DHPubKey getEphemeralKey() {
47 | return ephemeralKey;
48 | }
49 |
50 | public byte[] serialise() {
51 | DHRatchetSetupMessageStruct struct = new DHRatchetSetupMessageStruct();
52 | struct.setPeerNum(peerNum);
53 | struct.setIdentityKey(identity.getPubKeyBytes());
54 | struct.setEphemeralKey(ephemeralKey.getPubKeyBytes());
55 | return Utils.serialise(struct);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/dhratchet/message/thrift/DHRatchet.thrift:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017-present, Facebook, Inc.
2 | # All rights reserved.
3 | #
4 | # This source code is licensed under the license found in the
5 | # LICENSE file in the root directory of this source tree.
6 | #
7 | # Compile this file using the Thrift compiler, from the current directory, with the following command:
8 | # thrift -r --gen java -out ../../../../../../../ DHRatchet.thrift
9 |
10 | namespace java com.facebook.research.asynchronousratchetingtree.dhratchet.message.thrift
11 |
12 | struct DHRatchetSetupMessageStruct {
13 | 1: i32 peerNum,
14 | 2: binary identityKey,
15 | 3: binary ephemeralKey,
16 | }
17 |
18 | struct DHRatchetMessageStruct {
19 | 1: i32 peerNum,
20 | 2: binary ratchetKey,
21 | 3: binary ciphertext,
22 | }
23 |
--------------------------------------------------------------------------------
/AsynchronousRatchetingTree/src/main/java/com/facebook/research/asynchronousratchetingtree/dhratchet/message/thrift/DHRatchetMessageStruct.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Autogenerated by Thrift Compiler (0.10.0)
3 | *
4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
5 | * @generated
6 | */
7 | package com.facebook.research.asynchronousratchetingtree.dhratchet.message.thrift;
8 |
9 | @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
10 | @javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)", date = "2018-01-05")
11 | public class DHRatchetMessageStruct implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable {
12 | private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("DHRatchetMessageStruct");
13 |
14 | private static final org.apache.thrift.protocol.TField PEER_NUM_FIELD_DESC = new org.apache.thrift.protocol.TField("peerNum", org.apache.thrift.protocol.TType.I32, (short)1);
15 | private static final org.apache.thrift.protocol.TField RATCHET_KEY_FIELD_DESC = new org.apache.thrift.protocol.TField("ratchetKey", org.apache.thrift.protocol.TType.STRING, (short)2);
16 | private static final org.apache.thrift.protocol.TField CIPHERTEXT_FIELD_DESC = new org.apache.thrift.protocol.TField("ciphertext", org.apache.thrift.protocol.TType.STRING, (short)3);
17 |
18 | private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new DHRatchetMessageStructStandardSchemeFactory();
19 | private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new DHRatchetMessageStructTupleSchemeFactory();
20 |
21 | public int peerNum; // required
22 | public java.nio.ByteBuffer ratchetKey; // required
23 | public java.nio.ByteBuffer ciphertext; // required
24 |
25 | /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
26 | public enum _Fields implements org.apache.thrift.TFieldIdEnum {
27 | PEER_NUM((short)1, "peerNum"),
28 | RATCHET_KEY((short)2, "ratchetKey"),
29 | CIPHERTEXT((short)3, "ciphertext");
30 |
31 | private static final java.util.Map byName = new java.util.HashMap();
32 |
33 | static {
34 | for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
35 | byName.put(field.getFieldName(), field);
36 | }
37 | }
38 |
39 | /**
40 | * Find the _Fields constant that matches fieldId, or null if its not found.
41 | */
42 | public static _Fields findByThriftId(int fieldId) {
43 | switch(fieldId) {
44 | case 1: // PEER_NUM
45 | return PEER_NUM;
46 | case 2: // RATCHET_KEY
47 | return RATCHET_KEY;
48 | case 3: // CIPHERTEXT
49 | return CIPHERTEXT;
50 | default:
51 | return null;
52 | }
53 | }
54 |
55 | /**
56 | * Find the _Fields constant that matches fieldId, throwing an exception
57 | * if it is not found.
58 | */
59 | public static _Fields findByThriftIdOrThrow(int fieldId) {
60 | _Fields fields = findByThriftId(fieldId);
61 | if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!");
62 | return fields;
63 | }
64 |
65 | /**
66 | * Find the _Fields constant that matches name, or null if its not found.
67 | */
68 | public static _Fields findByName(java.lang.String name) {
69 | return byName.get(name);
70 | }
71 |
72 | private final short _thriftId;
73 | private final java.lang.String _fieldName;
74 |
75 | _Fields(short thriftId, java.lang.String fieldName) {
76 | _thriftId = thriftId;
77 | _fieldName = fieldName;
78 | }
79 |
80 | public short getThriftFieldId() {
81 | return _thriftId;
82 | }
83 |
84 | public java.lang.String getFieldName() {
85 | return _fieldName;
86 | }
87 | }
88 |
89 | // isset id assignments
90 | private static final int __PEERNUM_ISSET_ID = 0;
91 | private byte __isset_bitfield = 0;
92 | public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
93 | static {
94 | java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
95 | tmpMap.put(_Fields.PEER_NUM, new org.apache.thrift.meta_data.FieldMetaData("peerNum", org.apache.thrift.TFieldRequirementType.DEFAULT,
96 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
97 | tmpMap.put(_Fields.RATCHET_KEY, new org.apache.thrift.meta_data.FieldMetaData("ratchetKey", org.apache.thrift.TFieldRequirementType.DEFAULT,
98 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING , true)));
99 | tmpMap.put(_Fields.CIPHERTEXT, new org.apache.thrift.meta_data.FieldMetaData("ciphertext", org.apache.thrift.TFieldRequirementType.DEFAULT,
100 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING , true)));
101 | metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
102 | org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(DHRatchetMessageStruct.class, metaDataMap);
103 | }
104 |
105 | public DHRatchetMessageStruct() {
106 | }
107 |
108 | public DHRatchetMessageStruct(
109 | int peerNum,
110 | java.nio.ByteBuffer ratchetKey,
111 | java.nio.ByteBuffer ciphertext)
112 | {
113 | this();
114 | this.peerNum = peerNum;
115 | setPeerNumIsSet(true);
116 | this.ratchetKey = org.apache.thrift.TBaseHelper.copyBinary(ratchetKey);
117 | this.ciphertext = org.apache.thrift.TBaseHelper.copyBinary(ciphertext);
118 | }
119 |
120 | /**
121 | * Performs a deep copy on other.
122 | */
123 | public DHRatchetMessageStruct(DHRatchetMessageStruct other) {
124 | __isset_bitfield = other.__isset_bitfield;
125 | this.peerNum = other.peerNum;
126 | if (other.isSetRatchetKey()) {
127 | this.ratchetKey = org.apache.thrift.TBaseHelper.copyBinary(other.ratchetKey);
128 | }
129 | if (other.isSetCiphertext()) {
130 | this.ciphertext = org.apache.thrift.TBaseHelper.copyBinary(other.ciphertext);
131 | }
132 | }
133 |
134 | public DHRatchetMessageStruct deepCopy() {
135 | return new DHRatchetMessageStruct(this);
136 | }
137 |
138 | @Override
139 | public void clear() {
140 | setPeerNumIsSet(false);
141 | this.peerNum = 0;
142 | this.ratchetKey = null;
143 | this.ciphertext = null;
144 | }
145 |
146 | public int getPeerNum() {
147 | return this.peerNum;
148 | }
149 |
150 | public DHRatchetMessageStruct setPeerNum(int peerNum) {
151 | this.peerNum = peerNum;
152 | setPeerNumIsSet(true);
153 | return this;
154 | }
155 |
156 | public void unsetPeerNum() {
157 | __isset_bitfield = org.apache.thrift.EncodingUtils.clearBit(__isset_bitfield, __PEERNUM_ISSET_ID);
158 | }
159 |
160 | /** Returns true if field peerNum is set (has been assigned a value) and false otherwise */
161 | public boolean isSetPeerNum() {
162 | return org.apache.thrift.EncodingUtils.testBit(__isset_bitfield, __PEERNUM_ISSET_ID);
163 | }
164 |
165 | public void setPeerNumIsSet(boolean value) {
166 | __isset_bitfield = org.apache.thrift.EncodingUtils.setBit(__isset_bitfield, __PEERNUM_ISSET_ID, value);
167 | }
168 |
169 | public byte[] getRatchetKey() {
170 | setRatchetKey(org.apache.thrift.TBaseHelper.rightSize(ratchetKey));
171 | return ratchetKey == null ? null : ratchetKey.array();
172 | }
173 |
174 | public java.nio.ByteBuffer bufferForRatchetKey() {
175 | return org.apache.thrift.TBaseHelper.copyBinary(ratchetKey);
176 | }
177 |
178 | public DHRatchetMessageStruct setRatchetKey(byte[] ratchetKey) {
179 | this.ratchetKey = ratchetKey == null ? (java.nio.ByteBuffer)null : java.nio.ByteBuffer.wrap(ratchetKey.clone());
180 | return this;
181 | }
182 |
183 | public DHRatchetMessageStruct setRatchetKey(java.nio.ByteBuffer ratchetKey) {
184 | this.ratchetKey = org.apache.thrift.TBaseHelper.copyBinary(ratchetKey);
185 | return this;
186 | }
187 |
188 | public void unsetRatchetKey() {
189 | this.ratchetKey = null;
190 | }
191 |
192 | /** Returns true if field ratchetKey is set (has been assigned a value) and false otherwise */
193 | public boolean isSetRatchetKey() {
194 | return this.ratchetKey != null;
195 | }
196 |
197 | public void setRatchetKeyIsSet(boolean value) {
198 | if (!value) {
199 | this.ratchetKey = null;
200 | }
201 | }
202 |
203 | public byte[] getCiphertext() {
204 | setCiphertext(org.apache.thrift.TBaseHelper.rightSize(ciphertext));
205 | return ciphertext == null ? null : ciphertext.array();
206 | }
207 |
208 | public java.nio.ByteBuffer bufferForCiphertext() {
209 | return org.apache.thrift.TBaseHelper.copyBinary(ciphertext);
210 | }
211 |
212 | public DHRatchetMessageStruct setCiphertext(byte[] ciphertext) {
213 | this.ciphertext = ciphertext == null ? (java.nio.ByteBuffer)null : java.nio.ByteBuffer.wrap(ciphertext.clone());
214 | return this;
215 | }
216 |
217 | public DHRatchetMessageStruct setCiphertext(java.nio.ByteBuffer ciphertext) {
218 | this.ciphertext = org.apache.thrift.TBaseHelper.copyBinary(ciphertext);
219 | return this;
220 | }
221 |
222 | public void unsetCiphertext() {
223 | this.ciphertext = null;
224 | }
225 |
226 | /** Returns true if field ciphertext is set (has been assigned a value) and false otherwise */
227 | public boolean isSetCiphertext() {
228 | return this.ciphertext != null;
229 | }
230 |
231 | public void setCiphertextIsSet(boolean value) {
232 | if (!value) {
233 | this.ciphertext = null;
234 | }
235 | }
236 |
237 | public void setFieldValue(_Fields field, java.lang.Object value) {
238 | switch (field) {
239 | case PEER_NUM:
240 | if (value == null) {
241 | unsetPeerNum();
242 | } else {
243 | setPeerNum((java.lang.Integer)value);
244 | }
245 | break;
246 |
247 | case RATCHET_KEY:
248 | if (value == null) {
249 | unsetRatchetKey();
250 | } else {
251 | if (value instanceof byte[]) {
252 | setRatchetKey((byte[])value);
253 | } else {
254 | setRatchetKey((java.nio.ByteBuffer)value);
255 | }
256 | }
257 | break;
258 |
259 | case CIPHERTEXT:
260 | if (value == null) {
261 | unsetCiphertext();
262 | } else {
263 | if (value instanceof byte[]) {
264 | setCiphertext((byte[])value);
265 | } else {
266 | setCiphertext((java.nio.ByteBuffer)value);
267 | }
268 | }
269 | break;
270 |
271 | }
272 | }
273 |
274 | public java.lang.Object getFieldValue(_Fields field) {
275 | switch (field) {
276 | case PEER_NUM:
277 | return getPeerNum();
278 |
279 | case RATCHET_KEY:
280 | return getRatchetKey();
281 |
282 | case CIPHERTEXT:
283 | return getCiphertext();
284 |
285 | }
286 | throw new java.lang.IllegalStateException();
287 | }
288 |
289 | /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
290 | public boolean isSet(_Fields field) {
291 | if (field == null) {
292 | throw new java.lang.IllegalArgumentException();
293 | }
294 |
295 | switch (field) {
296 | case PEER_NUM:
297 | return isSetPeerNum();
298 | case RATCHET_KEY:
299 | return isSetRatchetKey();
300 | case CIPHERTEXT:
301 | return isSetCiphertext();
302 | }
303 | throw new java.lang.IllegalStateException();
304 | }
305 |
306 | @Override
307 | public boolean equals(java.lang.Object that) {
308 | if (that == null)
309 | return false;
310 | if (that instanceof DHRatchetMessageStruct)
311 | return this.equals((DHRatchetMessageStruct)that);
312 | return false;
313 | }
314 |
315 | public boolean equals(DHRatchetMessageStruct that) {
316 | if (that == null)
317 | return false;
318 | if (this == that)
319 | return true;
320 |
321 | boolean this_present_peerNum = true;
322 | boolean that_present_peerNum = true;
323 | if (this_present_peerNum || that_present_peerNum) {
324 | if (!(this_present_peerNum && that_present_peerNum))
325 | return false;
326 | if (this.peerNum != that.peerNum)
327 | return false;
328 | }
329 |
330 | boolean this_present_ratchetKey = true && this.isSetRatchetKey();
331 | boolean that_present_ratchetKey = true && that.isSetRatchetKey();
332 | if (this_present_ratchetKey || that_present_ratchetKey) {
333 | if (!(this_present_ratchetKey && that_present_ratchetKey))
334 | return false;
335 | if (!this.ratchetKey.equals(that.ratchetKey))
336 | return false;
337 | }
338 |
339 | boolean this_present_ciphertext = true && this.isSetCiphertext();
340 | boolean that_present_ciphertext = true && that.isSetCiphertext();
341 | if (this_present_ciphertext || that_present_ciphertext) {
342 | if (!(this_present_ciphertext && that_present_ciphertext))
343 | return false;
344 | if (!this.ciphertext.equals(that.ciphertext))
345 | return false;
346 | }
347 |
348 | return true;
349 | }
350 |
351 | @Override
352 | public int hashCode() {
353 | int hashCode = 1;
354 |
355 | hashCode = hashCode * 8191 + peerNum;
356 |
357 | hashCode = hashCode * 8191 + ((isSetRatchetKey()) ? 131071 : 524287);
358 | if (isSetRatchetKey())
359 | hashCode = hashCode * 8191 + ratchetKey.hashCode();
360 |
361 | hashCode = hashCode * 8191 + ((isSetCiphertext()) ? 131071 : 524287);
362 | if (isSetCiphertext())
363 | hashCode = hashCode * 8191 + ciphertext.hashCode();
364 |
365 | return hashCode;
366 | }
367 |
368 | @Override
369 | public int compareTo(DHRatchetMessageStruct other) {
370 | if (!getClass().equals(other.getClass())) {
371 | return getClass().getName().compareTo(other.getClass().getName());
372 | }
373 |
374 | int lastComparison = 0;
375 |
376 | lastComparison = java.lang.Boolean.valueOf(isSetPeerNum()).compareTo(other.isSetPeerNum());
377 | if (lastComparison != 0) {
378 | return lastComparison;
379 | }
380 | if (isSetPeerNum()) {
381 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.peerNum, other.peerNum);
382 | if (lastComparison != 0) {
383 | return lastComparison;
384 | }
385 | }
386 | lastComparison = java.lang.Boolean.valueOf(isSetRatchetKey()).compareTo(other.isSetRatchetKey());
387 | if (lastComparison != 0) {
388 | return lastComparison;
389 | }
390 | if (isSetRatchetKey()) {
391 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.ratchetKey, other.ratchetKey);
392 | if (lastComparison != 0) {
393 | return lastComparison;
394 | }
395 | }
396 | lastComparison = java.lang.Boolean.valueOf(isSetCiphertext()).compareTo(other.isSetCiphertext());
397 | if (lastComparison != 0) {
398 | return lastComparison;
399 | }
400 | if (isSetCiphertext()) {
401 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.ciphertext, other.ciphertext);
402 | if (lastComparison != 0) {
403 | return lastComparison;
404 | }
405 | }
406 | return 0;
407 | }
408 |
409 | public _Fields fieldForId(int fieldId) {
410 | return _Fields.findByThriftId(fieldId);
411 | }
412 |
413 | public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
414 | scheme(iprot).read(iprot, this);
415 | }
416 |
417 | public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
418 | scheme(oprot).write(oprot, this);
419 | }
420 |
421 | @Override
422 | public java.lang.String toString() {
423 | java.lang.StringBuilder sb = new java.lang.StringBuilder("DHRatchetMessageStruct(");
424 | boolean first = true;
425 |
426 | sb.append("peerNum:");
427 | sb.append(this.peerNum);
428 | first = false;
429 | if (!first) sb.append(", ");
430 | sb.append("ratchetKey:");
431 | if (this.ratchetKey == null) {
432 | sb.append("null");
433 | } else {
434 | org.apache.thrift.TBaseHelper.toString(this.ratchetKey, sb);
435 | }
436 | first = false;
437 | if (!first) sb.append(", ");
438 | sb.append("ciphertext:");
439 | if (this.ciphertext == null) {
440 | sb.append("null");
441 | } else {
442 | org.apache.thrift.TBaseHelper.toString(this.ciphertext, sb);
443 | }
444 | first = false;
445 | sb.append(")");
446 | return sb.toString();
447 | }
448 |
449 | public void validate() throws org.apache.thrift.TException {
450 | // check for required fields
451 | // check for sub-struct validity
452 | }
453 |
454 | private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
455 | try {
456 | write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
457 | } catch (org.apache.thrift.TException te) {
458 | throw new java.io.IOException(te);
459 | }
460 | }
461 |
462 | private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException {
463 | try {
464 | // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
465 | __isset_bitfield = 0;
466 | read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
467 | } catch (org.apache.thrift.TException te) {
468 | throw new java.io.IOException(te);
469 | }
470 | }
471 |
472 | private static class DHRatchetMessageStructStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
473 | public DHRatchetMessageStructStandardScheme getScheme() {
474 | return new DHRatchetMessageStructStandardScheme();
475 | }
476 | }
477 |
478 | private static class DHRatchetMessageStructStandardScheme extends org.apache.thrift.scheme.StandardScheme {
479 |
480 | public void read(org.apache.thrift.protocol.TProtocol iprot, DHRatchetMessageStruct struct) throws org.apache.thrift.TException {
481 | org.apache.thrift.protocol.TField schemeField;
482 | iprot.readStructBegin();
483 | while (true)
484 | {
485 | schemeField = iprot.readFieldBegin();
486 | if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
487 | break;
488 | }
489 | switch (schemeField.id) {
490 | case 1: // PEER_NUM
491 | if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
492 | struct.peerNum = iprot.readI32();
493 | struct.setPeerNumIsSet(true);
494 | } else {
495 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
496 | }
497 | break;
498 | case 2: // RATCHET_KEY
499 | if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
500 | struct.ratchetKey = iprot.readBinary();
501 | struct.setRatchetKeyIsSet(true);
502 | } else {
503 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
504 | }
505 | break;
506 | case 3: // CIPHERTEXT
507 | if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
508 | struct.ciphertext = iprot.readBinary();
509 | struct.setCiphertextIsSet(true);
510 | } else {
511 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
512 | }
513 | break;
514 | default:
515 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
516 | }
517 | iprot.readFieldEnd();
518 | }
519 | iprot.readStructEnd();
520 |
521 | // check for required fields of primitive type, which can't be checked in the validate method
522 | struct.validate();
523 | }
524 |
525 | public void write(org.apache.thrift.protocol.TProtocol oprot, DHRatchetMessageStruct struct) throws org.apache.thrift.TException {
526 | struct.validate();
527 |
528 | oprot.writeStructBegin(STRUCT_DESC);
529 | oprot.writeFieldBegin(PEER_NUM_FIELD_DESC);
530 | oprot.writeI32(struct.peerNum);
531 | oprot.writeFieldEnd();
532 | if (struct.ratchetKey != null) {
533 | oprot.writeFieldBegin(RATCHET_KEY_FIELD_DESC);
534 | oprot.writeBinary(struct.ratchetKey);
535 | oprot.writeFieldEnd();
536 | }
537 | if (struct.ciphertext != null) {
538 | oprot.writeFieldBegin(CIPHERTEXT_FIELD_DESC);
539 | oprot.writeBinary(struct.ciphertext);
540 | oprot.writeFieldEnd();
541 | }
542 | oprot.writeFieldStop();
543 | oprot.writeStructEnd();
544 | }
545 |
546 | }
547 |
548 | private static class DHRatchetMessageStructTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
549 | public DHRatchetMessageStructTupleScheme getScheme() {
550 | return new DHRatchetMessageStructTupleScheme();
551 | }
552 | }
553 |
554 | private static class DHRatchetMessageStructTupleScheme extends org.apache.thrift.scheme.TupleScheme {
555 |
556 | @Override
557 | public void write(org.apache.thrift.protocol.TProtocol prot, DHRatchetMessageStruct struct) throws org.apache.thrift.TException {
558 | org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
559 | java.util.BitSet optionals = new java.util.BitSet();
560 | if (struct.isSetPeerNum()) {
561 | optionals.set(0);
562 | }
563 | if (struct.isSetRatchetKey()) {
564 | optionals.set(1);
565 | }
566 | if (struct.isSetCiphertext()) {
567 | optionals.set(2);
568 | }
569 | oprot.writeBitSet(optionals, 3);
570 | if (struct.isSetPeerNum()) {
571 | oprot.writeI32(struct.peerNum);
572 | }
573 | if (struct.isSetRatchetKey()) {
574 | oprot.writeBinary(struct.ratchetKey);
575 | }
576 | if (struct.isSetCiphertext()) {
577 | oprot.writeBinary(struct.ciphertext);
578 | }
579 | }
580 |
581 | @Override
582 | public void read(org.apache.thrift.protocol.TProtocol prot, DHRatchetMessageStruct struct) throws org.apache.thrift.TException {
583 | org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
584 | java.util.BitSet incoming = iprot.readBitSet(3);
585 | if (incoming.get(0)) {
586 | struct.peerNum = iprot.readI32();
587 | struct.setPeerNumIsSet(true);
588 | }
589 | if (incoming.get(1)) {
590 | struct.ratchetKey = iprot.readBinary();
591 | struct.setRatchetKeyIsSet(true);
592 | }
593 | if (incoming.get(2)) {
594 | struct.ciphertext = iprot.readBinary();
595 | struct.setCiphertextIsSet(true);
596 | }
597 | }
598 | }
599 |
600 | private static S scheme(org.apache.thrift.protocol.TProtocol proto) {
601 | return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme();
602 | }
603 | }
604 |
605 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct
2 |
3 | Facebook has adopted a Code of Conduct that we expect project participants to
4 | adhere to. Please read the [full
5 | text](https://code.facebook.com/pages/876921332402685/open-source-code-of-conduct)
6 | so that you can understand what actions will and will not be tolerated.
7 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Asynchronous Ratcheting Tree
2 | We want to make contributing to this project as easy and transparent as
3 | possible.
4 |
5 | ## Our Development Process
6 | This repository contains example code, provided to ensure that the results of
7 | our paper "On Ends-to-Ends Encryption" are reproducible. As such, it is not
8 | under active development. We are interested in ensuring that the provided
9 | implementation is faithful to the algorithms described within the paper, so
10 | we will create or accept patches as and when bugs are discovered.
11 |
12 | ## Pull Requests
13 | We actively welcome your pull requests.
14 |
15 | 1. Fork the repo and create your branch from `master`.
16 | 2. Ensure that the benchmarks still run.
17 | 3. Make sure your code lints.
18 | 4. If you haven't already, complete the Contributor License Agreement ("CLA").
19 |
20 | ## Contributor License Agreement ("CLA")
21 | In order to accept your pull request, we need you to submit a CLA. You only need
22 | to do this once to work on any of Facebook's open source projects.
23 |
24 | Complete your CLA here:
25 |
26 | ## Issues
27 | We use GitHub issues to track public bugs. Please ensure your description is
28 | clear and has sufficient instructions to be able to reproduce the issue.
29 |
30 | ## Coding Style
31 | * 2 spaces for indentation rather than tabs
32 |
33 | ## License
34 | By contributing to Asynchronous Ratcheting Tree, you agree that your
35 | contributions will be licensed under the LICENSE file in the root directory of
36 | this source tree.
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Attribution-NonCommercial 4.0 International
2 |
3 | =======================================================================
4 |
5 | Creative Commons Corporation ("Creative Commons") is not a law firm and
6 | does not provide legal services or legal advice. Distribution of
7 | Creative Commons public licenses does not create a lawyer-client or
8 | other relationship. Creative Commons makes its licenses and related
9 | information available on an "as-is" basis. Creative Commons gives no
10 | warranties regarding its licenses, any material licensed under their
11 | terms and conditions, or any related information. Creative Commons
12 | disclaims all liability for damages resulting from their use to the
13 | fullest extent possible.
14 |
15 | Using Creative Commons Public Licenses
16 |
17 | Creative Commons public licenses provide a standard set of terms and
18 | conditions that creators and other rights holders may use to share
19 | original works of authorship and other material subject to copyright
20 | and certain other rights specified in the public license below. The
21 | following considerations are for informational purposes only, are not
22 | exhaustive, and do not form part of our licenses.
23 |
24 | Considerations for licensors: Our public licenses are
25 | intended for use by those authorized to give the public
26 | permission to use material in ways otherwise restricted by
27 | copyright and certain other rights. Our licenses are
28 | irrevocable. Licensors should read and understand the terms
29 | and conditions of the license they choose before applying it.
30 | Licensors should also secure all rights necessary before
31 | applying our licenses so that the public can reuse the
32 | material as expected. Licensors should clearly mark any
33 | material not subject to the license. This includes other CC-
34 | licensed material, or material used under an exception or
35 | limitation to copyright. More considerations for licensors:
36 | wiki.creativecommons.org/Considerations_for_licensors
37 |
38 | Considerations for the public: By using one of our public
39 | licenses, a licensor grants the public permission to use the
40 | licensed material under specified terms and conditions. If
41 | the licensor's permission is not necessary for any reason--for
42 | example, because of any applicable exception or limitation to
43 | copyright--then that use is not regulated by the license. Our
44 | licenses grant only permissions under copyright and certain
45 | other rights that a licensor has authority to grant. Use of
46 | the licensed material may still be restricted for other
47 | reasons, including because others have copyright or other
48 | rights in the material. A licensor may make special requests,
49 | such as asking that all changes be marked or described.
50 | Although not required by our licenses, you are encouraged to
51 | respect those requests where reasonable. More_considerations
52 | for the public:
53 | wiki.creativecommons.org/Considerations_for_licensees
54 |
55 | =======================================================================
56 |
57 | Creative Commons Attribution-NonCommercial 4.0 International Public
58 | License
59 |
60 | By exercising the Licensed Rights (defined below), You accept and agree
61 | to be bound by the terms and conditions of this Creative Commons
62 | Attribution-NonCommercial 4.0 International Public License ("Public
63 | License"). To the extent this Public License may be interpreted as a
64 | contract, You are granted the Licensed Rights in consideration of Your
65 | acceptance of these terms and conditions, and the Licensor grants You
66 | such rights in consideration of benefits the Licensor receives from
67 | making the Licensed Material available under these terms and
68 | conditions.
69 |
70 | Section 1 -- Definitions.
71 |
72 | a. Adapted Material means material subject to Copyright and Similar
73 | Rights that is derived from or based upon the Licensed Material
74 | and in which the Licensed Material is translated, altered,
75 | arranged, transformed, or otherwise modified in a manner requiring
76 | permission under the Copyright and Similar Rights held by the
77 | Licensor. For purposes of this Public License, where the Licensed
78 | Material is a musical work, performance, or sound recording,
79 | Adapted Material is always produced where the Licensed Material is
80 | synched in timed relation with a moving image.
81 |
82 | b. Adapter's License means the license You apply to Your Copyright
83 | and Similar Rights in Your contributions to Adapted Material in
84 | accordance with the terms and conditions of this Public License.
85 |
86 | c. Copyright and Similar Rights means copyright and/or similar rights
87 | closely related to copyright including, without limitation,
88 | performance, broadcast, sound recording, and Sui Generis Database
89 | Rights, without regard to how the rights are labeled or
90 | categorized. For purposes of this Public License, the rights
91 | specified in Section 2(b)(1)-(2) are not Copyright and Similar
92 | Rights.
93 | d. Effective Technological Measures means those measures that, in the
94 | absence of proper authority, may not be circumvented under laws
95 | fulfilling obligations under Article 11 of the WIPO Copyright
96 | Treaty adopted on December 20, 1996, and/or similar international
97 | agreements.
98 |
99 | e. Exceptions and Limitations means fair use, fair dealing, and/or
100 | any other exception or limitation to Copyright and Similar Rights
101 | that applies to Your use of the Licensed Material.
102 |
103 | f. Licensed Material means the artistic or literary work, database,
104 | or other material to which the Licensor applied this Public
105 | License.
106 |
107 | g. Licensed Rights means the rights granted to You subject to the
108 | terms and conditions of this Public License, which are limited to
109 | all Copyright and Similar Rights that apply to Your use of the
110 | Licensed Material and that the Licensor has authority to license.
111 |
112 | h. Licensor means the individual(s) or entity(ies) granting rights
113 | under this Public License.
114 |
115 | i. NonCommercial means not primarily intended for or directed towards
116 | commercial advantage or monetary compensation. For purposes of
117 | this Public License, the exchange of the Licensed Material for
118 | other material subject to Copyright and Similar Rights by digital
119 | file-sharing or similar means is NonCommercial provided there is
120 | no payment of monetary compensation in connection with the
121 | exchange.
122 |
123 | j. Share means to provide material to the public by any means or
124 | process that requires permission under the Licensed Rights, such
125 | as reproduction, public display, public performance, distribution,
126 | dissemination, communication, or importation, and to make material
127 | available to the public including in ways that members of the
128 | public may access the material from a place and at a time
129 | individually chosen by them.
130 |
131 | k. Sui Generis Database Rights means rights other than copyright
132 | resulting from Directive 96/9/EC of the European Parliament and of
133 | the Council of 11 March 1996 on the legal protection of databases,
134 | as amended and/or succeeded, as well as other essentially
135 | equivalent rights anywhere in the world.
136 |
137 | l. You means the individual or entity exercising the Licensed Rights
138 | under this Public License. Your has a corresponding meaning.
139 |
140 | Section 2 -- Scope.
141 |
142 | a. License grant.
143 |
144 | 1. Subject to the terms and conditions of this Public License,
145 | the Licensor hereby grants You a worldwide, royalty-free,
146 | non-sublicensable, non-exclusive, irrevocable license to
147 | exercise the Licensed Rights in the Licensed Material to:
148 |
149 | a. reproduce and Share the Licensed Material, in whole or
150 | in part, for NonCommercial purposes only; and
151 |
152 | b. produce, reproduce, and Share Adapted Material for
153 | NonCommercial purposes only.
154 |
155 | 2. Exceptions and Limitations. For the avoidance of doubt, where
156 | Exceptions and Limitations apply to Your use, this Public
157 | License does not apply, and You do not need to comply with
158 | its terms and conditions.
159 |
160 | 3. Term. The term of this Public License is specified in Section
161 | 6(a).
162 |
163 | 4. Media and formats; technical modifications allowed. The
164 | Licensor authorizes You to exercise the Licensed Rights in
165 | all media and formats whether now known or hereafter created,
166 | and to make technical modifications necessary to do so. The
167 | Licensor waives and/or agrees not to assert any right or
168 | authority to forbid You from making technical modifications
169 | necessary to exercise the Licensed Rights, including
170 | technical modifications necessary to circumvent Effective
171 | Technological Measures. For purposes of this Public License,
172 | simply making modifications authorized by this Section 2(a)
173 | (4) never produces Adapted Material.
174 |
175 | 5. Downstream recipients.
176 |
177 | a. Offer from the Licensor -- Licensed Material. Every
178 | recipient of the Licensed Material automatically
179 | receives an offer from the Licensor to exercise the
180 | Licensed Rights under the terms and conditions of this
181 | Public License.
182 |
183 | b. No downstream restrictions. You may not offer or impose
184 | any additional or different terms or conditions on, or
185 | apply any Effective Technological Measures to, the
186 | Licensed Material if doing so restricts exercise of the
187 | Licensed Rights by any recipient of the Licensed
188 | Material.
189 |
190 | 6. No endorsement. Nothing in this Public License constitutes or
191 | may be construed as permission to assert or imply that You
192 | are, or that Your use of the Licensed Material is, connected
193 | with, or sponsored, endorsed, or granted official status by,
194 | the Licensor or others designated to receive attribution as
195 | provided in Section 3(a)(1)(A)(i).
196 |
197 | b. Other rights.
198 |
199 | 1. Moral rights, such as the right of integrity, are not
200 | licensed under this Public License, nor are publicity,
201 | privacy, and/or other similar personality rights; however, to
202 | the extent possible, the Licensor waives and/or agrees not to
203 | assert any such rights held by the Licensor to the limited
204 | extent necessary to allow You to exercise the Licensed
205 | Rights, but not otherwise.
206 |
207 | 2. Patent and trademark rights are not licensed under this
208 | Public License.
209 |
210 | 3. To the extent possible, the Licensor waives any right to
211 | collect royalties from You for the exercise of the Licensed
212 | Rights, whether directly or through a collecting society
213 | under any voluntary or waivable statutory or compulsory
214 | licensing scheme. In all other cases the Licensor expressly
215 | reserves any right to collect such royalties, including when
216 | the Licensed Material is used other than for NonCommercial
217 | purposes.
218 |
219 | Section 3 -- License Conditions.
220 |
221 | Your exercise of the Licensed Rights is expressly made subject to the
222 | following conditions.
223 |
224 | a. Attribution.
225 |
226 | 1. If You Share the Licensed Material (including in modified
227 | form), You must:
228 |
229 | a. retain the following if it is supplied by the Licensor
230 | with the Licensed Material:
231 |
232 | i. identification of the creator(s) of the Licensed
233 | Material and any others designated to receive
234 | attribution, in any reasonable manner requested by
235 | the Licensor (including by pseudonym if
236 | designated);
237 |
238 | ii. a copyright notice;
239 |
240 | iii. a notice that refers to this Public License;
241 |
242 | iv. a notice that refers to the disclaimer of
243 | warranties;
244 |
245 | v. a URI or hyperlink to the Licensed Material to the
246 | extent reasonably practicable;
247 |
248 | b. indicate if You modified the Licensed Material and
249 | retain an indication of any previous modifications; and
250 |
251 | c. indicate the Licensed Material is licensed under this
252 | Public License, and include the text of, or the URI or
253 | hyperlink to, this Public License.
254 |
255 | 2. You may satisfy the conditions in Section 3(a)(1) in any
256 | reasonable manner based on the medium, means, and context in
257 | which You Share the Licensed Material. For example, it may be
258 | reasonable to satisfy the conditions by providing a URI or
259 | hyperlink to a resource that includes the required
260 | information.
261 |
262 | 3. If requested by the Licensor, You must remove any of the
263 | information required by Section 3(a)(1)(A) to the extent
264 | reasonably practicable.
265 |
266 | 4. If You Share Adapted Material You produce, the Adapter's
267 | License You apply must not prevent recipients of the Adapted
268 | Material from complying with this Public License.
269 |
270 | Section 4 -- Sui Generis Database Rights.
271 |
272 | Where the Licensed Rights include Sui Generis Database Rights that
273 | apply to Your use of the Licensed Material:
274 |
275 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right
276 | to extract, reuse, reproduce, and Share all or a substantial
277 | portion of the contents of the database for NonCommercial purposes
278 | only;
279 |
280 | b. if You include all or a substantial portion of the database
281 | contents in a database in which You have Sui Generis Database
282 | Rights, then the database in which You have Sui Generis Database
283 | Rights (but not its individual contents) is Adapted Material; and
284 |
285 | c. You must comply with the conditions in Section 3(a) if You Share
286 | all or a substantial portion of the contents of the database.
287 |
288 | For the avoidance of doubt, this Section 4 supplements and does not
289 | replace Your obligations under this Public License where the Licensed
290 | Rights include other Copyright and Similar Rights.
291 |
292 | Section 5 -- Disclaimer of Warranties and Limitation of Liability.
293 |
294 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
295 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
296 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
297 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
298 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
299 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
300 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
301 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
302 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
303 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
304 |
305 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
306 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
307 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
308 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
309 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
310 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
311 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
312 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
313 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
314 |
315 | c. The disclaimer of warranties and limitation of liability provided
316 | above shall be interpreted in a manner that, to the extent
317 | possible, most closely approximates an absolute disclaimer and
318 | waiver of all liability.
319 |
320 | Section 6 -- Term and Termination.
321 |
322 | a. This Public License applies for the term of the Copyright and
323 | Similar Rights licensed here. However, if You fail to comply with
324 | this Public License, then Your rights under this Public License
325 | terminate automatically.
326 |
327 | b. Where Your right to use the Licensed Material has terminated under
328 | Section 6(a), it reinstates:
329 |
330 | 1. automatically as of the date the violation is cured, provided
331 | it is cured within 30 days of Your discovery of the
332 | violation; or
333 |
334 | 2. upon express reinstatement by the Licensor.
335 |
336 | For the avoidance of doubt, this Section 6(b) does not affect any
337 | right the Licensor may have to seek remedies for Your violations
338 | of this Public License.
339 |
340 | c. For the avoidance of doubt, the Licensor may also offer the
341 | Licensed Material under separate terms or conditions or stop
342 | distributing the Licensed Material at any time; however, doing so
343 | will not terminate this Public License.
344 |
345 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
346 | License.
347 |
348 | Section 7 -- Other Terms and Conditions.
349 |
350 | a. The Licensor shall not be bound by any additional or different
351 | terms or conditions communicated by You unless expressly agreed.
352 |
353 | b. Any arrangements, understandings, or agreements regarding the
354 | Licensed Material not stated herein are separate from and
355 | independent of the terms and conditions of this Public License.
356 |
357 | Section 8 -- Interpretation.
358 |
359 | a. For the avoidance of doubt, this Public License does not, and
360 | shall not be interpreted to, reduce, limit, restrict, or impose
361 | conditions on any use of the Licensed Material that could lawfully
362 | be made without permission under this Public License.
363 |
364 | b. To the extent possible, if any provision of this Public License is
365 | deemed unenforceable, it shall be automatically reformed to the
366 | minimum extent necessary to make it enforceable. If the provision
367 | cannot be reformed, it shall be severed from this Public License
368 | without affecting the enforceability of the remaining terms and
369 | conditions.
370 |
371 | c. No term or condition of this Public License will be waived and no
372 | failure to comply consented to unless expressly agreed to by the
373 | Licensor.
374 |
375 | d. Nothing in this Public License constitutes or may be interpreted
376 | as a limitation upon, or waiver of, any privileges and immunities
377 | that apply to the Licensor or You, including from the legal
378 | processes of any jurisdiction or authority.
379 |
380 | =======================================================================
381 |
382 | Creative Commons is not a party to its public
383 | licenses. Notwithstanding, Creative Commons may elect to apply one of
384 | its public licenses to material it publishes and in those instances
385 | will be considered the “Licensor.” The text of the Creative Commons
386 | public licenses is dedicated to the public domain under the CC0 Public
387 | Domain Dedication. Except for the limited purpose of indicating that
388 | material is shared under a Creative Commons public license or as
389 | otherwise permitted by the Creative Commons policies published at
390 | creativecommons.org/policies, Creative Commons does not authorize the
391 | use of the trademark "Creative Commons" or any other trademark or logo
392 | of Creative Commons without its prior written consent including,
393 | without limitation, in connection with any unauthorized modifications
394 | to any of its public licenses or any other arrangements,
395 | understandings, or agreements concerning use of licensed material. For
396 | the avoidance of doubt, this paragraph does not form part of the
397 | public licenses.
398 |
399 | Creative Commons may be contacted at creativecommons.org.
400 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2017-present, Facebook, Inc.
2 | # All rights reserved.
3 | #
4 | # This source code is licensed under the license found in the
5 | # LICENSE file in the root directory of this source tree.
6 | #
7 |
8 | help:
9 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "%-15s%s\n", $$1, $$2}'
10 |
11 | run: compile ## Run benchmarks from the paper, printing results to stdout
12 | @command -v java >/dev/null 2>&1 || { echo >&2 "I require java but it's not installed. Aborting."; exit 1; }
13 | java -Xms10g -Xmx10g -jar AsynchronousRatchetingTree/target/uber-AsynchronousRatchetingTree-1.0-SNAPSHOT.jar
14 |
15 | compile: ## Compile benchmarks
16 | @command -v mvn >/dev/null 2>&1 || { echo >&2 "I require maven but it's not installed. Aborting."; exit 1; }
17 | mvn --file AsynchronousRatchetingTree/pom.xml package
18 |
19 | clean: ## Remove Java artifacts
20 | @command -v mvn >/dev/null 2>&1 || { echo >&2 "I require maven but it's not installed. Aborting."; exit 1; }
21 | mvn --file AsynchronousRatchetingTree/pom.xml clean
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Asynchronous Ratcheting Tree
2 |
3 | Asynchronous Ratcheting Tree (ART) is a protocol for end-to-end encrypted group
4 | messaging. It aims to provide scalable group messaging while maintaining strong
5 | security guarantees.
6 |
7 | This repository contains the implementation used for the results in
8 | [our ART paper](https://eprint.iacr.org/2017/666). It contains implementations of
9 | ART and a pairwise Diffie-Hellman based ratcheting protocol which we used for
10 | comparison.
11 |
12 | The implementation in this repository is purely academic example code, and should
13 | not be used in any production or security-critical system.
14 |
15 | ## Requirements
16 |
17 | Asynchronous Ratcheting Trees requires or works with:
18 | * Java 1.8.
19 | * Apache Maven 1.8.
20 | * Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files
21 | (http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html).
22 | * Apache Thrift 0.10.0 (just for rebuilding the Thrift definitions).
23 |
24 | ## Building and executing
25 | The Makefile in this directory will compile our source and then run the
26 | benchmarks; simply run
27 |
28 | make run
29 |
30 | ## The Team
31 |
32 | The team who worked on the Asynchronous Ratcheting Tree paper are as follows:
33 |
34 | From Facebook:
35 | * Jon Millican
36 |
37 | From Oxford University:
38 | * Katriel Cohn-Gordon
39 | * Cas Cremers
40 | * Luke Garratt
41 | * Kevin Milner
42 |
43 | We are grateful to our collaborators from Oxford University for the considerable
44 | time and expertise that they put in to this paper, and into the formal proofs of
45 | the ART protocol.
46 |
47 | ## Contributing
48 |
49 | See the CONTRIBUTING file for how to help out.
50 |
51 | ## License
52 |
53 | Asynchronous Ratcheting Tree is CC-BY-NC-licensed.
54 |
--------------------------------------------------------------------------------