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

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

Changed surrogates to work the way discussed with David. EncryptedExpReader/Writer updated to work with this.

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