source: trunk/src/org/expeditee/encryption/io/EncryptedExpWriter.java@ 1409

Last change on this file since 1409 was 1409, checked in by bln4, 5 years ago

Moved Label.java to Surrogates folder as it makes more sense there.

File size: 8.3 KB
Line 
1package org.expeditee.encryption.io;
2
3import java.io.IOException;
4import java.lang.reflect.InvocationTargetException;
5import java.lang.reflect.Method;
6import java.security.InvalidKeyException;
7import java.security.NoSuchAlgorithmException;
8import java.util.ArrayList;
9import java.util.Arrays;
10import java.util.Base64;
11import java.util.LinkedHashMap;
12import java.util.List;
13import java.util.function.Consumer;
14
15import javax.crypto.BadPaddingException;
16import javax.crypto.Cipher;
17import javax.crypto.IllegalBlockSizeException;
18import javax.crypto.NoSuchPaddingException;
19import javax.crypto.SecretKey;
20import javax.crypto.spec.SecretKeySpec;
21
22import org.expeditee.encryption.CryptographyConstants;
23import org.expeditee.encryption.items.surrogates.EncryptionDetail;
24import org.expeditee.encryption.items.surrogates.Label;
25import org.expeditee.encryption.items.surrogates.Surrogate;
26import org.expeditee.encryption.items.surrogates.Label.LabelResult;
27import org.expeditee.gui.Frame;
28import org.expeditee.gui.MessageBay;
29import org.expeditee.io.Conversion;
30import org.expeditee.io.ExpWriter;
31import org.expeditee.items.Item;
32import org.expeditee.items.Line;
33import org.expeditee.items.Text;
34import org.expeditee.settings.identity.secrets.KeyList;
35import org.expeditee.stats.SessionStats;
36
37public class EncryptedExpWriter extends ExpWriter implements CryptographyConstants {
38 private SecretKey key;
39
40 private final String label;
41
42 private static final String ENCRYPTED_EXP_FLAG = "EncryptedExp";
43 private static final String nl = "\n";
44 private static final String labelProfile = "Profile";
45 private static final String labelNone = "None";
46 protected static final String SURROGATE_TERMINATOR = TERMINATOR + "...";
47
48 public EncryptedExpWriter(String encryptionLabel) {
49 label = encryptionLabel;
50 if (label.equals(labelNone)) {
51 return;
52 }
53
54 if (label.equals(labelProfile)) {
55 // obtain personal key
56 Text text = KeyList.PersonalKey.get();
57 List<String> data = text.getData();
58 if (data != null && !data.isEmpty()) {
59 byte[] keyBytes = Base64.getDecoder().decode(data.get(0));
60 key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
61 }
62 } else {
63 LabelResult res = Label.resolveKey(label);
64 if (res == LabelResult.SuccessResolveLabelToKey) {
65 byte[] keyBytes = res.key;
66 key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
67 } else if (res == LabelResult.ErrorUnableToFindLabel) {
68 MessageBay.errorMessage(res.toString() + encryptionLabel);
69 key = null;
70 } else {
71 MessageBay.errorMessage(res.toString());
72 }
73 }
74 }
75
76 @Override
77 public void outputFrame(Frame frame) throws IOException {
78 if (_writer == null) { return; }
79
80 preOutputFrame();
81 writeHeader(frame);
82
83 // write item
84 writeItemData(frame);
85 writeTerminator();
86
87 // write lines and constraints
88 writeLineData();
89 writeTerminator();
90 writeConstraintData();
91 writeTerminator();
92
93 writeLine(SessionStats.getFrameEventList(frame));
94 }
95
96 @Override
97 protected void preOutputFrame() {
98 try {
99 String line = ENCRYPTED_EXP_FLAG + label + nl;
100 _writer.write(line);
101 _stringWriter.append(line);
102 } catch (final IOException e) {
103 e.printStackTrace();
104 }
105 }
106
107 @Override
108 protected void writeLine(String line) throws IOException {
109 // do not write empty lines
110 if (line == null) { return; }
111
112 String toWrite;
113 if (key == null && label.equals(labelNone)) {
114 toWrite = line + nl;
115 } else {
116 // prepare line to write out
117 byte[] encrypted = EncryptSymmetric(line.getBytes(), key);
118 toWrite = Base64.getEncoder().encodeToString(encrypted) + nl;
119 }
120
121 // output
122 _writer.write(toWrite);
123 _stringWriter.append(toWrite);
124 }
125
126 @Override
127 protected void writeLineData() throws IOException {
128 super.writeLineData();
129
130 writeSurrogateLineData();
131 }
132
133 @Override
134 protected void writeClass(Item toWrite) throws IOException {
135 LinkedHashMap<Character,Method> itemTags = new LinkedHashMap<Character, Method>(getItemTags());
136 LinkedHashMap<String,Method> itemTagsExt = new LinkedHashMap<String, Method>(getItemTagsExt());
137
138 writeTag(toWrite, new Object[] {}, itemTags, 'S');
139 writeTag(toWrite, new Object[] {}, itemTagsExt, "_el");
140
141 itemTags.remove('S');
142 itemTagsExt.remove("_el");
143
144 writeTags(toWrite, new Object[] {}, itemTags);
145 writeTags(toWrite, new Object[] {}, itemTagsExt);
146 }
147
148 @Override
149 protected <T> void writeTag(Item toWrite, Object[] param, LinkedHashMap<T, Method> tags, T tag) {
150 EncryptionDetail encryptionDetail = toWrite.getEncryptionDetailForTag(tag + "");
151 switch (encryptionDetail) {
152 case UnencryptedOnSave:
153 super.writeTag(toWrite, param, tags, tag);
154 break;
155 case ReencryptOnSave:
156 Method toRun = tags.get(tag);
157 Class<?> declarer = toRun.getDeclaringClass();
158 LabelResult res = Label.resolveKey(toWrite.getEncryptionLabel());
159 if (declarer.isAssignableFrom(toWrite.getClass()) && res == LabelResult.SuccessResolveLabelToKey) {
160 SecretKey key = new SecretKeySpec(res.key, SymmetricAlgorithm);
161 try {
162 Object o = toRun.invoke(toWrite, new Object[] {});
163 o = Conversion.ConvertToExpeditee(toRun, o);
164 if (o != null) {
165 if (o instanceof List) {
166 for (Object line: (List<?>)o) {
167 byte[] encryptedBytes = EncryptSymmetric(line.toString().getBytes(), key);
168 writeLine(tag + "E", Base64.getEncoder().encodeToString(encryptedBytes));
169 }
170 } else {
171 byte[] encryptedBytes = EncryptSymmetric(o.toString().getBytes(), key);
172 writeLine(tag + "E", Base64.getEncoder().encodeToString(encryptedBytes));
173 }
174 }
175 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
176 e.printStackTrace();
177 } catch (IOException e) {
178 e.printStackTrace();
179 }
180 }
181 break;
182 case UseUndecipheredValueOnSave:
183 try {
184 writeLine(tag + "E", encryptionDetail.getUndecipheredValue());
185 } catch (IOException e) {
186 e.printStackTrace();
187 }
188 break;
189 }
190 }
191
192 private void writeItemData(Frame frame) throws IOException {
193 // write each item in the frame
194 for (Item i : frame.getItemsToSave()) {
195 assert (!(i instanceof Line));
196 writeItem(i);
197 }
198
199 for (final Item i: frame.getBodyItemsWithInsufficientPermissions()) {
200 assert (!(i instanceof Line));
201 writeItem(i);
202 }
203
204 writeSurrogateItemsData(frame);
205 }
206
207 private void writeSurrogateItemsData(Frame frame) throws IOException {
208 List<Surrogate> surrogates = new ArrayList<Surrogate>();
209
210 Consumer<? super Item> store = item -> surrogates.addAll(item.getSurrogates());
211 frame.getItemsToSave().forEach(store);
212 frame.getBodyItemsWithInsufficientPermissions().forEach(store);
213
214 if (!surrogates.isEmpty()) {
215 // If there is some surrogates, write the surrogate
216 // terminator, then write out the surrogates.
217 writeSurrogateTerminator();
218
219 for (Surrogate surrogate: surrogates) {
220 String output = surrogate.toString();
221 writeLine(output);
222 }
223 }
224 }
225
226 private void writeSurrogateLineData() throws IOException {
227 List<Surrogate> surrogateLines = new ArrayList<Surrogate>();
228
229 for(Item lineEnd: _lineEnds) {
230 List<Line> lines = lineEnd.getLines();
231 for (Line line: lines) {
232 surrogateLines.addAll(line.getSurrogates());
233 }
234 }
235
236 if (!surrogateLines.isEmpty()) {
237 // If there is some surrogates, write the surrogate
238 // terminator, then write out the surrogates.
239 writeSurrogateTerminator();
240
241 for (Surrogate surrogate: surrogateLines) {
242 String output = surrogate.toString();
243 writeLine(output);
244 }
245 }
246 }
247
248 private void writeSurrogateTerminator() throws IOException {
249 writeLine(SURROGATE_TERMINATOR + nl);
250 }
251
252 private static byte[] EncryptSymmetric(byte[] toEncrypt, SecretKey key) {
253 try {
254 Cipher cipher = Cipher.getInstance(SymmetricAlgorithm + SymmetricAlgorithmParameters);
255 cipher.init(Cipher.ENCRYPT_MODE, key);
256 //could use modulus
257 int length = (int) ((Math.ceil(toEncrypt.length / 16f)) * 16);
258 byte[] toEncryptSizeAdjusted = Arrays.copyOf(toEncrypt, length);
259 byte[] result = cipher.doFinal(toEncryptSizeAdjusted);
260 return result;
261 } catch (final NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
262 | IllegalBlockSizeException | BadPaddingException e) {
263 e.printStackTrace();
264 return null;
265 }
266 }
267}
Note: See TracBrowser for help on using the repository browser.