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

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

KeyStore instantiation now specifically uses the SunJSSE provider as all versions of Java from 5.0 onwards should have this included. Testing on David's PC to follow.

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