1 | package org.expeditee.encryption.items.surrogates;
|
---|
2 |
|
---|
3 | import java.util.ArrayList;
|
---|
4 | import java.util.Arrays;
|
---|
5 | import java.util.Base64;
|
---|
6 | import java.util.List;
|
---|
7 | import java.util.function.Predicate;
|
---|
8 | import java.util.stream.Collectors;
|
---|
9 | import java.util.stream.Stream;
|
---|
10 |
|
---|
11 | import org.expeditee.gui.ItemsList;
|
---|
12 | import org.expeditee.items.Item;
|
---|
13 | import org.expeditee.items.Text;
|
---|
14 | import org.expeditee.settings.identity.secrets.KeyList;
|
---|
15 |
|
---|
16 | public class Label {
|
---|
17 | private static List<String> userLabels = new ArrayList<String>();
|
---|
18 | private static List<LabelInfo> labelsInfo = new ArrayList<LabelInfo>();
|
---|
19 | private static int surrogateStep = 0;
|
---|
20 | private static boolean isInSurrogateMode = false;
|
---|
21 | private static boolean isUnprivileged = false;
|
---|
22 |
|
---|
23 | public static LabelInfo getLabel(String labelName) {
|
---|
24 | // Maintain the local cache of user labels
|
---|
25 | ensureUserLabels();
|
---|
26 |
|
---|
27 | int indexOfLabel = userLabels.indexOf(labelName);
|
---|
28 | if (indexOfLabel == -1) {
|
---|
29 | //A label by the specified name does not exist.
|
---|
30 | return unableToFindLabelResult(labelName);
|
---|
31 | } else {
|
---|
32 | //A label by the specified name is in the local cache and can be used.
|
---|
33 | LabelInfo labelResult = labelsInfo.get(indexOfLabel);
|
---|
34 | return labelResult;
|
---|
35 | }
|
---|
36 | }
|
---|
37 |
|
---|
38 | public static boolean isInSurrogateMode() {
|
---|
39 | return isInSurrogateMode;
|
---|
40 | }
|
---|
41 |
|
---|
42 | /**
|
---|
43 | * Progresses surrogate mode and returns a list of labels that are currently in effect.
|
---|
44 | * @param context The list of expeditee Items to be considered for context. These are checked for labels.
|
---|
45 | * @return Returns either:
|
---|
46 | * <ol type='a'>
|
---|
47 | * <li> A list of length 1 specifying the label that the current surrogate mode accepts or </li>
|
---|
48 | * <li> A list of length 0 which specifies that surrogate mode is in unprivileged view or </li>
|
---|
49 | * <li> Null, which means there are no labels in play on this frame
|
---|
50 | * (so asking for surrogate mode does not make sense) </li>
|
---|
51 | * </ol>
|
---|
52 | */
|
---|
53 | public static List<String> progressSurrogateMode(ItemsList context) {
|
---|
54 | // Maintain the local cache of user labels
|
---|
55 | ensureUserLabels();
|
---|
56 |
|
---|
57 | List<String> ret;
|
---|
58 |
|
---|
59 | List<String> localLabels = getLabelsFromContext(context);
|
---|
60 | if (localLabels.isEmpty()) {
|
---|
61 | // If there are no labels on this Frame return null;
|
---|
62 | return null;
|
---|
63 | }
|
---|
64 |
|
---|
65 | ArrayList<String> intersection = new ArrayList<String>(userLabels);
|
---|
66 | intersection.retainAll(localLabels);
|
---|
67 | if (!isInSurrogateMode) {
|
---|
68 | isInSurrogateMode = true;
|
---|
69 | // Priming surrogate step to become zero in the loop below.
|
---|
70 | surrogateStep = -1;
|
---|
71 | }
|
---|
72 |
|
---|
73 | // We are already in surrogate mode, progress it.
|
---|
74 | int index = surrogateStep + 1;
|
---|
75 | boolean found = false;
|
---|
76 | while (index < userLabels.size()) {
|
---|
77 | String surrogateMode = userLabels.get(index);
|
---|
78 | if (intersection.contains(surrogateMode)) {
|
---|
79 | found = true;
|
---|
80 | break;
|
---|
81 | }
|
---|
82 | index++;
|
---|
83 | }
|
---|
84 |
|
---|
85 | if (found) {
|
---|
86 | isUnprivileged = false;
|
---|
87 | surrogateStep = index;
|
---|
88 | String chosenSurrogateMode = userLabels.get(surrogateStep);
|
---|
89 | ret = Arrays.asList(chosenSurrogateMode);
|
---|
90 | } else {
|
---|
91 | if (surrogateStep >= userLabels.size()) {
|
---|
92 | surrogateStep = 0;
|
---|
93 | isInSurrogateMode = false;
|
---|
94 | isUnprivileged = false;
|
---|
95 | ret = intersection;
|
---|
96 | } else {
|
---|
97 | ret = new ArrayList<String>();
|
---|
98 | surrogateStep = index;
|
---|
99 | isUnprivileged = true;
|
---|
100 | }
|
---|
101 | }
|
---|
102 |
|
---|
103 | return ret;
|
---|
104 | }
|
---|
105 |
|
---|
106 | public static void resetSurrogateMode() {
|
---|
107 | // Maintain the local cache of user labels
|
---|
108 | ensureUserLabels();
|
---|
109 |
|
---|
110 | surrogateStep = 0;
|
---|
111 | isInSurrogateMode = false;
|
---|
112 | }
|
---|
113 |
|
---|
114 | public static List<String> getAccessibleLabelsNames(ItemsList itemsList) {
|
---|
115 | // Maintain the local cache of user labels
|
---|
116 | ensureUserLabels();
|
---|
117 |
|
---|
118 | if (isInSurrogateMode) {
|
---|
119 | if (isUnprivileged) {
|
---|
120 | return new ArrayList<String>();
|
---|
121 | } else {
|
---|
122 | return Arrays.asList(userLabels.get(surrogateStep));
|
---|
123 | }
|
---|
124 | } else {
|
---|
125 | List<String> labelsFromContext = getLabelsFromContext(itemsList);
|
---|
126 | ArrayList<String> copy = new ArrayList<String>(labelsFromContext);
|
---|
127 | copy.retainAll(userLabels);
|
---|
128 | return copy;
|
---|
129 | }
|
---|
130 | }
|
---|
131 |
|
---|
132 | private static void ensureUserLabels() {
|
---|
133 | List<String> userSettingsLabelNames = KeyList.getLabelsNameOnly();
|
---|
134 | boolean hasNoKeys = userLabels.isEmpty() && userSettingsLabelNames.isEmpty();
|
---|
135 | boolean hasNotChanged = userLabels.equals(userSettingsLabelNames) || hasNoKeys;
|
---|
136 |
|
---|
137 | if (hasNotChanged) { return; }
|
---|
138 |
|
---|
139 | // Deal with the fact that the position of our current surrogate mode
|
---|
140 | // might have moved in the users list of labels.
|
---|
141 | if (userLabels.size() > surrogateStep) {
|
---|
142 | String surrogateMode = userLabels.get(surrogateStep);
|
---|
143 | int newIndexOfSurrogateMode = userSettingsLabelNames.indexOf(surrogateMode);
|
---|
144 | if (newIndexOfSurrogateMode >= 0) {
|
---|
145 | surrogateStep = newIndexOfSurrogateMode;
|
---|
146 | } else {
|
---|
147 | surrogateStep = 0;
|
---|
148 | isInSurrogateMode = false;
|
---|
149 | // MessageBay.displayMessage("You have lost access to the encryption label "
|
---|
150 | // + surrogateMode + ". Dropping out of surrogate mode.");
|
---|
151 | System.out.println("You have lost access to the encryption label "
|
---|
152 | + surrogateMode + ". Dropping out of surrogate mode.");
|
---|
153 | }
|
---|
154 | }
|
---|
155 |
|
---|
156 | // (Re)Initialise the userLabels list and labelResultsCache.
|
---|
157 | userLabels.clear();
|
---|
158 | labelsInfo.clear();
|
---|
159 | Text[] userSettings = KeyList.UserLabels.get();
|
---|
160 | for (Text userSetting: userSettings) {
|
---|
161 | String labelName = userSetting.getName();
|
---|
162 | List<String> data = userSetting.getData();
|
---|
163 | if (data == null || data.isEmpty()) {
|
---|
164 | continue;
|
---|
165 | }
|
---|
166 |
|
---|
167 | // Extract the data and check if we have a full or partial key.
|
---|
168 | String dataEntry = data.get(0);
|
---|
169 | if (dataEntry.contains("{")) {
|
---|
170 | userLabels.add(labelName);
|
---|
171 | LabelInfo labelInfo = new LabelInfo(LabelResult.SuccessResolveLabelToPartialKey, labelName, null);
|
---|
172 | labelsInfo.add(labelInfo);
|
---|
173 | } else {
|
---|
174 | userLabels.add(labelName);
|
---|
175 | byte[] key = Base64.getDecoder().decode(dataEntry);
|
---|
176 | LabelInfo labelInfo = new LabelInfo(LabelResult.SuccessResolveLabelToKey, labelName, key);
|
---|
177 | labelsInfo.add(labelInfo);
|
---|
178 | }
|
---|
179 | }
|
---|
180 | }
|
---|
181 |
|
---|
182 | private static List<String> getLabelsFromContext(ItemsList context) {
|
---|
183 | Predicate<Item> hasEncryptionLabel = item -> item.getEncryptionLabel() != null && !item.getEncryptionLabel().isEmpty();
|
---|
184 | List<Item> local = context.cloneList();
|
---|
185 | Stream<Item> itemsWithLabel = local.stream().filter(hasEncryptionLabel);
|
---|
186 | Stream<String> labels = itemsWithLabel.map(item -> item.getEncryptionLabel()).distinct();
|
---|
187 | return labels.collect(Collectors.toList());
|
---|
188 | }
|
---|
189 |
|
---|
190 | private static LabelInfo unableToFindLabelResult(String label) {
|
---|
191 | LabelInfo info = new LabelInfo(LabelResult.ErrorUnableToFindLabel, label, null);
|
---|
192 | return info;
|
---|
193 | }
|
---|
194 |
|
---|
195 | public static class LabelInfo {
|
---|
196 |
|
---|
197 | public byte[] key;
|
---|
198 | public String name;
|
---|
199 | public LabelResult type;
|
---|
200 |
|
---|
201 | public LabelInfo(LabelResult type, String name, byte[] key) {
|
---|
202 | this.type = type;
|
---|
203 | this.name = name;
|
---|
204 | this.key = key;
|
---|
205 | }
|
---|
206 |
|
---|
207 | public boolean is(LabelResult type) {
|
---|
208 | return this.type == type;
|
---|
209 | }
|
---|
210 |
|
---|
211 | public String toString() {
|
---|
212 | switch(type) {
|
---|
213 | case SuccessResolveLabelToKey:
|
---|
214 | return "Resolved label to key: " + Base64.getEncoder().encodeToString(key);
|
---|
215 | case SuccessResolveLabelToPartialKey:
|
---|
216 | return "Resolved label to slice of a key: " + Base64.getEncoder().encodeToString(key);
|
---|
217 | case ErrorUnableToFindSecretsFrame:
|
---|
218 | return "Unable to find your Secrets Frame.";
|
---|
219 | case ErrorUnableToFindLabel:
|
---|
220 | return "Unable to resolve label to encrypt/decrypt frame. Label: " + name;
|
---|
221 | case ErrorForbiddenLabel:
|
---|
222 | return "Whilst you have the key for label " + name + " ; you are not allowed to use it.";
|
---|
223 | }
|
---|
224 |
|
---|
225 | String message = "Was the list of possible enum results updated without nessasary changes to the toString() function?";
|
---|
226 | throw new IllegalArgumentException(message);
|
---|
227 | }
|
---|
228 | }
|
---|
229 |
|
---|
230 | public enum LabelResult {
|
---|
231 | SuccessResolveLabelToKey,
|
---|
232 | SuccessResolveLabelToPartialKey,
|
---|
233 | ErrorUnableToFindSecretsFrame,
|
---|
234 | ErrorUnableToFindLabel,
|
---|
235 | ErrorForbiddenLabel;
|
---|
236 | }
|
---|
237 | }
|
---|