Ignore:
Timestamp:
05/17/19 14:37:12 (5 years ago)
Author:
bln4
Message:

It is now possible to complete the process of recovering access to a Expeditee account. Further work, in the form of frames in the authentication frameset, are to follow.
A refactoring/tidy up has also been completed.

Location:
trunk/src/org/expeditee/auth/account
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/expeditee/auth/account/Authenticate.java

    r1359 r1363  
    2525import org.expeditee.auth.Actions;
    2626import org.expeditee.auth.AuthenticatorBrowser;
    27 import org.expeditee.auth.gui.MailBay;
     27import org.expeditee.auth.mail.gui.MailBay;
    2828import org.expeditee.auth.tags.AuthenticationTag;
    2929import org.expeditee.gui.Browser;
     
    4141public class Authenticate implements CryptographyConstants {
    4242
     43        /**
     44         * Given a username and password, potentially login. 
     45         * @param userdata
     46         * @return AuthenticationResult.SuccessLogin if login works, AuthenticationResult.ErrorLoginNobody or AuthenticationResult.ErrorLoginUsernamePasswordCombo otherwise.
     47         */
    4348        public static AuthenticationResult login(Map<AuthenticationTag, String> userdata) {
    4449                String username = userdata.get(AuthenticationTag.Username);
     
    7681                                        if(data != null && data.contains("MultiuserCredentials")) {
    7782                                                AuthenticatorBrowser.CREDENTIALS_FRAME = f.getNumber();
     83                                        } else if (data != null && data.contains("PasswordColleagues")) {
     84                                                AuthenticatorBrowser.PASSWORD_RECOVERY_FRAME = f.getNumber();
     85                                        } else if (data != null && data.contains("SecretsFrame")) {
     86                                                AuthenticatorBrowser.SECRETS_FRAME = f.getNumber();
    7887                                        }
    79                                 }
     88                                }
    8089                        }
    8190                       
     
    103112                                        byte[] keyBytes = Base64.getDecoder().decode(keyEncoded);
    104113                                        PrivateKey key = KeyFactory.getInstance(AsymmetricAlgorithm).generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
    105                                         org.expeditee.auth.Mail.checkMail(key);
     114                                        org.expeditee.auth.mail.Mail.checkMail(key);
    106115                                } else {
    107116                                        res.additionalInfo.add("No private key present: your communication with other Expeditee users will be limited until this is resolved.");
     
    129138        }
    130139       
     140        /**
     141         * Logs out the current authenticated user.
     142         * @return AuthenticationResult.SuccessLogout to signal the logout has occured.
     143         */
    131144        public static AuthenticationResult logout() {
    132145                // Set user to nobody.
  • trunk/src/org/expeditee/auth/account/Create.java

    r1356 r1363  
    125125                return CreateResult.SuccessCreateAccount;
    126126        }
    127        
    128         public static CreateResult createAlternativeAccess(Map<AuthenticationTag, String> userdata) {
    129                 String username = userdata.get(AuthenticationTag.Username);
    130                 FrameIO.CreateFrame(username, null, "default1");
    131                 return null;
    132         }
    133                
     127                       
    134128        public enum CreateResult {
    135129                SuccessCreateAccount ("Account created."),
     
    193187                        FrameIO.migrateFrame(credentialsFrame, destinationFile);
    194188                        //      pwcolleagues.inf file.
    195                         String pwColleaguesPath = credentialsDir.getAbsolutePath() + File.separator + "pwcolleagues.inf";
    196                         File pwColleaguesFile = new File(pwColleaguesPath);
     189                        File pwColleaguesFile = Paths.get(FrameIO.PROFILE_PATH).resolve(username).resolve("pwcolleagues.inf").toFile();
    197190                        pwColleaguesFile.createNewFile();
    198191                        out = new FileWriter(pwColleaguesFile);
     
    234227                        }
    235228                });
    236                 notifiers.put("settings.identity.passwordrecovery", frame -> {
     229                notifiers.put("settings.identity.passwordrecovery", frame -> {
     230                        frame.addToData("PasswordColleagues");
    237231                        AuthenticatorBrowser.PASSWORD_RECOVERY_FRAME = frame.getNumber();
    238232                });
    239                
     233                notifiers.put("settings.identity.secrets", frame -> {
     234                        frame.addToData("SecretsFrame");
     235                        AuthenticatorBrowser.SECRETS_FRAME = frame.getNumber();
     236                });
    240237               
    241238                // Create users profile
  • trunk/src/org/expeditee/auth/account/Password.java

    r1357 r1363  
    11package org.expeditee.auth.account;
    22
     3import java.io.File;
    34import java.io.FileNotFoundException;
    45import java.io.IOException;
     6import java.nio.file.Path;
     7import java.nio.file.Paths;
    58import java.security.KeyStoreException;
    69import java.security.NoSuchAlgorithmException;
     10import java.security.SecureRandom;
    711import java.security.cert.CertificateException;
    812import java.sql.SQLException;
     13import java.util.Base64;
     14import java.util.Collection;
     15import java.util.HashMap;
     16import java.util.Iterator;
    917import java.util.Map;
    1018import java.util.Properties;
     19import java.util.Scanner;
    1120
    1221import javax.crypto.SecretKey;
     22import javax.crypto.spec.SecretKeySpec;
    1323import javax.mail.Message;
    1424import javax.mail.MessagingException;
     
    1626import javax.mail.Session;
    1727import javax.mail.Transport;
     28import javax.mail.internet.AddressException;
    1829import javax.mail.internet.InternetAddress;
    1930import javax.mail.internet.MimeMessage;
    2031
    2132import org.expeditee.auth.AuthenticatorBrowser;
     33import org.expeditee.auth.mail.Mail;
     34import org.expeditee.auth.mail.Mail.MailEntry;
    2235import org.expeditee.auth.tags.AuthenticationTag;
    2336import org.expeditee.gui.DisplayController;
     37import org.expeditee.gui.Frame;
    2438import org.expeditee.gui.FrameIO;
    2539import org.expeditee.gui.MessageBay;
     40import org.expeditee.items.Text;
     41import org.expeditee.settings.UserSettings;
     42import org.expeditee.settings.identity.passwordrecovery.Colleagues;
     43import org.expeditee.settings.identity.secrets.KeyList;
     44import org.expeditee.stats.Formatter;
    2645import org.ngikm.cryptography.CryptographyConstants;
    2746
     47import com.codahale.shamir.Scheme;
     48
    2849public class Password implements CryptographyConstants {
    29         /*
    30          * Changes the recorded password for a user in the key store.
     50        /**
     51         * Changes the recorded password for a user in the key store; given the username signaling whose password to change, along with the existing and new password.
    3152         */
    3253        public static void changePassword(Map<AuthenticationTag, String> userdata) throws NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, IOException, ClassNotFoundException, SQLException {
     
    4566        }
    4667
     68        /**
     69         * Generates a intergalaictic number for a specified user and emails that number using the specified email.
     70         * @param userData
     71         */
    4772        public static void generateAndDeliverIntergalacticNumber(Map<AuthenticationTag, String> userData) {
    4873                String username = userData.get(AuthenticationTag.Username);
     
    5782                        sb.append("If it was you who made this request, the following string of characters is your intergalactic number: " + intergalacticNumber + nl);
    5883                       
    59                         // Establish properties for email.
    60                         Properties properties = System.getProperties();
    61                         properties.setProperty("mail.transport.protocol", "smtp");
    62                         properties.setProperty("mail.smtp.host", "smtp.gmail.com");
    63                         properties.setProperty("mail.smtp.port", "465");
    64                         properties.setProperty("mail.smtp.starttls.enable", "true");
    65                         properties.setProperty("mail.smtp.auth", "true");
    66                         properties.setProperty("mail.smtp.debug", "true");
    67                         properties.setProperty("mail.smtp.auth", "true");
    68                         properties.setProperty("mail.smtp.socketFactory.port", "465");
    69                         properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
    70                         properties.setProperty("mail.smtp.socketFactory.fallback", "false");
    71                        
    72                         Session session = Session.getDefaultInstance(properties, new javax.mail.Authenticator() {
    73                                 @Override
    74                                 protected PasswordAuthentication getPasswordAuthentication() {
    75                                         return new PasswordAuthentication("noreply.expeditee", "intergalacticnumber");
    76                                 };
    77                         });
    78                        
    79                         // construct email message
    80                         final MimeMessage message = new MimeMessage(session);
    81                         message.setFrom(new InternetAddress("[email protected]"));
    82                         message.addRecipient(Message.RecipientType.TO, new InternetAddress(email));
    83                         message.setSubject("Expeditee Password Recovery");
    84                         message.setText(sb.toString());
    85                        
    86                         // send email message
    87                         Transport.send(message);               
     84                        sendEmail(email, sb);           
    8885                } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | ClassNotFoundException
    8986                                | IOException | SQLException | MessagingException e) {
     
    9289        }
    9390       
    94         public static void confirmIntergalacticNumberAndAlertColleagues(Map<AuthenticationTag, String> userData, String[] colleagues) {
    95                 System.err.println("Colleague One: " + colleagues[0] + " @" + colleagues[2]);
    96                 System.err.println("Colleague Two: " + colleagues[1] + " @" + colleagues[3]);
     91        /**
     92         * Confirms that the specified intergalaictic number matches the one of file for the specified username.
     93         * Passing this test it then alerts the users pw colleagues through a one-off secure Expeditee message.
     94         * @param tags
     95         */
     96        public static void confirmIntergalacticNumberAndAlertColleagues(Map<AuthenticationTag, String> tags) {
     97                // Confirm intergalactic numbers match
     98                String username = tags.get(AuthenticationTag.Username);
     99                String intergalacticNumber = tags.get(AuthenticationTag.IntergalacticNumber);
     100                boolean match = false;
     101                try {
     102                        match = AuthenticatorBrowser.getInstance().confirmIntergalaticNumber(username, intergalacticNumber);
     103                } catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | ClassNotFoundException
     104                                | IOException | SQLException e) {
     105                        e.printStackTrace();
     106                        return;
     107                }
     108                if (!match) {
     109                        MessageBay.errorMessage("The provided identity number does not match the one stored on file.");
     110                        return;
     111                }
     112               
     113                // Get colleagues to distribute messages too.
     114                String[] colleagues = getPasswordColleaguesFromUsername(username);
     115                //      Send secure message to colleague one
     116                String colleagueOne = colleagues[0];
     117                String time = Formatter.getDateTime();
     118                String topic = "Password Recovery for " + username;
     119                String message = "Your colleague " + username + " would like you to help them recover access to their account.";
     120                Map<String, String> options = new HashMap<String, String>();
     121                options.put("Provide assistance", "AuthEmailPasswordShare " + username);
     122                MailEntry mail = new MailEntry(time, username, colleagueOne, topic, message, options);
     123                Mail.sendOneOffMail(mail, colleagueOne, Base64.getDecoder().decode(intergalacticNumber));
     124               
     125                //      Send secure message to colleague two
     126                String colleagueTwo = colleagues[1];
     127                Mail.sendOneOffMail(mail, colleagueTwo, Base64.getDecoder().decode(intergalacticNumber));
     128               
     129                String nl = System.getProperty("line.separator");
     130                StringBuilder sb = new StringBuilder();
     131                sb.append("You are receiving this email because one of your Expeditee contacts has sent you a one-off secure message." + nl);
     132                sb.append("When you log into Expeditee and check your mail it will be there waiting for you." + nl);
     133                sb.append("You will need the following key to read this message: " + nl);
     134                sb.append(intergalacticNumber);
     135                try {
     136                        //      Send email with key to colleague one
     137                        String colleagueOneEmail = colleagues[2];
     138                        sendEmail(colleagueOneEmail, sb);
     139                        //      Send email with key to colleague two
     140                        String colleagueTwoEmail = colleagues[3];
     141                        sendEmail(colleagueTwoEmail, sb);
     142                } catch (MessagingException e) {
     143                        e.printStackTrace();
     144                }               
     145        }
     146       
     147        private static String[] getPasswordColleaguesFromUsername(String username) {
     148                Path credentialsFilePath = Paths.get(FrameIO.PROFILE_PATH).resolve(username).resolve("pwcolleagues.inf");
     149                String fileName = null;
     150                if (credentialsFilePath.toFile().exists()) {
     151                        try (Scanner in = new Scanner(credentialsFilePath)) {
     152                                fileName = in.nextLine();
     153                        } catch (IOException e) {
     154                                MessageBay.errorMessage("Unable to password colleague frame for specified user, are they registered on this computer?");
     155                                return null;
     156                        }
     157                } else {
     158                        MessageBay.errorMessage("Unable to password colleague frame for specified user, are they registered on this computer?");
     159                        return null;
     160                }
     161               
     162                int number = Integer.parseInt(fileName.replace(".exp", ""));
     163                Frame pwColleagueFrame = FrameIO.LoadFrame(username + number, FrameIO.PROFILE_PATH);
     164                Collection<Text> textItems = pwColleagueFrame.getTextItems();
     165                textItems.removeIf(text -> !text.getText().startsWith("Colleague"));
     166               
     167                String[] ret = new String[4];
     168                Iterator<Text> it = textItems.iterator();
     169                while(it.hasNext()) {
     170                        String content = it.next().getText().toLowerCase().trim();
     171                        if (content.contains("colleague_one:")) {
     172                                ret[0] = content.replace("colleague_one:", "").trim();
     173                        } else if (content.contains("colleague_two:")) {
     174                                ret[1] = content.replace("colleague_two:", "").trim();
     175                        }
     176                }
     177                               
     178                // find colleague one email
     179                Path credentialsDirectoryPath = UserSettings.PublicAndPrivateResources
     180                                ? Paths.get(FrameIO.PARENT_FOLDER).resolve("resources-" + username)
     181                                : Paths.get(FrameIO.PARENT_FOLDER);
     182                credentialsDirectoryPath = credentialsDirectoryPath.resolve("contacts").resolve(ret[0] + "-credentials");
     183                try (Scanner in = new Scanner(credentialsDirectoryPath.resolve("credentials.inf").toFile())) {
     184                        int parseInt = Integer.parseInt(in.nextLine().replace(".exp", ""));
     185                        Frame frame = FrameIO.LoadFrame(ret[0] + "-credentials" + parseInt, credentialsDirectoryPath.toAbsolutePath().getParent().toString() + File.separator);
     186                        textItems = frame.getTextItems();
     187                        textItems.removeIf(text -> !text.getText().startsWith("Email:"));
     188                        ret[2] = textItems.iterator().next().getText().replace("Email:", "").trim();
     189                } catch (FileNotFoundException e) {
     190                        MessageBay.errorMessage("You do not appear to have contact with your nominated password colleague: " + ret[0]);
     191                        return null;
     192                }
     193               
     194               
     195                // find colleague two email
     196                credentialsDirectoryPath = UserSettings.PublicAndPrivateResources
     197                                ? Paths.get(FrameIO.PARENT_FOLDER).resolve("resources-" + username)
     198                                : Paths.get(FrameIO.PARENT_FOLDER);
     199                credentialsDirectoryPath = credentialsDirectoryPath.resolve("contacts").resolve(ret[1] + "-credentials");
     200                try (Scanner in = new Scanner(credentialsDirectoryPath.resolve("credentials.inf").toFile())) {
     201                        int parseInt = Integer.parseInt(in.nextLine().replace(".exp", ""));
     202                        Frame frame = FrameIO.LoadFrame(ret[1] + "-credentials" + parseInt, credentialsDirectoryPath.toAbsolutePath().getParent().toString() + File.separator);
     203                        textItems = frame.getTextItems();
     204                        textItems.removeIf(text -> !text.getText().startsWith("Email:"));
     205                        ret[3] = textItems.iterator().next().getText().replace("Email:", "").trim();
     206                } catch (FileNotFoundException e) {
     207                        MessageBay.errorMessage("You do not appear to have contact with your nominated password colleague: " + ret[1]);
     208                        return null;
     209                }
     210               
     211                return ret;
     212        }
     213       
     214
     215        public static void sendEmail(String email, StringBuilder sb) throws MessagingException, AddressException {
     216                // Establish properties for email.
     217                Properties properties = System.getProperties();
     218                properties.setProperty("mail.transport.protocol", "smtp");
     219                properties.setProperty("mail.smtp.host", "smtp.gmail.com");
     220                properties.setProperty("mail.smtp.port", "465");
     221                properties.setProperty("mail.smtp.starttls.enable", "true");
     222                properties.setProperty("mail.smtp.auth", "true");
     223                properties.setProperty("mail.smtp.debug", "true");
     224                properties.setProperty("mail.smtp.auth", "true");
     225                properties.setProperty("mail.smtp.socketFactory.port", "465");
     226                properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
     227                properties.setProperty("mail.smtp.socketFactory.fallback", "false");
     228               
     229                Session session = Session.getDefaultInstance(properties, new javax.mail.Authenticator() {
     230                        @Override
     231                        protected PasswordAuthentication getPasswordAuthentication() {
     232                                return new PasswordAuthentication("noreply.expeditee", "intergalacticnumber");
     233                        };
     234                });
     235               
     236                // construct email message
     237                final MimeMessage message = new MimeMessage(session);
     238                message.setFrom(new InternetAddress("[email protected]"));
     239                message.addRecipient(Message.RecipientType.TO, new InternetAddress(email));
     240                message.setSubject("Expeditee Password Recovery");
     241                message.setText(sb.toString());
     242               
     243                // send email message
     244                Transport.send(message);
     245        }
     246
     247        public static void setPWColleagues(String colleagueOne, String colleagueTwo) {
     248                // Get needed text items.
     249                Frame pwRecoveryFrame = FrameIO.LoadFrame(UserSettings.UserName.get() + AuthenticatorBrowser.PASSWORD_RECOVERY_FRAME);
     250                Collection<Text> textItems = pwRecoveryFrame.getTextItems();
     251                textItems.removeIf(t -> !t.getText().toLowerCase().startsWith("colleague"));
     252               
     253                // Find colleague one and two text items.  Set appropriate values.
     254                Iterator<Text> it = textItems.iterator();
     255                while (it.hasNext()) {
     256                        Text text = it.next();
     257                        if (text.getText().toLowerCase().startsWith("colleague_one:")) {
     258                                text.setText("Colleague_one: " + colleagueOne);
     259                                Colleagues.Colleague_One.set(colleagueOne);
     260                        } else if (text.getText().toLowerCase().startsWith("colleague_two:")) {
     261                                text.setText("Colleague_two:" + colleagueTwo);
     262                                Colleagues.Colleague_Two.set(colleagueTwo);
     263                        }
     264                }
     265                FrameIO.ForceSaveFrame(pwRecoveryFrame);
     266               
     267                // Key to split and distribute
     268                String fullKey = KeyList.PersonalKey.get().getData().get(0);
     269                byte[] keyBytes = Base64.getDecoder().decode(fullKey);
     270               
     271                // Initialise Shamir
     272                int totalShares = 2;
     273                int requiredShares = 2;
     274                Scheme scheme = new Scheme(new SecureRandom(), totalShares, requiredShares);
     275               
     276                // Create shares
     277                Map<Integer, byte[]> shares = scheme.split(keyBytes);
     278                String colleagueOneShare = Base64.getEncoder().encodeToString(shares.get(1));
     279                String colleagueTwoShare = Base64.getEncoder().encodeToString(shares.get(2));
     280               
     281                // Distribute share zero to colleague one
     282                String time = org.expeditee.stats.Formatter.getDateTime();
     283                String sender = UserSettings.UserName.get();
     284                String topic = "Please help me secure my Expeditee account.";
     285                String message = "Run the below action to store a secret key that will help me recover access to my account should I ever loose it.";
     286                Map<String, String> options = new HashMap<String, String>();
     287                options.put("Store Secret Key for " + sender, "AuthAddSecretKey " + sender + "PersonalKeyShare " + colleagueOneShare);
     288                MailEntry mail = new MailEntry(time, sender, colleagueOne, topic, message, options);
     289                Mail.sendMail(mail, colleagueOne);
     290               
     291                // Distribute share one to colleague two
     292                options = new HashMap<String, String>();
     293                options.put("Store Secret Key for " + sender, "AuthAddSecretKey " + sender + "PersonalKeyShare " + colleagueTwoShare);
     294                mail = new MailEntry(time, sender, colleagueTwo, topic, message, options);
     295                Mail.sendMail(mail, colleagueTwo);
     296               
     297                MessageBay.displayMessage("PW Colleagues Set");
     298        }
     299
     300        public static void emailPasswordShare(String colleagueName) {
     301                Path credentialsDirectoryPath = Paths.get(FrameIO.CONTACTS_PATH).resolve(colleagueName + "-credentials");
     302                String colleagueEmail = null;
     303                try (Scanner in = new Scanner(credentialsDirectoryPath.resolve("credentials.inf").toFile())) {
     304                        int parseInt = Integer.parseInt(in.nextLine().replace(".exp", ""));
     305                        Frame frame = FrameIO.LoadFrame(colleagueName + "-credentials" + parseInt, credentialsDirectoryPath.toAbsolutePath().getParent().toString() + File.separator);
     306                        Collection<Text> textItems = frame.getTextItems();
     307                        textItems.removeIf(text -> !text.getText().startsWith("Email:"));
     308                        colleagueEmail = textItems.iterator().next().getText().replace("Email:", "").trim();
     309                } catch (FileNotFoundException e) {
     310                        MessageBay.errorMessage("You do not appear to have contact with: " + colleagueName);
     311                        return;
     312                }
     313               
     314                Frame secretsFrame = FrameIO.LoadFrame(UserSettings.UserName.get() + AuthenticatorBrowser.SECRETS_FRAME);
     315                Collection<Text> textItems = secretsFrame.getTextItems();
     316                textItems.removeIf(text -> !text.getText().toLowerCase().equals(colleagueName + "personalkeyshare"));
     317                String key = textItems.iterator().next().getData().get(0);
     318               
     319                String nl = System.getProperty("line.separator");
     320                StringBuilder sb = new StringBuilder();
     321                sb.append("In responce to your request for assistance regaining access to your Expeditee account, your colleague " + UserSettings.UserName.get() + " has provided you with the following key share:" + nl);
     322                sb.append(key + nl);
     323               
     324                try {
     325                        sendEmail(colleagueEmail, sb);
     326                } catch (MessagingException e) {
     327                        MessageBay.errorMessage("An error occured sending a email to your colleage " + colleagueName + " with the email " + colleagueEmail);
     328                }
     329        }
     330
     331        public static void regainAccountAccess(Map<AuthenticationTag, String> userData) {
     332                // Store shares in map
     333                Map<Integer, byte[]> contributingParts = new HashMap<Integer, byte[]>();
     334                contributingParts.put(1, Base64.getDecoder().decode(userData.get(AuthenticationTag.PasswordSliceOne)));
     335                contributingParts.put(2, Base64.getDecoder().decode(userData.get(AuthenticationTag.PasswordSliceTwo)));
     336               
     337                // initialise shamir
     338                int totalShares = 2;
     339                int requiredShares = 2;
     340                Scheme scheme = new Scheme(new SecureRandom(), totalShares, requiredShares);
     341               
     342                // perform joining
     343                byte[] join = scheme.join(contributingParts);
     344               
     345                try {
     346                        AuthenticatorBrowser.getInstance().putKey(userData.get(AuthenticationTag.Username), userData.get(AuthenticationTag.NewPassword), new SecretKeySpec(join, SymmetricAlgorithm));
     347                } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | ClassNotFoundException
     348                                | IOException | SQLException e) {
     349                        e.printStackTrace();
     350                }
     351               
     352                MessageBay.displayMessage("Your new password has been set.");
    97353        }
    98354}
Note: See TracChangeset for help on using the changeset viewer.