source: trunk/src/org/expeditee/auth/Authenticator.java@ 1253

Last change on this file since 1253 was 1253, checked in by bln4, 5 years ago
File size: 15.9 KB
Line 
1package org.expeditee.auth;
2
3import java.io.File;
4import java.io.FileInputStream;
5import java.io.FileNotFoundException;
6import java.io.FileOutputStream;
7import java.io.IOException;
8import java.io.InputStream;
9import java.nio.file.Path;
10import java.nio.file.Paths;
11import java.security.KeyFactory;
12import java.security.KeyStore;
13import java.security.KeyStore.SecretKeyEntry;
14import java.security.KeyStoreException;
15import java.security.NoSuchAlgorithmException;
16import java.security.NoSuchProviderException;
17import java.security.PublicKey;
18import java.security.SecureRandom;
19import java.security.UnrecoverableEntryException;
20import java.security.cert.CertificateException;
21import java.security.spec.InvalidKeySpecException;
22import java.security.spec.X509EncodedKeySpec;
23import java.sql.Connection;
24import java.sql.DriverManager;
25import java.sql.PreparedStatement;
26import java.sql.ResultSet;
27import java.sql.SQLException;
28import java.util.Arrays;
29import java.util.Base64;
30import java.util.Collection;
31import java.util.HashMap;
32import java.util.Map;
33import java.util.Scanner;
34import java.util.stream.Stream;
35
36import javax.crypto.SecretKey;
37import javax.crypto.spec.SecretKeySpec;
38
39import org.expeditee.actions.Actions;
40import org.expeditee.auth.tags.Constants;
41import org.expeditee.core.Dimension;
42import org.expeditee.core.Point;
43import org.expeditee.gio.EcosystemManager;
44import org.expeditee.gio.GraphicsManager;
45import org.expeditee.gio.InputManager;
46import org.expeditee.gio.InputManager.WindowEventListener;
47import org.expeditee.gio.InputManager.WindowEventType;
48import org.expeditee.gio.gesture.StandardGestureActions;
49import org.expeditee.gui.Browser;
50import org.expeditee.gui.DisplayController;
51import org.expeditee.gui.Frame;
52import org.expeditee.gui.FrameIO;
53import org.expeditee.gui.FrameUtils;
54import org.expeditee.gui.MessageBay;
55import org.expeditee.io.ExpReader;
56import org.expeditee.items.Item;
57import org.expeditee.items.ItemUtils;
58import org.expeditee.items.Text;
59import org.expeditee.settings.Settings;
60import org.expeditee.settings.UserSettings;
61import org.expeditee.settings.identity.secrets.KeyList;
62import org.ngikm.cryptography.CryptographyConstants;
63
64public final class Authenticator implements CryptographyConstants {
65
66 // The frame number of the frame containing the current authenticated users public key.
67 public static int CREDENTIALS_FRAME = 13;
68
69 public static boolean Authenticated = false;
70
71 private KeyStore keyStore;//KeyStore.getInstance(KeystoreType);
72
73 private static final byte[] TRUE = "yes".getBytes();
74 private static final byte[] FALSE = "no".getBytes();
75 private static final String KEYSTOREFILENAME = "keystore.ks" + File.separator;
76
77 private static Authenticator instance;
78
79 public static Authenticator getInstance() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, IOException, ClassNotFoundException, SQLException {
80 if (instance == null) { instance = new Authenticator(); }
81 return instance;
82 }
83
84 private Authenticator() throws KeyStoreException, FileNotFoundException, IOException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, SQLException {
85 try {
86 keyStore = KeyStore.getInstance(KeystoreType, "SunJSSE");
87 } catch (NoSuchProviderException e) {
88 e.printStackTrace();
89 return;
90 }
91
92 UserSettings.setupDefaultFolders();
93
94 // initialise keystore and actions
95 loadKeystore();
96 Actions.LoadMethods(org.expeditee.auth.Actions.class);
97
98 // draw the window
99 GraphicsManager g = EcosystemManager.getGraphicsManager();
100 g.setWindowLocation(new Point(50, 50));
101 DisplayController.Init();
102 g.setWindowSize(new Dimension(UserSettings.InitialWidth.get(), UserSettings.InitialHeight.get()));
103 setInputManagerWindowRoutines();
104
105 // Load documentation and start pages
106 FrameUtils.extractResources(false);
107
108 // Load fonts before loading any frames so the items on the frames will be able to access their fonts
109 Text.InitFonts();
110
111 // initialing settings does not require a user profile established
112 Settings.Init();
113
114 // navigate to authentication frame
115 Frame authFrame = FrameIO.LoadFrame("authentication1");
116 DisplayController.setCurrentFrame(authFrame, true);
117
118 // set initial values
119 Stream<Text> usernameItemsStream = authFrame.getTextItems().stream().filter(t -> t.getData() != null && t.getData().contains("txtUsername"));
120 Stream<Text> passwordItemsStream = authFrame.getTextItems().stream().filter(t -> t.getData() != null && t.getData().contains("txtPassword"));
121 usernameItemsStream.forEach(txtUsername -> txtUsername.setText(System.getProperty("startinguser.name", "")));
122 passwordItemsStream.forEach(txtPassword -> { txtPassword.setText(""); txtPassword.invalidateAll(); });
123
124 MessageBay.warningMessages(org.expeditee.actions.Actions.Init());
125
126 // class load database classes
127 Class.forName("org.sqlite.JDBC");
128 }
129
130 private void loadKeystore()
131 throws IOException, NoSuchAlgorithmException, CertificateException, FileNotFoundException {
132 final File keyStoreFile = new File(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME);
133 if (!keyStoreFile.exists()) {
134 keyStore.load(null, Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
135 } else {
136 try (final InputStream in = new FileInputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME)) {
137 keyStore.load(in, Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
138 }
139 }
140 }
141
142 final void loadMailFromDirectory(Path contactDir) throws SQLException {
143 // Load in all mail.
144 Connection c = DriverManager.getConnection("jdbc:sqlite:" + contactDir.resolve("expmail.db"));
145 String sql = "SELECT * FROM EXPMAIL";
146 PreparedStatement query = c.prepareStatement(sql);
147 ResultSet allMail = query.executeQuery();
148
149 // Construct all mail objects using content from database.
150 while(allMail.next()) {
151 String timestamp = allMail.getString("time");
152 String from = allMail.getString("snd");
153 String to = allMail.getString("rec");
154 String msg = allMail.getString("msg");
155 String msg2 = allMail.getString("msg2");
156 String[] opts = allMail.getString("opts").split(",");
157 opts[0] = opts[0].replace("[", "");
158 opts[opts.length - 1] = opts[opts.length - 1].replace("]", "");
159 String[] optsVal = allMail.getString("optsval").split(",");
160 optsVal[0] = optsVal[0].replace("[", "");
161 optsVal[optsVal.length - 1] = optsVal[optsVal.length - 1].replace("]", "");
162
163 Map<String, String> options = new HashMap<String, String>();
164 for (int i = 0, o = 0; i < opts.length && o < optsVal.length; i++, o++) {
165 String key = opts[i].trim();
166 String val = optsVal[o].trim();
167 options.put(key, val);
168 }
169
170 Mail.addEntry(new Mail.MailEntry(timestamp, from, to, msg, msg2, options));
171 }
172
173 // Disconnect from database.
174 allMail.close();
175 query.close();
176 c.close();
177 }
178
179 final void loadMailDatabase() throws SQLException {
180 Path contactsPath = Paths.get(FrameIO.CONTACTS_PATH);
181 File[] contacts = contactsPath.toFile().listFiles();
182 for (int i = 0; i < contacts.length; i++) {
183 if (contacts[i].isDirectory()) {
184 Path contact = Paths.get(contacts[i].getAbsolutePath());
185 loadMailFromDirectory(contact);
186 }
187 }
188 }
189
190 final SecretKey getSecretKey(final String label, final String password) throws NoSuchAlgorithmException, KeyStoreException {
191
192 char[] password_ca = password.toCharArray();
193 //final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(password_ca);
194
195 SecretKey secret_key;
196 try {
197 //SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(label, entryPassword);
198 //secret_key = entry.getSecretKey();
199 secret_key = (SecretKey) keyStore.getKey(label, password_ca);
200 } catch (final UnrecoverableEntryException e) {
201 secret_key = null;
202 }
203
204 return secret_key;
205 }
206
207 final void putKey(final String label, final String password, final SecretKey key) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
208 final KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(key);
209 final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(password.toCharArray());
210 keyStore.setEntry(label, entry, entryPassword);
211 keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
212 }
213
214 final boolean confirmIntergalaticNumber(final String username, final String email, final String intergalacticNumber) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, FileNotFoundException, IOException {
215 try {
216 final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(intergalacticNumber.toCharArray());
217 final KeyStore.SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(email + username, entryPassword);
218 if (entry == null) {
219 return false;
220 } else if (entry.getSecretKey().getEncoded() == TRUE) {
221 keyStore.deleteEntry(email + username);
222 keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
223 return true;
224 } else { return false; }
225 } catch (final UnrecoverableEntryException e) {
226 return false;
227 }
228 }
229
230 final String newIntergalacticNumber(final String username, final String email) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
231 // generate intergalactic number
232 final SecureRandom rand = new SecureRandom();
233 final byte[] intergalacticNumberBytes = new byte[20];
234 rand.nextBytes(intergalacticNumberBytes);
235 final String intergalacticNumber = Base64.getEncoder().encodeToString(intergalacticNumberBytes);
236
237 // store intergalactic number
238 final KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(new SecretKeySpec(TRUE, SymmetricAlgorithm));
239 final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(intergalacticNumber.toCharArray());
240 keyStore.setEntry(email + username, entry, entryPassword);
241 keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
242
243 return intergalacticNumber;
244 }
245
246 final PublicKey getPublicKey(String username) throws InvalidKeySpecException, NoSuchAlgorithmException, FileNotFoundException {
247 // load in frame with public key on it.
248 String credentialsFramesetPath = FrameIO.CONTACTS_PATH + username + "-credentials" + File.separator;
249 if (!new File(credentialsFramesetPath).exists()) {
250 return null;
251 }
252 Scanner in = new Scanner(new File(credentialsFramesetPath + "credentials.inf"));
253 String credentialsFrameNumber = in.nextLine().replace(ExpReader.EXTENTION, "");
254 in.close();
255 Frame frame = FrameIO.LoadFrame(username + "-credentials" + credentialsFrameNumber, FrameIO.CONTACTS_PATH);
256 if (frame == null) {
257 return null;
258 }
259
260 // obtain public key from frame
261 Collection<Item> canditates = org.expeditee.auth.Actions.getByContent(frame, "PublicKey");
262 String keyEncoded = "";
263 for (Item i: canditates) {
264 if (i.getData() != null) {
265 keyEncoded = i.getData().get(0);
266 }
267 }
268 if (keyEncoded.isEmpty()) {
269 return null;
270 }
271 byte[] keyBytes = Base64.getDecoder().decode(keyEncoded);
272 return KeyFactory.getInstance(AsymmetricAlgorithm).generatePublic(new X509EncodedKeySpec(keyBytes));
273 }
274
275 final void markRequestedColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
276 KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(new SecretKeySpec(TRUE, SymmetricAlgorithm));
277 KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
278 keyStore.setEntry(username + "colleaguesRequested", entry, entryPassword);
279 keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
280 }
281
282 final void clearRequestedColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
283 KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(new SecretKeySpec(FALSE, SymmetricAlgorithm));
284 KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
285 keyStore.setEntry(username + "colleaguesRequested", entry, entryPassword);
286 keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), Constants.CREDENTIALS_KEYSTORE_PASSWORD.toCharArray());
287 }
288
289 final boolean hasRequestedColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
290 String alias = username + "colleaguesRequested";
291 if (!keyStore.containsAlias(alias)) {
292 return false;
293 } else {
294 KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
295 KeyStore.SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(alias, entryPassword);
296 return Arrays.equals(entry.getSecretKey().getEncoded(), TRUE);
297 }
298 }
299
300// final void putColleagues(String username, String[] colleagues) throws KeyStoreException {
301// String alias = username + "colleagues";
302// final SecretKeySpec secretKeySpec = new SecretKeySpec((colleagues[0] + System.getProperty("line.separator") + colleagues[1]).getBytes(), SymmetricAlgorithm);
303// KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(secretKeySpec);
304// KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
305// keyStore.setEntry(alias, entry, entryPassword);
306// }
307//
308// final String[] getColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
309// String alias = username + "colleagues";
310// if (!keyStore.containsAlias(alias)) {
311// return null;
312// } else {
313// KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
314// KeyStore.SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(alias, entryPassword);
315// byte[] colleaguesEncoded = entry.getSecretKey().getEncoded();
316// String colleagues = new String(colleaguesEncoded);
317// return colleagues.split(System.getProperty("line.separator"));
318// }
319// }
320
321 private static void setInputManagerWindowRoutines() {
322 InputManager manager = EcosystemManager.getInputManager();
323
324 // Refresh the layout when the window resizes
325 manager.addWindowEventListener(new WindowEventListener() {
326 @Override
327 public void onWindowEvent(WindowEventType type)
328 {
329 if (type != WindowEventType.WINDOW_RESIZED) {
330 return;
331 }
332 DisplayController.refreshWindowSize();
333 FrameIO.RefreshCacheImages();
334 for (Frame frame : DisplayController.getFrames()) {
335 if (frame != null) {
336 ItemUtils.Justify(frame);
337 frame.refreshSize();
338 }
339 }
340 DisplayController.requestRefresh(false);
341 }
342 });
343
344 manager.addWindowEventListener(new WindowEventListener() {
345 @Override
346 public void onWindowEvent(WindowEventType type)
347 {
348 if (type != WindowEventType.MOUSE_EXITED_WINDOW) {
349 return;
350 }
351 StandardGestureActions.mouseExitedWindow();
352 }
353 });
354
355 manager.addWindowEventListener(new WindowEventListener() {
356 @Override
357 public void onWindowEvent(WindowEventType type)
358 {
359 if (type != WindowEventType.MOUSE_ENTERED_WINDOW) {
360 return;
361 }
362 StandardGestureActions.mouseEnteredWindow();
363 }
364 });
365
366 manager.addWindowEventListener(new WindowEventListener() {
367 @Override
368 public void onWindowEvent(WindowEventType type)
369 {
370 if (type != WindowEventType.WINDOW_CLOSED) {
371 return;
372 }
373 if (Browser._theBrowser != null) {
374 Browser._theBrowser.exit();
375 }
376 }
377 });
378 }
379}
Note: See TracBrowser for help on using the repository browser.