source: trunk/src/org/expeditee/auth/EncryptedExpReader.java@ 1202

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

Initial commit of functionality concerning multiuser login, further to come.

Actions.java -> Actions that allow users to authenticate and secure their accounts.
AuthenticationTag.java -> Enum like structure for text fields associated with authentication.
Authenticator.java -> Startup functionality for when Expeditee is run in authentication mode.
EncryptedExpReader.java -> Reads exp files previously encrypted with EncryptedExpWriter (not currently used) and EncryptedProfileExpWriter
Mail.java -> Functions for transforming database stored messages into datastructures used to display those messages to the MailBay.

File size: 6.9 KB
Line 
1package org.expeditee.auth;
2
3import java.io.BufferedReader;
4import java.io.FileInputStream;
5import java.io.FileReader;
6import java.io.IOException;
7import java.io.InputStreamReader;
8import java.io.Reader;
9import java.io.UnsupportedEncodingException;
10import java.security.InvalidKeyException;
11import java.security.NoSuchAlgorithmException;
12import java.util.Arrays;
13import java.util.Base64;
14import java.util.List;
15import java.util.stream.Collectors;
16
17import javax.crypto.BadPaddingException;
18import javax.crypto.Cipher;
19import javax.crypto.IllegalBlockSizeException;
20import javax.crypto.NoSuchPaddingException;
21import javax.crypto.SecretKey;
22import javax.crypto.spec.SecretKeySpec;
23
24import org.expeditee.gui.Frame;
25import org.expeditee.io.ExpReader;
26import org.expeditee.items.Text;
27import org.expeditee.settings.auth.secrets.KeyList;
28import org.ngikm.Util.ThrowingFunction;
29import org.ngikm.cryptography.CryptographyConstants;
30
31public class EncryptedExpReader extends ExpReader implements CryptographyConstants {
32 static final String ENCRYPTED_EXP_FLAG = "EncryptedExp";
33 private SecretKey personalKey;
34 private List<SecretKey> multiKey;
35 private boolean accessDenied = false;
36 private boolean usePersonalKey;
37
38 public EncryptedExpReader(final String frameName, final boolean usePersonalKey) throws UnsupportedEncodingException {
39 super(frameName);
40 this.usePersonalKey = usePersonalKey;
41 }
42
43 public static boolean isEncryptedExpediteeFile(final String path) throws IOException {
44 final BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(path), "UTF-8"));
45 final String firstLine = in.readLine();
46 in.close();
47 return firstLine.startsWith(ENCRYPTED_EXP_FLAG);
48 }
49
50 public int getVersionEnc(String fullpath) {
51 try {
52 BufferedReader reader;
53 if (usePersonalKey) {
54 reader = new EncryptedProfileLineReader(new BufferedReader(new FileReader(fullpath)));
55 } else {
56 reader = new EncryptedLineReader(new BufferedReader(new FileReader(fullpath)));
57 }
58 String next = "";
59 // First read the header lines until we get the version number
60 while (reader.ready() && !(next = reader.readLine()).equals("Z")) {
61 if (isValidLine(next)) {
62 Character tag = getTag(next);
63 String value = getValue(next);
64 if (tag.equals('V')) {
65 reader.close();
66 return Integer.parseInt(value);
67 }
68 }
69 }
70 reader.close();
71 } catch (Exception e) {
72 }
73 return -1;
74 }
75
76 @Override
77 public Frame readFrame(final String fullPath) throws IOException {
78 final Reader in = new InputStreamReader(new FileInputStream(fullPath), "UTF-8");
79 if (usePersonalKey) {
80 return readFrame(new EncryptedProfileLineReader(new BufferedReader(in)));
81 } else {
82 return readFrame(new EncryptedLineReader(new BufferedReader(in)));
83 }
84 }
85
86 @Override
87 public Frame readFrame(final BufferedReader reader) throws IOException {
88 if (accessDenied) { return null; }
89 else return super.readFrame(reader);
90 }
91
92 private static byte[] DecryptSymmetric(final byte[] toDecrypt, final SecretKey key) {
93 try {
94 final Cipher cipher = Cipher.getInstance(SymmetricAlgorithm + SymmetricAlgorithmParameters);
95 cipher.init(Cipher.DECRYPT_MODE, key);
96 final byte[] decryptedBytes = cipher.doFinal(toDecrypt);
97 int indexOfZero = decryptedBytes.length - 1;
98 for (int i = decryptedBytes.length - 1; i >= 0; i--) {
99 if (decryptedBytes[i] != (byte) 0) {
100 indexOfZero = i + 1;
101 break;
102 }
103 }
104 if (indexOfZero < 0) { return decryptedBytes; }
105 else { return Arrays.copyOf(decryptedBytes, indexOfZero); }
106 } catch (final NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
107 | IllegalBlockSizeException | BadPaddingException e) {
108 e.printStackTrace();
109 return null;
110 }
111 }
112
113 private class EncryptedProfileLineReader extends BufferedReader {
114
115 public EncryptedProfileLineReader(final Reader in) {
116 super(in);
117 }
118
119 @Override
120 /**
121 * Reads a line from an encrypted exp file that uses profile encryption (single key; personal key)
122 * Returns that line to process, null if the currently logged in users personal key is not the appropriate one (access denied).
123 */
124 public String readLine() throws IOException {
125 // read encrypted line
126 final String line = super.readLine();
127
128 if (line.isEmpty()) { return ""; }
129 if (line.startsWith(ENCRYPTED_EXP_FLAG)) {
130 // record/overwrite previous personal key then ignore this line by recursing
131 final Text text = KeyList.PersonalKey.get();
132 final byte[] keyBytes = Base64.getDecoder().decode(text.getData().get(0));
133 personalKey = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
134 return readLine();
135 }
136
137 // decrypt line and return result
138 final byte[] toDecrypt = Base64.getDecoder().decode(line);
139 final byte[] decrypted = DecryptSymmetric(toDecrypt, personalKey);
140 if (decrypted == null) {
141 accessDenied = true;
142 return null; // access denied
143 } else {
144 final String decryptedLine = new String(decrypted);
145 if (decryptedLine.startsWith("Z")) { return decryptedLine.trim(); }
146 else { return decryptedLine; }
147 }
148 }
149 }
150
151 private class EncryptedLineReader extends BufferedReader {
152
153 public EncryptedLineReader(final Reader in) {
154 super(in);
155 }
156
157 @Override
158 /**
159 * Reads a line from an encrypted exp file that uses (potentially multiple) labeled keys
160 * Returns that line to process, null if the ...
161 */
162 public String readLine() throws IOException {
163 // read encrypted line
164 final String line = super.readLine();
165
166 if (line.isEmpty()) { return ""; }
167 if (line.startsWith(ENCRYPTED_EXP_FLAG)) {
168 // resolve labels to secret keys
169 final List<String> labels = Arrays.asList(line.split(" ")).stream().skip(1).collect(Collectors.toList());
170 final ThrowingFunction<String, SecretKey, Exception> worker = new ThrowingFunction<String, SecretKey, Exception>() {
171 @Override
172 public SecretKey applyThrows(final String label) throws Exception {
173 return Authenticator.getInstance().getSecretKey(label, System.getProperty("password"));
174 }
175 };
176 multiKey = labels.stream().map(l -> {
177 try {
178 return worker.apply(l);
179 } catch (final Exception e) {
180 return null;
181 }
182 }).collect(Collectors.toList());
183
184 // confirm you have all the keys necessary for decryption
185 if (multiKey.contains(null)) {
186 return null;
187 }
188
189 // move onto the next line
190 return readLine();
191 }
192
193 // decrypt line and return result
194 final byte[] toDecrypt = Base64.getDecoder().decode(line);
195 byte[] decryptedBytes = null;
196 for (final SecretKey key: multiKey) {
197 decryptedBytes = DecryptSymmetric(toDecrypt, key);
198 if (decryptedBytes == null) { return null; }
199 }
200 final String decrypted = new String(decryptedBytes);
201 if (decrypted.startsWith("Z")) { return decrypted.trim(); }
202 else { return decrypted; }
203 }
204 }
205}
Note: See TracBrowser for help on using the repository browser.