source: trunk/src/org/expeditee/encryption/Actions.java@ 1485

Last change on this file since 1485 was 1485, checked in by bnemhaus, 4 years ago

When adding a colleagues pw share to your secrets frame, save that frame to ensure it is actually there.

File size: 10.0 KB
Line 
1package org.expeditee.encryption;
2
3import java.security.InvalidKeyException;
4import java.security.NoSuchAlgorithmException;
5import java.security.SecureRandom;
6import java.util.Arrays;
7import java.util.Base64;
8import java.util.Collection;
9import java.util.HashMap;
10import java.util.List;
11import java.util.Map;
12import java.util.Random;
13
14import javax.crypto.BadPaddingException;
15import javax.crypto.Cipher;
16import javax.crypto.IllegalBlockSizeException;
17import javax.crypto.NoSuchPaddingException;
18import javax.crypto.SecretKey;
19import javax.crypto.spec.SecretKeySpec;
20
21import org.expeditee.auth.AuthenticatorBrowser;
22import org.expeditee.core.Colour;
23import org.expeditee.gui.DisplayController;
24import org.expeditee.gui.Frame;
25import org.expeditee.gui.FrameIO;
26import org.expeditee.gui.FreeItems;
27import org.expeditee.gui.MessageBay;
28import org.expeditee.items.Item;
29import org.expeditee.items.Text;
30import org.expeditee.settings.UserSettings;
31
32import com.codahale.shamir.Scheme;
33
34public class Actions implements CryptographyConstants {
35
36 public static void SetSurrogateFor(Text surrogate, Text action) {
37 Frame frame = DisplayController.getCurrentFrame();
38 String[] split = action.getText().split(" ");
39
40 if (split.length >= 2) {
41 int primaryID = Integer.parseInt(split[1]);
42 Item itemWithID = frame.getItemWithID(primaryID);
43 if (itemWithID == null) {
44 MessageBay.displayMessage("No item with ID " + primaryID + " exists on this frame.");
45 return;
46 } else {
47 itemWithID.addToSurrogates(surrogate);
48 }
49 } else {
50 MessageBay.displayMessage("Usage: SetSurrogateFor Int, inject desired surrogate.");
51 }
52 }
53
54 public static Text GenerateSecret() {
55 return AuthGenerateSecretUsage();
56 }
57
58 public static Text GenerateSecret(String label) {
59 String nl = System.getProperty("line.separator");
60 String secretsFrame = UserSettings.UserName.get() + 11;
61 StringBuilder instructions = new StringBuilder("You have generated a encryption label with name " + label + "." + nl);
62 instructions.append("Place this generated label on your secrets frame (" + secretsFrame + ") before using it.");
63 MessageBay.displayMessage(instructions.toString()).setLink(secretsFrame);
64 return AuthGenerateSecret(label);
65 }
66
67 public static Text SplitSecret(Text key) {
68 return AuthSplitSecret(key);
69 }
70
71 public static Text JoinSecret(Text key) {
72 return AuthJoinSecret(key);
73 }
74
75 public static void Encrypt(Text labelWithKey) {
76 AuthEncrypt(labelWithKey);
77 }
78
79 public static void Decrypt(Text labelWithKey) {
80 AuthDecrypt(labelWithKey);
81 }
82
83 public static Text AuthGenerateSecret() {
84 return AuthGenerateSecretUsage();
85 }
86
87 public static Text AuthGenerateSecret(String label) {
88 // Generate AES Key
89 Random rand = new SecureRandom();
90 byte[] keyBytes = new byte[16];
91 rand.nextBytes(keyBytes);
92 String key = Base64.getEncoder().encodeToString(keyBytes);
93
94 Text text = new Text(label);
95 text.setData(key);
96 text.setPosition(DisplayController.getMousePosition());
97 return text;
98 }
99
100 public static Text AuthSplitSecret(Text key) {
101 if (!FreeItems.hasItemsAttachedToCursor()) {
102 return AuthSplitSecretUsage();
103 }
104
105 // Retrieve secret
106 String secret = key.getData().get(0);
107 byte[] secretBytes = Base64.getDecoder().decode(secret);
108
109 // Obtain parameters for shamir
110 String[] arguments = key.getText().split(" ");
111 int requiredShares = Integer.parseInt(arguments[1]);
112 int totalShares = arguments.length - 2;
113
114 // Create shares
115 Scheme scheme = new Scheme(new SecureRandom(), totalShares, requiredShares);
116 Map<Integer, byte[]> split = scheme.split(secretBytes);
117
118 // Add shares to key
119 List<String> data = key.getData();
120 for (Integer i: split.keySet()) {
121 data.add("{" + i + "}" + Base64.getEncoder().encodeToString(split.get(i)));
122 }
123 key.setData(data);
124 key.setText(arguments[0]);
125
126 return key;
127 }
128
129 public static Text AuthJoinSecret(Text key) {
130 Map<Integer, byte[]> contributingParts = new HashMap<Integer, byte[]>();
131
132 // Retrieve splits
133 List<String> data = key.getData();
134 for (String d: data) {
135 if (d.startsWith("{")) {
136 String[] split = d.split("}");
137 Integer k = Integer.parseInt(split[0].replace("{", ""));
138 byte[] v = Base64.getDecoder().decode(split[1]);
139 contributingParts.put(k, v);
140 }
141 }
142
143 // Obtain parameters for shamir
144 String[] arguments = key.getText().split(" ");
145 int totalShares = Integer.parseInt(arguments[2]);
146 int requiredShares = Integer.parseInt(arguments[1]);
147
148 // Perform join
149 Scheme scheme = new Scheme(new SecureRandom(), totalShares, requiredShares);
150 byte[] join = scheme.join(contributingParts);
151
152 data.clear();
153 data.add(Base64.getEncoder().encodeToString(join));
154
155 return key;
156 }
157
158 public static void AuthEncrypt(Text labelWithKey) {
159 // Obtain encryption key
160 String keyEncoded = labelWithKey.getData().get(0);
161 byte[] keyDecoded = Base64.getDecoder().decode(keyEncoded);
162 SecretKey key = new SecretKeySpec(keyDecoded, SymmetricAlgorithm);
163
164 // Perform encryption
165 Frame toEncrypt = FrameIO.LoadFrame(labelWithKey.getLink());
166 Collection<Text> textItems = toEncrypt.getTextItems();
167 for (Text t: textItems) {
168 byte[] encrypted = EncryptSymmetric(t.getText().getBytes(), key);
169 t.setText(Base64.getEncoder().encodeToString(encrypted));
170 }
171
172 // Save changes
173 FrameIO.SaveFrame(toEncrypt);
174 }
175
176 public static void AuthDecrypt(Text labelWithKey) {
177 // Obtain encryption key
178 String keyEncoded = labelWithKey.getData().get(0);
179 byte[] keyDecoded = Base64.getDecoder().decode(keyEncoded);
180 SecretKey key = new SecretKeySpec(keyDecoded, SymmetricAlgorithm);
181
182 // Perform decryption
183 Frame toDecrypt = FrameIO.LoadFrame(labelWithKey.getLink());
184 Collection<Text> textItems = toDecrypt.getTextItems();
185 for (Text t: textItems) {
186 byte[] decrypted = DecryptSymmetric(Base64.getDecoder().decode(t.getText().getBytes()), key);
187 t.setText(new String(decrypted));
188 }
189
190 // Save changes
191 FrameIO.SaveFrame(toDecrypt);
192 }
193
194 public static byte[] EncryptSymmetric(final byte[] toEncrypt, final SecretKey key) {
195 // toEncrypt = Base64.getDecoder().decode(toEncrypt);
196 try {
197 final Cipher cipher = Cipher.getInstance(SymmetricAlgorithm + SymmetricAlgorithmParameters);
198 cipher.init(Cipher.ENCRYPT_MODE, key);
199 //could use modulus
200 final int length = (int) ((Math.ceil(toEncrypt.length / 16f)) * 16);
201 final byte[] toEncryptSizeAdjusted = Arrays.copyOf(toEncrypt, length);
202 //System.err.println("(" + toEncryptSizeAdjusted.length + ")" + "Before Encryption Data: "
203 // + Arrays.toString(toEncryptSizeAdjusted));
204 final byte[] result = cipher.doFinal(toEncryptSizeAdjusted);
205 //System.err.println("(" + result.length + ")" + "Encrypted Data: " + Arrays.toString(result));
206 return result;
207 } catch (final NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
208 | IllegalBlockSizeException | BadPaddingException e) {
209 e.printStackTrace();
210 return null;
211 }
212 }
213
214 public static byte[] DecryptSymmetric(final byte[] toDecrypt, final SecretKey key) {
215 try {
216 final Cipher cipher = Cipher.getInstance(SymmetricAlgorithm + SymmetricAlgorithmParameters);
217 cipher.init(Cipher.DECRYPT_MODE, key);
218 final byte[] decryptedBytes = cipher.doFinal(toDecrypt);
219 int indexOfZero = decryptedBytes.length - 1;
220 for (int i = decryptedBytes.length - 1; i >= 0; i--) {
221 if (decryptedBytes[i] != (byte) 0) {
222 indexOfZero = i + 1;
223 break;
224 }
225 }
226 return Arrays.copyOf(decryptedBytes, indexOfZero);
227 } catch (final NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
228 | IllegalBlockSizeException | BadPaddingException e) {
229 e.printStackTrace();
230 return null;
231 }
232 }
233
234 public static void AuthAddSecretKey(String name, String data) {
235 String frameName = UserSettings.UserName.get() + AuthenticatorBrowser.SECRETS_FRAME;
236 Frame secretsFrame = FrameIO.LoadFrame(frameName);
237 secretsFrame.addText(500, 500, name, null).addToData(data);
238 FrameIO.ForceSaveFrame(secretsFrame);
239 MessageBay.displayMessage("Your half of " + name + "'s personal key has been added to " + frameName);
240 }
241
242 private static Text AuthSplitSecretUsage() {
243 String nl = System.getProperty("line.separator");
244 String tab = " ";
245 StringBuilder message = new StringBuilder("Usage: " + nl);
246 message.append(tab + "With Text Item attached to cursor: " + nl);
247 message.append(tab + tab + "Content matches pattern \"<SecretName> <Amount of Coperation Required> <Individual Name 1> <Individual Name 2> ... <Individual Name N>\"" + nl);
248 message.append(tab + tab + "Context Example: \"SecretName 3 Sandra John Billy Sally Sam Tim\"" + nl);
249 message.append(tab + tab + "Data contains key data" + nl);
250 message.append(tab + "Middle click on this action." + nl);
251 message.append(tab + "Resulting Text Item will contain shares in data.");
252 return generateUsageText(message);
253 }
254
255 private static Text AuthGenerateSecretUsage() {
256 String nl = System.getProperty("line.separator");
257 String tab = " ";
258 StringBuilder message = new StringBuilder("Usage: " + nl);
259 message.append(tab + "With Text Item attached to cursor: " + nl);
260 message.append(tab + tab + "Content should be one word with no spaces." + nl);
261 message.append(tab + tab + "Content represents the desired label name for the generated secret." + nl);
262 message.append(tab + tab + "This action will overwrite any existing data." + nl);
263 message.append(tab + "Middle click on this action." + nl);
264 message.append(tab + "Text Item will now contain a full key in its data." + nl);
265 message.append(tab + "Resulting Text Item is now a Secret and can be placed on secrets frame.");
266 return generateUsageText(message);
267 }
268
269 private static Text generateUsageText(StringBuilder message) {
270 Text ret = new Text(message.toString());
271 ret.setPosition(DisplayController.getMousePosition());
272 ret.setSize(14);
273 ret.setBackgroundColor(Colour.LIGHT_GRAY);
274 ret.setBorderColor(Colour.DARK_GRAY);
275 return ret;
276 }
277}
Note: See TracBrowser for help on using the repository browser.