Ignore:
Timestamp:
01/30/19 12:49:25 (5 years ago)
Author:
bln4
Message:

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.

Location:
trunk/src/org/expeditee/auth
Files:
3 added
1 deleted
1 edited
2 copied

Legend:

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

    r1201 r1202  
    55import java.io.FileNotFoundException;
    66import java.io.FileOutputStream;
     7import java.io.FileWriter;
    78import java.io.IOException;
    89import java.io.InputStream;
     10import java.io.Writer;
     11import java.security.KeyFactory;
    912import java.security.KeyStore;
    1013import java.security.KeyStore.SecretKeyEntry;
    1114import java.security.KeyStoreException;
    1215import java.security.NoSuchAlgorithmException;
     16import java.security.PublicKey;
     17import java.security.SecureRandom;
    1318import java.security.UnrecoverableEntryException;
    1419import java.security.cert.CertificateException;
     20import java.security.spec.InvalidKeySpecException;
     21import java.security.spec.X509EncodedKeySpec;
     22import java.sql.Connection;
     23import java.sql.DriverManager;
     24import java.sql.ResultSet;
     25import java.sql.SQLException;
     26import java.sql.Statement;
     27import java.util.Arrays;
     28import java.util.Base64;
     29import java.util.Collection;
     30import java.util.HashMap;
     31import java.util.Map;
     32import java.util.stream.Stream;
    1533
    1634import javax.crypto.SecretKey;
    17 
     35import javax.crypto.spec.SecretKeySpec;
     36
     37import org.expeditee.actions.Actions;
     38import org.expeditee.core.Dimension;
     39import org.expeditee.core.Point;
     40import org.expeditee.gio.EcosystemManager;
     41import org.expeditee.gio.GraphicsManager;
     42import org.expeditee.gio.InputManager;
     43import org.expeditee.gio.InputManager.WindowEventListener;
     44import org.expeditee.gio.InputManager.WindowEventType;
     45import org.expeditee.gio.gesture.StandardGestureActions;
     46import org.expeditee.gui.Browser;
     47import org.expeditee.gui.DisplayController;
     48import org.expeditee.gui.Frame;
    1849import org.expeditee.gui.FrameIO;
     50import org.expeditee.gui.FrameUtils;
     51import org.expeditee.gui.MessageBay;
     52import org.expeditee.items.ItemUtils;
     53import org.expeditee.items.Text;
     54import org.expeditee.settings.Settings;
     55import org.expeditee.settings.UserSettings;
     56import org.expeditee.settings.auth.secrets.KeyList;
    1957import org.ngikm.cryptography.CryptographyConstants;
    2058
    2159public final class Authenticator implements CryptographyConstants {
    22         final KeyStore keyStore = KeyStore.getInstance(KeystoreType);
    23         private static final String keystoreFileName = FrameIO.PARENT_FOLDER + "keystore.ks" + File.separator;
    24        
    25         public Authenticator() throws KeyStoreException, FileNotFoundException, IOException, NoSuchAlgorithmException, CertificateException {
    26                 final File keyStoreFile = new File(keystoreFileName);
     60       
     61        // The frame number of the frame containing the current authenticated users public key.
     62        public static final int PUBLIC_KEY_FRAME = 4;
     63       
     64        private final KeyStore keyStore = KeyStore.getInstance(KeystoreType);
     65        private static final byte[] TRUE = "yes".getBytes();
     66        private static final byte[] FALSE = "no".getBytes();
     67        private static final String KEYSTOREFILENAME = "keystore.ks" + File.separator;
     68       
     69        private static Authenticator instance;
     70       
     71        public static Authenticator getInstance() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, IOException, ClassNotFoundException, SQLException {
     72                if (instance == null) { instance = new Authenticator(); }
     73                return instance;
     74        }
     75       
     76        private Authenticator() throws KeyStoreException, FileNotFoundException, IOException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, SQLException {
     77                UserSettings.setupDefaultFolders();
     78               
     79                // initialise keystore and actions
     80                loadKeystore();
     81                Actions.LoadMethods(org.expeditee.auth.Actions.class);
     82
     83                // draw the window
     84                final GraphicsManager g = EcosystemManager.getGraphicsManager();
     85                g.setWindowLocation(new Point(50, 50));
     86                DisplayController.Init();
     87                g.setWindowSize(new Dimension(UserSettings.InitialWidth.get(), UserSettings.InitialHeight.get()));
     88                setInputManagerWindowRoutines();
     89               
     90                // Load documentation and start pages
     91                FrameUtils.extractResources(false);
     92
     93                // Load fonts before loading any frames so the items on the frames will be able to access their fonts
     94                Text.InitFonts();
     95               
     96                // initialing settings does not require a user profile established
     97                Settings.Init();
     98               
     99                // navigate to authentication frame
     100                final Frame authFrame = FrameIO.LoadFrame("authentication1");
     101                DisplayController.setCurrentFrame(authFrame, true);
     102               
     103                // set initial values
     104                final Stream<Text> usernameItemsStream = authFrame.getTextItems().stream().filter(t -> t.getData() != null && t.getData().contains("txtUsername"));
     105                final Stream<Text> passwordItemsStream = authFrame.getTextItems().stream().filter(t -> t.getData() != null && t.getData().contains("txtPassword"));
     106                usernameItemsStream.forEach(txtUsername -> txtUsername.setText(System.getProperty("user.name", "")));
     107                passwordItemsStream.forEach(txtPassword -> txtPassword.setText(System.getProperty("user.password", "")));
     108                                               
     109                MessageBay.warningMessages(org.expeditee.actions.Actions.Init());
     110               
     111                // ensure database
     112                Class.forName("org.sqlite.JDBC");
     113                if (!mailDatabaseExists()) {
     114                        createMailDatabase();
     115                }
     116        }
     117       
     118        private void createMailDatabase() throws ClassNotFoundException, SQLException {
     119                Connection c = DriverManager.getConnection("jdbc:sqlite:" + FrameIO.PARENT_FOLDER + "/expmail.db");
     120                Statement createTable = c.createStatement();
     121                String sql = "CREATE TABLE EXPMAIL (" +
     122                                "SND            TEXT                                    NOT NULL, " +
     123                                "REC            TEXT                                    NOT NULL, " +
     124                                "MSG            TEXT                                    NOT NULL, " +
     125                                "MSG2           TEXT                                    NOT NULL, " +
     126                                "OPTS           ARRAY                                   NOT NULL, " +
     127                                "OPTSVAL        ARRAY                                   NOT NULL)";
     128                createTable.executeUpdate(sql);
     129                createTable.close();
     130                c.close();
     131        }
     132       
     133        final void loadMailDatabase() throws SQLException {
     134                Connection c = DriverManager.getConnection("jdbc:sqlite:" + FrameIO.PARENT_FOLDER + "/expmail.db");
     135                Statement query = c.createStatement();
     136                ResultSet results = query.executeQuery("SELECT * FROM EXPMAIL");
     137                Mail.clear();
     138                while (results.next()) {
     139                        String from = results.getString("snd");
     140                        String to = results.getString("rec");
     141                        String msg = results.getString("msg");
     142                        String msg2 = results.getString("msg2");
     143                        String[] opts = results.getString("opts").split(",");
     144                        opts[0] = opts[0].replace("[", "");
     145                        opts[opts.length - 1] = opts[opts.length - 1].replace("]", "");
     146                        String[] optsVal = results.getString("optsval").split(",");
     147                        optsVal[0] = optsVal[0].replace("[", "");
     148                        optsVal[optsVal.length - 1] = optsVal[optsVal.length - 1].replace("]", "");
     149                       
     150                        Map<String, String> options = new HashMap<String, String>();
     151                        for (int i = 0, o = 0; i < opts.length && o < optsVal.length; i++, o++) {
     152                                String key = opts[i].trim();
     153                                String val = optsVal[o].trim();
     154                                options.put(key, val);
     155                        }
     156                       
     157                        Mail.addEntry(new Mail.MailEntry(from, to, msg, msg2, options));
     158                }
     159                results.close();
     160                query.close();
     161                c.close();
     162        }
     163       
     164        private boolean mailDatabaseExists() {
     165                final File file = new File(FrameIO.PARENT_FOLDER + "/expmail.db");
     166                return file.exists();
     167        }
     168               
     169        private void loadKeystore()
     170                        throws IOException, NoSuchAlgorithmException, CertificateException, FileNotFoundException {
     171                final File keyStoreFile = new File(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME);
    27172                if (!keyStoreFile.exists()) {
    28173                        keyStore.load(null, "ExpediteeAuthPassword".toCharArray());
    29174                } else {
    30                         try (final InputStream in = new FileInputStream(keystoreFileName)) {
     175                        try (final InputStream in = new FileInputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME)) {
    31176                                keyStore.load(in, "ExpediteeAuthPassword".toCharArray());
    32177                        }
     
    34179        }
    35180       
    36         public final SecretKey getSecretKey(final String label, final String password) throws NoSuchAlgorithmException, UnrecoverableEntryException, KeyStoreException {               
     181        final SecretKey getSecretKey(final String label, final String password) throws NoSuchAlgorithmException, KeyStoreException {           
    37182                final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(password.toCharArray());
    38                 final KeyStore.SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(label, entryPassword);
     183                KeyStore.SecretKeyEntry entry = null;
     184                try {
     185                        entry = (SecretKeyEntry) keyStore.getEntry(label, entryPassword);
     186                } catch (final UnrecoverableEntryException e) {
     187                        entry = null;
     188                }
    39189                if (entry == null) { return null; }
    40190                else { return entry.getSecretKey(); }
    41191        }
    42192       
    43         public final void putKey(final String label, final String password, final SecretKey key) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
     193        final void putKey(final String label, final String password, final SecretKey key) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
    44194                final KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(key);
    45195                final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(password.toCharArray());
    46196                keyStore.setEntry(label, entry, entryPassword);
    47                 keyStore.store(new FileOutputStream(keystoreFileName), "ExpediteeAuthPassword".toCharArray());
     197                keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), "ExpediteeAuthPassword".toCharArray());
     198        }
     199       
     200        final void putEmail(String username, String email) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
     201                // Establish location of email file
     202                String emailFilePath = FrameIO.PROFILE_PATH + username + File.separator + username + ".email";
     203                File emailFile = new File(emailFilePath);
     204               
     205                // Delete old version if it exists.
     206                if (emailFile.exists()) {
     207                        emailFile.delete();
     208                }
     209               
     210                // Write email to file
     211                emailFile.createNewFile();
     212                Writer w = new FileWriter(emailFile);
     213                w.write(email);
     214                w.flush();
     215                w.close();
     216               
     217                // TODO: set rights on file to be read only by 'owner' once installed on drive.
     218        }
     219       
     220        final boolean hasRegisteredEmail(String username) throws KeyStoreException {
     221                String emailFilePath = FrameIO.PROFILE_PATH + username + File.separator + username + ".email";
     222                File emailFile = new File(emailFilePath);
     223                return emailFile.exists();
     224        }
     225       
     226        final boolean confirmIntergalaticNumber(final String username, final String email, final String intergalacticNumber) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, FileNotFoundException, IOException {
     227                try {
     228                        final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(intergalacticNumber.toCharArray());
     229                        final KeyStore.SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(email + username, entryPassword);
     230                        if (entry == null) {
     231                                return false;
     232                        } else if (entry.getSecretKey().getEncoded() == TRUE) {
     233                                keyStore.deleteEntry(email + username);
     234                                keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), "ExpediteeAuthPassword".toCharArray());
     235                                return true;
     236                        } else { return false; }
     237                } catch (final UnrecoverableEntryException e) {
     238                        return false;
     239                }
     240        }
     241       
     242        final String newIntergalacticNumber(final String username, final String email) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
     243                // generate intergalactic number
     244                final SecureRandom rand = new SecureRandom();
     245                final byte[] intergalacticNumberBytes = new byte[20];
     246                rand.nextBytes(intergalacticNumberBytes);
     247                final String intergalacticNumber = Base64.getEncoder().encodeToString(intergalacticNumberBytes);
     248               
     249                // store intergalactic number
     250                final KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(new SecretKeySpec(TRUE, SymmetricAlgorithm));
     251                final KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(intergalacticNumber.toCharArray());
     252                keyStore.setEntry(email + username, entry, entryPassword);
     253                keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), "ExpediteeAuthPassword".toCharArray());
     254               
     255                return intergalacticNumber;
     256        }
     257       
     258        final PublicKey getPublicKey(String username) throws InvalidKeySpecException, NoSuchAlgorithmException {
     259                Frame withTargetPublic = FrameIO.LoadFrame(username + Authenticator.PUBLIC_KEY_FRAME);
     260                Collection<Text> textItems = withTargetPublic.getTextItems();
     261                textItems.removeIf(t -> !t.getText().startsWith("PublicKey"));
     262               
     263                if (textItems.isEmpty()) {
     264                        return null;
     265                } else {
     266                        String keyEncoded = textItems.stream().findFirst().get().getData().get(0);
     267                        byte[] keyBytes = Base64.getDecoder().decode(keyEncoded);
     268                        PublicKey key = KeyFactory.getInstance(AsymmetricAlgorithm).generatePublic(new X509EncodedKeySpec(keyBytes));
     269                        return key;
     270                }
     271        }
     272       
     273        final void markRequestedColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
     274                KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(new SecretKeySpec(TRUE, SymmetricAlgorithm));
     275                KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
     276                keyStore.setEntry(username + "colleaguesRequested", entry, entryPassword);
     277                keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), "ExpediteeAuthPassword".toCharArray());
     278        }
     279       
     280        final void clearRequestedColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
     281                KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(new SecretKeySpec(FALSE, SymmetricAlgorithm));
     282                KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
     283                keyStore.setEntry(username + "colleaguesRequested", entry, entryPassword);
     284                keyStore.store(new FileOutputStream(FrameIO.PARENT_FOLDER + KEYSTOREFILENAME), "ExpediteeAuthPassword".toCharArray());
     285        }
     286       
     287        final boolean hasRequestedColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
     288                String alias = username + "colleaguesRequested";
     289                if (!keyStore.containsAlias(alias)) {
     290                        return false;
     291                } else {
     292                        KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
     293                        KeyStore.SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(alias, entryPassword);
     294                        return Arrays.equals(entry.getSecretKey().getEncoded(), TRUE);
     295                }
     296        }
     297       
     298        final void putColleagues(String username, String[] colleagues) throws KeyStoreException {
     299                String alias = username + "colleagues";
     300                final SecretKeySpec secretKeySpec = new SecretKeySpec((colleagues[0] + System.getProperty("line.separator") + colleagues[1]).getBytes(), SymmetricAlgorithm);
     301                KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(secretKeySpec);
     302                KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
     303                keyStore.setEntry(alias, entry, entryPassword);
     304        }
     305       
     306        final String[] getColleagues(String username) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
     307                String alias = username + "colleagues";
     308                if (!keyStore.containsAlias(alias)) {
     309                        return null;
     310                } else {
     311                        KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(KeyList.PersonalKey.get().getText().toCharArray());
     312                        KeyStore.SecretKeyEntry entry = (SecretKeyEntry) keyStore.getEntry(alias, entryPassword);
     313                        byte[] colleaguesEncoded = entry.getSecretKey().getEncoded();
     314                        String colleagues = new String(colleaguesEncoded);
     315                        return colleagues.split(System.getProperty("line.separator"));
     316                }
     317        }
     318       
     319        private static void setInputManagerWindowRoutines()     {
     320                InputManager manager = EcosystemManager.getInputManager();
     321               
     322            // Refresh the layout when the window resizes
     323                manager.addWindowEventListener(new WindowEventListener() {
     324                        @Override
     325                        public void onWindowEvent(WindowEventType type)
     326                        {
     327                                if (type != WindowEventType.WINDOW_RESIZED) {
     328                                        return;
     329                                }
     330                                DisplayController.refreshWindowSize();
     331                                FrameIO.RefreshCacheImages();
     332                                for (Frame frame : DisplayController.getFrames()) {
     333                                        if (frame != null) {
     334                                                ItemUtils.Justify(frame);
     335                                                frame.refreshSize();
     336                                        }
     337                                }
     338                                DisplayController.requestRefresh(false);
     339                        }
     340                });
     341               
     342                manager.addWindowEventListener(new WindowEventListener() {
     343                        @Override
     344                        public void onWindowEvent(WindowEventType type)
     345                        {
     346                                if (type != WindowEventType.MOUSE_EXITED_WINDOW) {
     347                                        return;
     348                                }
     349                                StandardGestureActions.mouseExitedWindow();
     350                        }
     351                });
     352               
     353                manager.addWindowEventListener(new WindowEventListener() {
     354                        @Override
     355                        public void onWindowEvent(WindowEventType type)
     356                        {
     357                                if (type != WindowEventType.MOUSE_ENTERED_WINDOW) {
     358                                        return;
     359                                }
     360                                StandardGestureActions.mouseEnteredWindow();
     361                        }
     362                });
     363               
     364                manager.addWindowEventListener(new WindowEventListener() {
     365                        @Override
     366                        public void onWindowEvent(WindowEventType type)
     367                        {
     368                                if (type != WindowEventType.WINDOW_CLOSED) {
     369                                        return;
     370                                }
     371                                if (Browser._theBrowser != null) {
     372                                        Browser._theBrowser.exit();
     373                                }
     374                        }
     375                });
    48376        }
    49377}
  • trunk/src/org/expeditee/auth/EncryptedExpReader.java

    r1201 r1202  
    1 package org.expeditee.auth.io;
     1package org.expeditee.auth;
    22
    33import java.io.BufferedReader;
    44import java.io.FileInputStream;
     5import java.io.FileReader;
    56import java.io.IOException;
    67import java.io.InputStreamReader;
     
    1920import javax.crypto.NoSuchPaddingException;
    2021import javax.crypto.SecretKey;
    21 
    22 import org.expeditee.auth.Authenticator;
     22import javax.crypto.spec.SecretKeySpec;
     23
    2324import org.expeditee.gui.Frame;
    2425import org.expeditee.io.ExpReader;
     26import org.expeditee.items.Text;
     27import org.expeditee.settings.auth.secrets.KeyList;
    2528import org.ngikm.Util.ThrowingFunction;
    2629import org.ngikm.cryptography.CryptographyConstants;
     
    2831public class EncryptedExpReader extends ExpReader implements CryptographyConstants {
    2932        static final String ENCRYPTED_EXP_FLAG = "EncryptedExp";
    30         private List<SecretKey> keys;
    31        
    32         public EncryptedExpReader(final String frameName) throws UnsupportedEncodingException {
     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 {
    3339                super(frameName);
     40                this.usePersonalKey = usePersonalKey;
    3441        }
    3542       
     
    4148        }
    4249       
     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       
    4376        @Override
    4477        public Frame readFrame(final String fullPath) throws IOException {
    4578                final Reader in = new InputStreamReader(new FileInputStream(fullPath), "UTF-8");
    46                 return readFrame(new EncryptedLineReader(new BufferedReader(in)));
    47         }
    48        
    49         public class EncryptedLineReader extends BufferedReader {
    50 
    51                 public EncryptedLineReader(final Reader in) {
    52                         super(in);
    53                 }
    54                                                                  
    55                 @Override
    56                 public String readLine() throws IOException {
    57                         final String line = super.readLine();   
    58                         if (line.isEmpty()) { return ""; }
    59                         if (line.startsWith(ENCRYPTED_EXP_FLAG)) {
    60                                 try {
    61                                         // resolve labels to secret keys
    62                                         final List<String> labels = Arrays.asList(line.split(" ")).stream().skip(1).collect(Collectors.toList());
    63                                         final Authenticator auth = new Authenticator();
    64                                         final ThrowingFunction<String, SecretKey, Exception> worker = new ThrowingFunction<String, SecretKey, Exception>() {
    65                                                 @Override
    66                                                 public SecretKey applyThrows(final String label) throws Exception {
    67                                                         return auth.getSecretKey(label, System.getProperty("password"));
    68                                                 }
    69                                         };
    70                                         keys = labels.stream().map(worker).collect(Collectors.toList());
    71                                         return readLine();
    72                                 } catch (final Exception e) {
    73                                         return "";
    74                                 }
    75                         }
    76                        
    77                         if (keys == null) {
    78                                 // We do not have permission to view this frame.
    79                                 return "";
    80                         }
    81                        
    82                         // use keys to decrypt
    83                         byte[] toDecrypt = Base64.getDecoder().decode(line);
    84                         for (final SecretKey key: keys) {
    85                                 toDecrypt = DecryptSymmetric(toDecrypt, key);
    86                         }
    87                         final String result = new String(toDecrypt);
    88                         if (result.startsWith("Z")) { return result.trim(); }
    89                         else { return result; }
    90                 }               
     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);
    9190        }
    9291       
     
    111110                }
    112111        }
     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        }
    113205}
  • trunk/src/org/expeditee/auth/EncryptedProfileExpWriter.java

    r1201 r1202  
    1 package org.expeditee.auth.io;
     1package org.expeditee.auth;
    22
    33import java.io.IOException;
    44import java.security.InvalidKeyException;
    5 import java.security.KeyStoreException;
    65import java.security.NoSuchAlgorithmException;
    7 import java.security.UnrecoverableEntryException;
    8 import java.security.cert.CertificateException;
    96import java.util.Arrays;
    107import java.util.Base64;
     
    1714import javax.crypto.spec.SecretKeySpec;
    1815
    19 import org.expeditee.auth.Authenticator;
    2016import org.expeditee.io.ExpWriter;
    21 import org.expeditee.settings.UserSettings;
     17import org.expeditee.items.Text;
     18import org.expeditee.settings.auth.secrets.KeyList;
    2219import org.ngikm.cryptography.CryptographyConstants;
    2320
    24 public class EncryptedExpWriter extends ExpWriter implements CryptographyConstants {
    25         private SecretKey key;
     21public class EncryptedProfileExpWriter extends ExpWriter implements CryptographyConstants {
     22        private SecretKey personalKey;
    2623        private static final String nl = "\n";
    2724       
    28         public EncryptedExpWriter() throws IOException {
    29                 try {
    30                         final Authenticator auth = new Authenticator();
    31                         SecretKey key = auth.getSecretKey(UserSettings.UserName.get(), System.getProperty("password"));
    32                         if (key == null) {
    33                                 final byte[] keyBytes = pad(UserSettings.UserName.get().getBytes("UTF-8"));
    34                                 key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
    35                                 auth.putKey(UserSettings.UserName.get(), System.getProperty("password"), key);
    36                         }
    37                         this.key = key;                 
    38                 } catch (final KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException | UnrecoverableEntryException e) {
    39                         e.printStackTrace();
    40                 }
    41                
     25        public EncryptedProfileExpWriter() throws IOException {
     26                // obtain personal key
     27                final Text text = KeyList.PersonalKey.get();
     28                final byte[] keyBytes = Base64.getDecoder().decode(text.getData().get(0));
     29                personalKey = new SecretKeySpec(keyBytes, SymmetricAlgorithm);         
    4230        }
    4331
     
    4533        protected void preOutputFrame() {
    4634                try {
    47                         final String line = EncryptedExpReader.ENCRYPTED_EXP_FLAG + " " + UserSettings.UserName.get() + nl;
     35                        final String line = EncryptedExpReader.ENCRYPTED_EXP_FLAG + nl;
    4836                        _writer.write(line);
    4937                        _stringWriter.append(line);
     
    5947               
    6048                // prepare line to write out
    61                 final byte[] encrypted = EncryptSymmetric(line.getBytes(), key);
     49                final byte[] encrypted = EncryptSymmetric(line.getBytes(), personalKey);
    6250                final String toWrite = Base64.getEncoder().encodeToString(encrypted) + nl;
    6351               
     
    6755        }
    6856       
    69         private byte[] pad(final byte[] bytes) {
    70                 int c = 16;
    71                 while (c - bytes.length < 0) { c *= 2; }
    72                 return Arrays.copyOf(bytes, c);
    73         }
    74        
    7557        private static byte[] EncryptSymmetric(final byte[] toEncrypt, final SecretKey key) {
    76                 // toEncrypt = Base64.getDecoder().decode(toEncrypt);
    7758                try {
    7859                        final Cipher cipher = Cipher.getInstance(SymmetricAlgorithm + SymmetricAlgorithmParameters);
     
    8162                        final int length = (int) ((Math.ceil(toEncrypt.length / 16f)) * 16);
    8263                        final byte[] toEncryptSizeAdjusted = Arrays.copyOf(toEncrypt, length);
    83                         //System.err.println("(" + toEncryptSizeAdjusted.length + ")" + "Before Encryption Data: "
    84                         //              + Arrays.toString(toEncryptSizeAdjusted));
    8564                        final byte[] result = cipher.doFinal(toEncryptSizeAdjusted);
    86                         //System.err.println("(" + result.length + ")" + "Encrypted Data: " + Arrays.toString(result));
    8765                        return result;
    8866                } catch (final NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
Note: See TracChangeset for help on using the changeset viewer.