From c0b2c1c82d1bb7ae4eac3e3bc749f3c4923c833e Mon Sep 17 00:00:00 2001 From: Dave Date: Fri, 3 Jul 2015 22:44:08 +0200 Subject: [PATCH] massive changes - Changed NoCore to a non-static object - Cut out all spheres in favour of a NoAdapter interface - Added basic NoDefaultAdapter object, should be overridden in prod uses --- src/nodash/core/NoAdapter.java | 41 +++ src/nodash/core/NoConfigBase.java | 54 ---- src/nodash/core/NoConfigDefault.java | 88 ------- src/nodash/core/NoConfigInterface.java | 21 -- src/nodash/core/NoCore.java | 247 ++++++++++++------ src/nodash/core/NoDefaultAdapter.java | 229 ++++++++++++++++ src/nodash/core/NoRegister.java | 4 +- .../core/exceptions/NoAdapterException.java | 15 ++ src/nodash/core/spheres/NoByteSetSphere.java | 57 ---- .../core/spheres/NoHashSphereDefault.java | 113 -------- .../core/spheres/NoHashSphereInterface.java | 23 -- src/nodash/core/spheres/NoSessionSphere.java | 199 -------------- src/nodash/exceptions/NoDashException.java | 6 +- ...ava => NoDashSessionBadUuidException.java} | 6 +- src/nodash/models/NoAction.java | 4 +- src/nodash/models/NoSession.java | 104 ++++---- src/nodash/test/NoCoreTest.java | 142 ++++++++++ src/nodash/test/NoSessionTest.java | 72 +++++ 18 files changed, 732 insertions(+), 693 deletions(-) create mode 100644 src/nodash/core/NoAdapter.java delete mode 100644 src/nodash/core/NoConfigBase.java delete mode 100644 src/nodash/core/NoConfigDefault.java delete mode 100644 src/nodash/core/NoConfigInterface.java create mode 100644 src/nodash/core/NoDefaultAdapter.java create mode 100644 src/nodash/core/exceptions/NoAdapterException.java delete mode 100644 src/nodash/core/spheres/NoByteSetSphere.java delete mode 100644 src/nodash/core/spheres/NoHashSphereDefault.java delete mode 100644 src/nodash/core/spheres/NoHashSphereInterface.java delete mode 100644 src/nodash/core/spheres/NoSessionSphere.java rename src/nodash/exceptions/{NoDashSessionBadUUIDException.java => NoDashSessionBadUuidException.java} (84%) create mode 100644 src/nodash/test/NoCoreTest.java create mode 100644 src/nodash/test/NoSessionTest.java diff --git a/src/nodash/core/NoAdapter.java b/src/nodash/core/NoAdapter.java new file mode 100644 index 0000000..7a25f49 --- /dev/null +++ b/src/nodash/core/NoAdapter.java @@ -0,0 +1,41 @@ +package nodash.core; + +import java.security.PublicKey; +import java.util.Collection; + +import nodash.core.exceptions.NoAdapterException; +import nodash.exceptions.NoUserAlreadyOnlineException; +import nodash.exceptions.NoUserNotValidException; +import nodash.models.NoByteSet; +import nodash.models.NoSession; + +public interface NoAdapter { + public void insertHash(byte[] hash) throws NoAdapterException; + + public void removeHash(byte[] hash) throws NoAdapterException; + + public void checkHash(byte[] hash) throws NoAdapterException, NoUserNotValidException; + + public byte[][] exportHashes() throws NoAdapterException; + + public long hashCount() throws NoAdapterException; + + public void goOnline(byte[] hash) throws NoAdapterException, NoUserAlreadyOnlineException; + + public boolean isOnline(byte[] hash) throws NoAdapterException; + + public void goOffline(byte[] hash) throws NoAdapterException; + + public void addNoSession(NoSession session) throws NoAdapterException; + + public boolean containsNoSession(byte[] encryptedUuid) throws NoAdapterException; + + public void shredNoSession(byte[] encryptedUuid) throws NoAdapterException; + + public NoSession getNoSession(byte[] encryptedUuid) throws NoAdapterException; + + public Collection pollNoByteSets(PublicKey address) throws NoAdapterException; + + public void addNoByteSets(Collection noByteSets, PublicKey address) + throws NoAdapterException; +} diff --git a/src/nodash/core/NoConfigBase.java b/src/nodash/core/NoConfigBase.java deleted file mode 100644 index c04d703..0000000 --- a/src/nodash/core/NoConfigBase.java +++ /dev/null @@ -1,54 +0,0 @@ -package nodash.core; - -import java.io.IOException; -import java.security.NoSuchAlgorithmException; - -import javax.crypto.KeyGenerator; -import javax.crypto.SecretKey; - -import nodash.exceptions.NoDashFatalException; - -public abstract class NoConfigBase implements NoConfigInterface { - protected boolean ready; - protected SecretKey secretKey; - protected boolean saveDatabase; - protected boolean saveByteSets; - - protected final void generateSecretKey() { - try { - KeyGenerator keyGenerator = KeyGenerator.getInstance(NoUtil.CIPHER_KEY_SPEC); - keyGenerator.init(NoUtil.AES_STRENGTH); - this.secretKey = keyGenerator.generateKey(); - } catch (NoSuchAlgorithmException e) { - throw new NoDashFatalException("Value for CIPHER_KEY_SPEC not valid.", e); - } - } - - @Override - public void construct() { - this.generateSecretKey(); - this.ready = true; - } - - @Override - public SecretKey getSecretKey() { - return this.secretKey; - } - - @Override - public boolean saveDatabase() { - return this.saveDatabase; - } - - @Override - public boolean saveByteSets() { - return this.saveByteSets; - } - - @Override - public abstract void saveNoConfig(); - - @Override - public abstract NoConfigInterface loadNoConfig() throws IOException; - -} diff --git a/src/nodash/core/NoConfigDefault.java b/src/nodash/core/NoConfigDefault.java deleted file mode 100644 index 899f5d5..0000000 --- a/src/nodash/core/NoConfigDefault.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2014 David Horscroft - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - * - * The NoConfig is a means to store the server secret key, database address and other configs. - */ - -package nodash.core; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.nio.file.Files; -import java.nio.file.StandardOpenOption; - -import nodash.exceptions.NoDashFatalException; - -public final class NoConfigDefault extends NoConfigBase implements NoConfigInterface, Serializable { - private static final long serialVersionUID = -8498303909736017075L; - - private static final String CONFIG_FILENAME = "noconfig.cfg"; - - private String databaseFileName = "nodatabase.hash"; - - @Override - public boolean saveDatabase() { - return saveDatabase; - } - - public String getDatabaseName() { - return databaseFileName; - } - - @Override - public boolean saveByteSets() { - return saveByteSets; - } - - @Override - public void saveNoConfig() { - try { - File file = new File(NoConfigDefault.CONFIG_FILENAME); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(this); - byte[] data = baos.toByteArray(); - - Files.write(file.toPath(), data, StandardOpenOption.CREATE_NEW); - } catch (IOException e) { - throw new NoDashFatalException("Unable to save config, including generated secret key.", e); - } - } - - @Override - public NoConfigInterface loadNoConfig() throws IOException { - File file = new File(NoConfigDefault.CONFIG_FILENAME); - byte[] data = Files.readAllBytes(file.toPath()); - ByteArrayInputStream bais = new ByteArrayInputStream(data); - ObjectInputStream ois = new ObjectInputStream(bais); - NoConfigInterface noConfig; - try { - noConfig = (NoConfigDefault) ois.readObject(); - } catch (ClassNotFoundException e) { - throw new NoDashFatalException( - "Given bytestream does not compile into a configuration object.", e); - } - this.ready = true; - return noConfig; - } - - @Override - public boolean isReady() { - return this.ready; - } -} diff --git a/src/nodash/core/NoConfigInterface.java b/src/nodash/core/NoConfigInterface.java deleted file mode 100644 index b8bd8ad..0000000 --- a/src/nodash/core/NoConfigInterface.java +++ /dev/null @@ -1,21 +0,0 @@ -package nodash.core; - -import java.io.IOException; - -import javax.crypto.SecretKey; - -public interface NoConfigInterface { - public void construct(); - - public SecretKey getSecretKey(); - - public boolean saveDatabase(); - - public boolean saveByteSets(); - - public void saveNoConfig(); - - public NoConfigInterface loadNoConfig() throws IOException; - - public boolean isReady(); -} diff --git a/src/nodash/core/NoCore.java b/src/nodash/core/NoCore.java index c9538d3..faff872 100644 --- a/src/nodash/core/NoCore.java +++ b/src/nodash/core/NoCore.java @@ -17,14 +17,9 @@ package nodash.core; -import java.io.IOException; -import java.security.PublicKey; - -import nodash.core.spheres.NoByteSetSphere; -import nodash.core.spheres.NoHashSphereDefault; -import nodash.core.spheres.NoHashSphereInterface; -import nodash.core.spheres.NoSessionSphere; -import nodash.exceptions.NoDashSessionBadUUIDException; +import nodash.core.exceptions.NoAdapterException; +import nodash.exceptions.NoByteSetBadDecryptionException; +import nodash.exceptions.NoDashFatalException; import nodash.exceptions.NoSessionAlreadyAwaitingConfirmationException; import nodash.exceptions.NoSessionConfirmedException; import nodash.exceptions.NoSessionExpiredException; @@ -33,98 +28,198 @@ import nodash.exceptions.NoSessionNotChangedException; import nodash.exceptions.NoUserAlreadyOnlineException; import nodash.exceptions.NoUserNotValidException; import nodash.models.NoByteSet; +import nodash.models.NoSession; import nodash.models.NoUser; import nodash.models.NoSession.NoState; public final class NoCore { - public static NoConfigInterface config; - public static NoHashSphereInterface hashSphere; + private NoAdapter adapter; - public static boolean isReady() { - return (config != null && config.isReady()) && (hashSphere != null && hashSphere.isReady()); + public NoCore(NoAdapter adapter) { + this.adapter = adapter; } - public static void setup(NoConfigInterface config, NoHashSphereInterface hashSphere) { - NoCore.setup(config); - NoCore.setup(hashSphere); - } - - public static void setup(NoConfigInterface config) { - NoCore.config = config; - } - - public static void setup(NoHashSphereInterface hashSphere) { - NoCore.hashSphere = hashSphere; - hashSphere.setup(); - } - - public static void setup() { - NoConfigInterface newConfig = new NoConfigDefault(); + private NoSession getNoSession(byte[] cookie) throws NoSessionExpiredException { + boolean containsSession; try { - newConfig = newConfig.loadNoConfig(); - } catch (IOException e) { - newConfig.construct(); + containsSession = adapter.containsNoSession(cookie); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Could not verify existence of session.", e); } - NoCore.setup(newConfig); - NoCore.setup(new NoHashSphereDefault()); + + if (containsSession) { + try { + return adapter.getNoSession(cookie); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Could not get session.", e); + } + } + throw new NoSessionExpiredException(); } - public static byte[] login(byte[] data, char[] password) throws NoUserNotValidException, + public byte[] login(byte[] data, char[] password) throws NoUserNotValidException, NoUserAlreadyOnlineException, NoSessionExpiredException { - /* steps 1 through to pre-3 */ - return NoSessionSphere.login(data, password); + NoSession session = new NoSession(adapter, data, password); + + /* 1. Check that user is a valid user of the system based on their hash. */ + try { + adapter.checkHash(session.getOriginalHash()); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Unable to verify user."); + } + + /* 2. Attempt to set user to online (avoid two of the same account online at the same time) */ + try { + adapter.goOnline(session.getOriginalHash()); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Could not mark user as online.", e); + } + + /* 3. Add the session to the live session pool. */ + try { + adapter.addNoSession(session); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Could not add the session.", e); + } + + /* 4. Transfer any incoming NoByteSets to session. */ + try { + session.setIncoming(adapter.pollNoByteSets(session.getNoUserSafe().getRsaPublicKey())); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Could not get incoming byte sets.", e); + } + + /* 5. Apply any incoming ByteSets to the session. */ + for (NoByteSet byteSet : session.getIncomingSafe()) { + try { + session.consume(byteSet); + } catch (NoByteSetBadDecryptionException e) { + throw new NoDashFatalException("Bad byte sets on consumption.", e); + } catch (NoSessionConfirmedException e) { + throw new NoDashFatalException("NoSession is confirmed despite being newly created."); + } finally { + try { + adapter.addNoByteSets(session.getIncomingSafe(), session.getNoUserSafe() + .getRsaPublicKey()); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Could not return failed byte sets to pool.", e); + } + } + } + + /* 6. Check the session to see if the incoming actions have modified it at all. */ + try { + session.check(); + } catch (NoSessionConfirmedException e) { + throw new NoDashFatalException("NoSession is confirmed despite being newly created."); + } + + return session.getEncryptedUuid(); } - public static NoRegister register(NoUser user, char[] password) { - /* Straight to step 4 */ - return NoSessionSphere.registerUser(user, password); + public NoRegister register(NoUser user, char[] password) { + NoSession session = new NoSession(user); + try { + adapter.addNoSession(session); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Adapter could not save the session.", e); + } + + byte[] cookie = session.getEncryptedUuid(); + byte[] userFile; + try { + userFile = save(cookie, password); + } catch (NoSessionExpiredException e) { + throw new NoDashFatalException("Session expired despite just being created."); + } catch (NoSessionConfirmedException e) { + throw new NoDashFatalException("Session confirmed despite just being created."); + } catch (NoSessionNotChangedException e) { + throw new NoDashFatalException( + "Session throwing NotChangedException despite being a new user"); + } catch (NoSessionAlreadyAwaitingConfirmationException e) { + throw new NoDashFatalException( + "Session already waiting confirmation despite just being created."); + } + + return new NoRegister(cookie, userFile); } - public static NoUser getUser(byte[] cookie) throws NoSessionExpiredException, - NoSessionConfirmedException, NoDashSessionBadUUIDException { - /* - * Facilitates step 3 allow website-side modifications to the NoUser or NoUser inheritant - */ - return NoSessionSphere.getUser(cookie); + public NoUser getNoUser(byte[] cookie) throws NoSessionExpiredException, + NoSessionConfirmedException { + boolean containsSession; + try { + containsSession = adapter.containsNoSession(cookie); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Could not verify existence of session.", e); + } + + if (containsSession) { + try { + return adapter.getNoSession(cookie).getNoUser(); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Could not get session.", e); + } + } else { + throw new NoSessionExpiredException(); + } } - public static NoState getSessionState(byte[] cookie) throws NoSessionExpiredException, - NoSessionConfirmedException, NoDashSessionBadUUIDException { - /* - * Facilitates step 3 allow front-side to keep track of session state - */ - return NoSessionSphere.getState(cookie); + public NoState getSessionState(byte[] cookie) throws NoSessionConfirmedException, + NoSessionExpiredException { + return getNoSession(cookie).getNoState(); } - public static byte[] requestSave(byte[] cookie, char[] password) - throws NoSessionExpiredException, NoSessionConfirmedException, NoSessionNotChangedException, - NoSessionAlreadyAwaitingConfirmationException, NoDashSessionBadUUIDException { - /* Step 4. Provides a user with the new binary file */ - return NoSessionSphere.save(cookie, password); + public byte[] save(byte[] cookie, char[] password) throws NoSessionExpiredException, + NoSessionConfirmedException, NoSessionNotChangedException, + NoSessionAlreadyAwaitingConfirmationException { + NoSession session = getNoSession(cookie); + session.check(); + if (session.getNoState().equals(NoState.IDLE)) { + throw new NoSessionNotChangedException(); + } else if (session.getNoState().equals(NoState.AWAITING_CONFIRMATION)) { + throw new NoSessionAlreadyAwaitingConfirmationException(); + } + return session.initiateSaveAttempt(password); } - public static void confirm(byte[] cookie, char[] password, byte[] data) - throws NoSessionExpiredException, NoSessionConfirmedException, - NoSessionNotAwaitingConfirmationException, NoUserNotValidException, - NoDashSessionBadUUIDException { - /* - * Step 5. Assumes the user has re-uploaded the file along with providing the same password. - * Further attempts of getUser or getSessionState will fail with a NoSessionExpiredException - */ - NoSessionSphere.confirm(cookie, password, data); + public void confirm(byte[] cookie, char[] password, byte[] data) throws NoSessionExpiredException, NoSessionConfirmedException, NoSessionNotAwaitingConfirmationException, NoUserNotValidException { + NoSession session = getNoSession(cookie); + byte[] oldHash = session.getOriginalHash(); + byte[] newHash = session.getNoUserSafe().createHash(); + + session.confirmSave(adapter, data, password); + + try { + adapter.insertHash(newHash); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Could not insert confirmed hash.", e); + } + + try { + adapter.goOffline(newHash); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Could not go offline.", e); + } + + try { + adapter.shredNoSession(cookie); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Could not shred session.", e); + } + + try { + adapter.removeHash(oldHash); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Could not remove old hash.", e); + } } - public static void addByteSet(NoByteSet byteSet, PublicKey publicKey) { - NoByteSetSphere.add(byteSet, publicKey); - } - - public static void shred(byte[] cookie) { - /* 3.2 Hot pull */ - NoSessionSphere.shred(cookie); - } - - public static void triggerPrune() { - NoSessionSphere.prune(); + public void shred(byte[] cookie) { + try { + adapter.shredNoSession(cookie); + } catch (NoAdapterException e) { + throw new NoDashFatalException("Could not shred session.", e); + } } } diff --git a/src/nodash/core/NoDefaultAdapter.java b/src/nodash/core/NoDefaultAdapter.java new file mode 100644 index 0000000..504cf61 --- /dev/null +++ b/src/nodash/core/NoDefaultAdapter.java @@ -0,0 +1,229 @@ +package nodash.core; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.security.PublicKey; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; + +import org.apache.commons.codec.binary.Base64; + +import nodash.core.exceptions.NoAdapterException; +import nodash.exceptions.NoDashFatalException; +import nodash.exceptions.NoUserAlreadyOnlineException; +import nodash.exceptions.NoUserNotValidException; +import nodash.models.NoByteSet; +import nodash.models.NoSession; + +public class NoDefaultAdapter implements NoAdapter { + private static Map> byteSets = + new ConcurrentHashMap>(); + private static Map sessions = new ConcurrentHashMap(); + private static Set online = Collections + .newSetFromMap(new ConcurrentHashMap()); + + private static final String HASH_FILE = "nosystem.hash"; + + private static byte[] getFile() throws NoAdapterException { + try { + return alterFile(null, null); + } catch (IOException e) { + throw new NoAdapterException("Could not get hash file.", e); + } + } + + private static synchronized byte[] alterFile(byte[] hashToAdd, byte[] hashToRemove) + throws IOException { + if (!(hashToAdd == null ^ hashToRemove == null) && Arrays.equals(hashToAdd, hashToRemove)) { + throw new IllegalArgumentException("Hashes to add and remove cannot be the same."); + } + + File file = new File(HASH_FILE); + byte[] originalFileBytes = Files.readAllBytes(file.toPath()); + if (hashToAdd == null && hashToRemove == null) { + return originalFileBytes; + } + + int hashes = originalFileBytes.length / 64; + List newFile = new ArrayList(); + + for (int x = 0; x < hashes; x++) { + byte[] hash = Arrays.copyOfRange(originalFileBytes, x * 64, x * 64 + 64); + + if (hashToRemove == null || !Arrays.equals(hash, hashToRemove)) { + for (byte hashByte : hash) { + newFile.add(hashByte); + } + } + + if (hashToAdd != null || Arrays.equals(hash, hashToAdd)) { + hashToAdd = null; + } + } + + if (hashToAdd != null) { + for (byte hashByte : hashToAdd) { + newFile.add(hashByte); + } + } + + byte[] newFileAsPrimitive = new byte[newFile.size()]; + for (int x = 0; x < newFile.size(); x++) { + newFileAsPrimitive[x] = newFile.get(x).byteValue(); + } + + Files.write(file.toPath(), newFileAsPrimitive); + + return newFileAsPrimitive; + } + + public NoDefaultAdapter() { + + } + + @Override + public void insertHash(byte[] hash) throws NoAdapterException { + try { + alterFile(hash, null); + } catch (IOException e) { + throw new NoAdapterException("Trouble while inserting hash.", e); + } + } + + @Override + public void removeHash(byte[] hash) throws NoAdapterException { + try { + alterFile(null, hash); + } catch (IOException e) { + throw new NoAdapterException("Trouble removing hash.", e); + } + } + + @Override + public void checkHash(byte[] hash) throws NoAdapterException, NoUserNotValidException { + byte[] hashFile = getFile(); + int hashes = hashFile.length / 64; + for (int x = 0; x < hashes; x++) { + byte[] examine = Arrays.copyOfRange(hashFile, x * 64, x * 64 + 64); + if (Arrays.equals(hash, examine)) { + return; + } + } + throw new NoUserNotValidException(); + } + + @Override + public byte[][] exportHashes() throws NoAdapterException { + byte[] hashFile = getFile(); + int hashes = hashFile.length / 64; + byte[][] export = new byte[hashes][64]; + for (int x = 0; x < hashes; x++) { + byte[] hash = Arrays.copyOfRange(hashFile, x * 64, x * 64 + 64); + export[x] = hash; + } + return export; + } + + @Override + public long hashCount() throws NoAdapterException { + byte[] hashFile = getFile(); + return hashFile.length / 64; + } + + @Override + public void addNoSession(NoSession session) { + if (containsNoSession(session.getEncryptedUuid())) { + throw new NoDashFatalException("No such session exists."); + } + sessions.put(session.getUuid(), session); + } + + @Override + public boolean containsNoSession(byte[] encryptedUuid) { + String uuid; + try { + uuid = Base64.encodeBase64String(NoUtil.decrypt(encryptedUuid)); + } catch (IllegalBlockSizeException | BadPaddingException e) { + throw new NoDashFatalException("Could not decrypt given UUID.", e); + } + + return sessions.containsKey(uuid); + } + + @Override + public void shredNoSession(byte[] encryptedUuid) { + NoSession session = getNoSession(encryptedUuid); + addNoByteSets(session.getIncomingSafe(), session.getNoUserSafe().getRsaPublicKey()); + sessions.remove(session.getUuid()); + } + + @Override + public NoSession getNoSession(byte[] encryptedUuid) { + if (containsNoSession(encryptedUuid)) { + String uuid; + try { + uuid = Base64.encodeBase64String(NoUtil.decrypt(encryptedUuid)); + } catch (IllegalBlockSizeException | BadPaddingException e) { + throw new NoDashFatalException("Could not decrypt given UUID.", e); + } + return sessions.get(uuid); + } + throw new NoDashFatalException("No such session exists."); + } + + @Override + public Collection pollNoByteSets(PublicKey address) { + if (byteSets.containsKey(address)) { + Collection storedByteSets = byteSets.get(address); + Collection result = new ArrayList(); + for (NoByteSet byteSet : storedByteSets) { + result.add(byteSet); + storedByteSets.remove(byteSet); + } + return result; + } else { + return new ArrayList(); + } + } + + @Override + public void addNoByteSets(Collection addedByteSets, PublicKey address) { + if (byteSets.containsKey(address)) { + byteSets.get(address).addAll(addedByteSets); + } else { + byteSets.put(address, addedByteSets); + } + } + + @Override + public void goOnline(byte[] hash) throws NoUserAlreadyOnlineException { + String hashString = Base64.encodeBase64String(hash); + if (online.contains(hashString)) { + throw new NoUserAlreadyOnlineException(); + } + online.add(hashString); + } + + @Override + public boolean isOnline(byte[] hash) { + String hashString = Base64.encodeBase64String(hash); + return online.contains(hashString); + } + + @Override + public void goOffline(byte[] hash) { + String hashString = Base64.encodeBase64String(hash); + online.remove(hashString); + } + +} diff --git a/src/nodash/core/NoRegister.java b/src/nodash/core/NoRegister.java index 500f4f0..9292e5a 100644 --- a/src/nodash/core/NoRegister.java +++ b/src/nodash/core/NoRegister.java @@ -18,8 +18,8 @@ package nodash.core; public final class NoRegister { - public byte[] cookie; - public byte[] data; + public final byte[] cookie; + public final byte[] data; public NoRegister(byte[] cookie, byte[] data) { this.cookie = cookie; diff --git a/src/nodash/core/exceptions/NoAdapterException.java b/src/nodash/core/exceptions/NoAdapterException.java new file mode 100644 index 0000000..1ace056 --- /dev/null +++ b/src/nodash/core/exceptions/NoAdapterException.java @@ -0,0 +1,15 @@ +package nodash.core.exceptions; + +import nodash.exceptions.NoDashException; + +public class NoAdapterException extends NoDashException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public NoAdapterException(String message, Throwable e) { + super(message, e); + } +} diff --git a/src/nodash/core/spheres/NoByteSetSphere.java b/src/nodash/core/spheres/NoByteSetSphere.java deleted file mode 100644 index 83bbd96..0000000 --- a/src/nodash/core/spheres/NoByteSetSphere.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2014 David Horscroft - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - * - * The NoByteSetSphere stores user-to-user influences and their encryption keys in an accessible - * manner. - */ - -package nodash.core.spheres; - -import java.security.PublicKey; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; - -import nodash.models.NoByteSet; -import nodash.models.NoUser; - -public final class NoByteSetSphere { - private static final List EMPTY_BYTESET_LIST = new ArrayList(0); - - private static ConcurrentHashMap> byteSets = - new ConcurrentHashMap>(); - - public static void add(NoByteSet byteSet, PublicKey publicKey) { - if (!NoByteSetSphere.byteSets.containsKey(publicKey)) { - NoByteSetSphere.byteSets.put(publicKey, new ArrayList()); - } - NoByteSetSphere.byteSets.get(publicKey).add(byteSet); - } - - public static void addList(List byteSetList, PublicKey publicKey) { - if (!NoByteSetSphere.byteSets.containsKey(publicKey)) { - NoByteSetSphere.byteSets.put(publicKey, new ArrayList()); - } - NoByteSetSphere.byteSets.get(publicKey).addAll(byteSetList); - } - - public static List consume(NoUser user) { - if (NoByteSetSphere.byteSets.containsKey(user.getRsaPublicKey())) { - ArrayList result = NoByteSetSphere.byteSets.get(user.getRsaPublicKey()); - NoByteSetSphere.byteSets.remove(user.getRsaPublicKey()); - return result; - } else { - return NoByteSetSphere.EMPTY_BYTESET_LIST; - } - } -} diff --git a/src/nodash/core/spheres/NoHashSphereDefault.java b/src/nodash/core/spheres/NoHashSphereDefault.java deleted file mode 100644 index e322fb3..0000000 --- a/src/nodash/core/spheres/NoHashSphereDefault.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2014 David Horscroft - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - * - * The NoHashSpehre stores database hashes for user verification. - * - * Must be used with something that uses NoConfigDefault or an extension. - */ - -package nodash.core.spheres; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.nio.file.Files; -import java.nio.file.StandardOpenOption; -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import nodash.core.NoCore; -import nodash.core.NoConfigDefault; -import nodash.exceptions.NoDashFatalException; -import nodash.models.NoUser; - -public final class NoHashSphereDefault implements NoHashSphereInterface { - private Set database = Collections - .newSetFromMap(new ConcurrentHashMap()); - private String fileName; - private boolean ready = false; - - public NoHashSphereDefault(String fileName) { - this.fileName = fileName; - } - - public NoHashSphereDefault() { - this.fileName = ((NoConfigDefault) NoCore.config).getDatabaseName(); - } - - @SuppressWarnings("unchecked") - public void setup() { - if (NoCore.config.saveDatabase()) { - File file = new File(this.fileName); - if (file.exists()) { - try { - byte[] data = Files.readAllBytes(file.toPath()); - ByteArrayInputStream bais = new ByteArrayInputStream(data); - ObjectInputStream ois = new ObjectInputStream(bais); - this.database = (Set) ois.readObject(); - ois.close(); - bais.close(); - } catch (IOException e) { - throw new NoDashFatalException("Unable to load up given database file.", e); - } catch (ClassNotFoundException e) { - throw new NoDashFatalException("Database file not in a verifiable format.", e); - } - } - } - this.ready = true; - } - - public synchronized void saveToFile() throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(this.database); - byte[] data = baos.toByteArray(); - oos.close(); - baos.close(); - File file = new File(((NoConfigDefault) NoCore.config).getDatabaseName()); - Files.write(file.toPath(), data, StandardOpenOption.CREATE); - } - - public synchronized void addNewNoUser(NoUser user) throws IOException { - String hash = user.createHashString(); - this.database.add(hash); - this.saveToFile(); - } - - public synchronized void insertHash(String hash) throws IOException { - this.database.add(hash); - this.saveToFile(); - } - - public synchronized void removeHash(String hash) throws IOException { - this.database.remove(hash); - this.saveToFile(); - } - - public synchronized boolean checkHash(String hash) { - return this.database.contains(hash); - } - - public synchronized long size() { - return this.database.size(); - } - - @Override - public boolean isReady() { - return this.ready; - } -} diff --git a/src/nodash/core/spheres/NoHashSphereInterface.java b/src/nodash/core/spheres/NoHashSphereInterface.java deleted file mode 100644 index c452d0e..0000000 --- a/src/nodash/core/spheres/NoHashSphereInterface.java +++ /dev/null @@ -1,23 +0,0 @@ -package nodash.core.spheres; - -import java.io.IOException; - -import nodash.models.NoUser; - -public interface NoHashSphereInterface { - public void setup(); - - public void saveToFile() throws IOException; - - public void addNewNoUser(NoUser user) throws IOException; - - public void insertHash(String hash) throws IOException; - - public void removeHash(String hash) throws IOException; - - public boolean checkHash(String hash); - - public long size(); - - public boolean isReady(); -} diff --git a/src/nodash/core/spheres/NoSessionSphere.java b/src/nodash/core/spheres/NoSessionSphere.java deleted file mode 100644 index df6f865..0000000 --- a/src/nodash/core/spheres/NoSessionSphere.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2014 David Horscroft - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - * - * The NoSessionSphere stores user sessions and allows their access and manipulation with the use of - * their UUID. - */ - -package nodash.core.spheres; - -import java.util.Collections; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.commons.codec.binary.Base64; - -import nodash.core.NoRegister; -import nodash.exceptions.NoByteSetBadDecryptionException; -import nodash.exceptions.NoDashFatalException; -import nodash.exceptions.NoDashSessionBadUUIDException; -import nodash.exceptions.NoSessionAlreadyAwaitingConfirmationException; -import nodash.exceptions.NoSessionConfirmedException; -import nodash.exceptions.NoSessionExpiredException; -import nodash.exceptions.NoSessionNotAwaitingConfirmationException; -import nodash.exceptions.NoSessionNotChangedException; -import nodash.exceptions.NoUserAlreadyOnlineException; -import nodash.exceptions.NoUserNotValidException; -import nodash.models.NoByteSet; -import nodash.models.NoSession; -import nodash.models.NoUser; -import nodash.models.NoSession.NoState; - -public final class NoSessionSphere { - private static ConcurrentHashMap sessions = - new ConcurrentHashMap(); - private static Set originalHashesOnline = Collections - .newSetFromMap(new ConcurrentHashMap()); - - public static synchronized void prune() { - for (UUID uuid : NoSessionSphere.sessions.keySet()) { - pruneSingle(uuid); - } - } - - public static void shred(byte[] encryptedUuid) { - try { - UUID uuid = NoSession.decryptUuid(encryptedUuid); - if (NoSessionSphere.sessions.containsKey(uuid)) { - NoSession session = NoSessionSphere.sessions.get(uuid); - NoByteSetSphere.addList(session.incoming, session.current.getRsaPublicKey()); - NoSessionSphere.originalHashesOnline.remove(Base64.encodeBase64String(session - .getOriginalHash())); - NoSessionSphere.sessions.remove(uuid); - session = null; - } - } catch (NoDashSessionBadUUIDException e) { - // Suppress, doesn't matter - } - } - - public static synchronized void pruneSingle(UUID uuid) { - NoSession session = NoSessionSphere.sessions.get(uuid); - try { - session.check(); - } catch (NoSessionExpiredException e) { - /* Resultant from 3.1 and 3.2 */ - NoByteSetSphere.addList(session.incoming, session.current.getRsaPublicKey()); - NoSessionSphere.originalHashesOnline.remove(session.getOriginalHash()); - NoSessionSphere.sessions.remove(uuid); - session = null; - } catch (NoSessionConfirmedException e) { - /* Should be cleaned up at 5.2 */ - } - } - - public static synchronized byte[] login(byte[] data, char[] password) - throws NoUserNotValidException, NoUserAlreadyOnlineException, NoSessionExpiredException { - /* 1. Login with byte[] data and byte[] password */ - NoSession session = new NoSession(data, password); - /* 1.1. User currently has an online session, must wait for it to expire. */ - if (originalHashesOnline.contains(Base64.encodeBase64String(session.getOriginalHash()))) { - throw new NoUserAlreadyOnlineException(); - } - /* 1.2. User successfully logged in: set up session records. */ - NoSessionSphere.originalHashesOnline.add(Base64.encodeBase64String(session.getOriginalHash())); - NoSessionSphere.sessions.put(session.uuid, session); - - /* 2. Check NoByteSetSphere for incoming Influences */ - session.incoming = NoByteSetSphere.consume(session.current); - for (NoByteSet nbs : session.incoming) { - /* 2.1 Decrypt NoInfluence from NoByteSet, let the current user consume them */ - try { - session.consume(nbs); - } catch (NoByteSetBadDecryptionException e) { - throw new NoDashFatalException("Bad byte sets on consumption.", e); - } - } /* 2.2 Alternatively, no NoByteSets to consume */ - - try { - session.check(); - } catch (NoSessionConfirmedException e) { - /* Should be impossible to reach */ - throw new NoDashFatalException(e); - } - - /* Will set to 2.1[MODIFIED] or 2.2[IDLE] */ - - /* Precursor to 3.; allow website to associate user session with a cookie. */ - return session.getEncryptedUuid(); - } - - public static NoUser getUser(byte[] encryptedUUID) throws NoDashSessionBadUUIDException, - NoSessionExpiredException, NoSessionConfirmedException { - UUID uuid = NoSession.decryptUuid(encryptedUUID); - if (NoSessionSphere.sessions.containsKey(uuid)) { - NoSessionSphere.pruneSingle(uuid); - try { - return NoSessionSphere.sessions.get(uuid).getNoUser(); - } catch (NullPointerException e) { - throw new NoSessionExpiredException(); - } - } - throw new NoSessionExpiredException(); - } - - public static NoState getState(byte[] encryptedUUID) throws NoDashSessionBadUUIDException, - NoSessionExpiredException, NoSessionConfirmedException { - UUID uuid = NoSession.decryptUuid(encryptedUUID); - if (NoSessionSphere.sessions.containsKey(uuid)) { - NoSessionSphere.pruneSingle(uuid); - NoSession session = NoSessionSphere.sessions.get(uuid); - return session.getNoState(); - } - throw new NoSessionExpiredException(); - } - - public static synchronized byte[] save(byte[] encryptedUUID, char[] password) - throws NoDashSessionBadUUIDException, NoSessionExpiredException, NoSessionConfirmedException, - NoSessionNotChangedException, NoSessionAlreadyAwaitingConfirmationException { - UUID uuid = NoSession.decryptUuid(encryptedUUID); - if (NoSessionSphere.sessions.containsKey(uuid)) { - NoSessionSphere.pruneSingle(uuid); - NoSession session = NoSessionSphere.sessions.get(uuid); - - if (session.getNoState().equals(NoState.IDLE)) { - throw new NoSessionNotChangedException(); - } else if (session.getNoState().equals(NoState.AWAITING_CONFIRMATION)) { - throw new NoSessionAlreadyAwaitingConfirmationException(); - } - return session.initiateSaveAttempt(password); - } - throw new NoSessionExpiredException(); - } - - public static synchronized void confirm(byte[] encryptedUUID, char[] password, byte[] data) - throws NoDashSessionBadUUIDException, NoSessionExpiredException, NoSessionConfirmedException, - NoSessionNotAwaitingConfirmationException, NoUserNotValidException { - UUID uuid = NoSession.decryptUuid(encryptedUUID); - if (NoSessionSphere.sessions.containsKey(uuid)) { - NoSessionSphere.pruneSingle(uuid); - NoSession session = NoSessionSphere.sessions.get(uuid); - session.confirmSave(data, password); - return; - } - throw new NoSessionExpiredException(); - } - - public static synchronized NoRegister registerUser(NoUser user, char[] password) { - NoSession session = new NoSession(user); - NoSessionSphere.sessions.put(session.uuid, session); - try { - byte[] cookie = session.getEncryptedUuid(); - return new NoRegister(cookie, NoSessionSphere.save(cookie, password)); - } catch (NoDashSessionBadUUIDException e) { - throw new NoDashFatalException("Immediately generated cookie throwing bad cookie error.", e); - } catch (NoSessionExpiredException e) { - throw new NoDashFatalException("Session expired before it was even returned to client.", e); - } catch (NoSessionConfirmedException e) { - throw new NoDashFatalException( - "Session is in confirmed state before it was returned to client.", e); - } catch (NoSessionNotChangedException e) { - throw new NoDashFatalException( - "Session claims to be unchanged but user is newly registered.", e); - } catch (NoSessionAlreadyAwaitingConfirmationException e) { - throw new NoDashFatalException( - "Session claims to be awaiting confirmation before returning data to the user.", e); - } - } -} diff --git a/src/nodash/exceptions/NoDashException.java b/src/nodash/exceptions/NoDashException.java index 861be9b..13acc8d 100644 --- a/src/nodash/exceptions/NoDashException.java +++ b/src/nodash/exceptions/NoDashException.java @@ -23,7 +23,11 @@ public class NoDashException extends Exception { super(); } - public NoDashException(Exception e) { + public NoDashException(Throwable e) { super(e); } + + public NoDashException(String message, Throwable e) { + super(message, e); + } } diff --git a/src/nodash/exceptions/NoDashSessionBadUUIDException.java b/src/nodash/exceptions/NoDashSessionBadUuidException.java similarity index 84% rename from src/nodash/exceptions/NoDashSessionBadUUIDException.java rename to src/nodash/exceptions/NoDashSessionBadUuidException.java index 773166e..356eec9 100644 --- a/src/nodash/exceptions/NoDashSessionBadUUIDException.java +++ b/src/nodash/exceptions/NoDashSessionBadUuidException.java @@ -17,14 +17,14 @@ package nodash.exceptions; -public class NoDashSessionBadUUIDException extends Exception { +public class NoDashSessionBadUuidException extends Exception { private static final long serialVersionUID = -402131397575158344L; - public NoDashSessionBadUUIDException() { + public NoDashSessionBadUuidException() { super(); } - public NoDashSessionBadUUIDException(Exception e) { + public NoDashSessionBadUuidException(Exception e) { super(e); } } diff --git a/src/nodash/models/NoAction.java b/src/nodash/models/NoAction.java index 30956fb..cc87903 100644 --- a/src/nodash/models/NoAction.java +++ b/src/nodash/models/NoAction.java @@ -19,12 +19,14 @@ package nodash.models; import java.io.Serializable; +import nodash.core.NoAdapter; + public abstract class NoAction implements Serializable { private static final long serialVersionUID = -194752850197321803L; public abstract void process(); - public abstract void execute(); + public abstract void execute(NoAdapter adapter); public abstract void purge(); } diff --git a/src/nodash/models/NoSession.java b/src/nodash/models/NoSession.java index a94ea49..6a20c71 100644 --- a/src/nodash/models/NoSession.java +++ b/src/nodash/models/NoSession.java @@ -2,6 +2,8 @@ package nodash.models; import java.io.IOException; import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.UUID; @@ -10,11 +12,12 @@ import javax.crypto.IllegalBlockSizeException; import org.apache.commons.codec.binary.Base64; +import nodash.core.NoAdapter; import nodash.core.NoCore; import nodash.core.NoUtil; import nodash.exceptions.NoByteSetBadDecryptionException; import nodash.exceptions.NoDashFatalException; -import nodash.exceptions.NoDashSessionBadUUIDException; +import nodash.exceptions.NoDashSessionBadUuidException; import nodash.exceptions.NoSessionConfirmedException; import nodash.exceptions.NoSessionExpiredException; import nodash.exceptions.NoSessionNotAwaitingConfirmationException; @@ -34,14 +37,14 @@ public final class NoSession implements Serializable { private final long expiry; private boolean newUserSession; - public List incoming; - public NoUser current; - public UUID uuid; + private Collection incoming; + private NoUser current; + private String uuid; public NoSession() { this.state = NoState.IDLE; this.expiry = System.currentTimeMillis() + NoSession.SESSION_DURATION; - this.uuid = UUID.randomUUID(); + this.uuid = UUID.randomUUID().toString(); } public NoSession(NoUser newUser) { @@ -52,20 +55,12 @@ public final class NoSession implements Serializable { this.newUserSession = true; } - public NoSession(byte[] data, char[] password) throws NoUserNotValidException { + public NoSession(NoAdapter adapter, byte[] data, char[] password) throws NoUserNotValidException { this(); this.newUserSession = false; this.state = NoState.IDLE; - char[] passwordDupe = password.clone(); try { this.original = NoUser.createUserFromFile(data, password); - if (NoCore.hashSphere.checkHash(this.original.createHashString())) { - this.current = NoUser.createUserFromFile(data, passwordDupe); - this.uuid = UUID.randomUUID(); - NoUtil.wipeBytes(data); - } else { - throw new NoUserNotValidException(); - } } catch (IOException e) { throw new NoUserNotValidException(); } catch (IllegalBlockSizeException e) { @@ -87,7 +82,7 @@ public final class NoSession implements Serializable { } public NoState touchState() throws NoSessionConfirmedException, NoSessionExpiredException { - this.check(); + check(); if (this.newUserSession) { if (this.state != NoState.AWAITING_CONFIRMATION) { this.state = NoState.MODIFIED; @@ -106,16 +101,16 @@ public final class NoSession implements Serializable { public byte[] initiateSaveAttempt(char[] password) throws NoSessionConfirmedException, NoSessionExpiredException { - this.touchState(); + touchState(); this.state = NoState.AWAITING_CONFIRMATION; byte[] file = this.current.createFile(password); NoUtil.wipeChars(password); return file; } - public void confirmSave(byte[] confirmData, char[] password) throws NoSessionConfirmedException, + public void confirmSave(NoAdapter adapter, byte[] confirmData, char[] password) throws NoSessionConfirmedException, NoSessionExpiredException, NoSessionNotAwaitingConfirmationException, NoUserNotValidException { - this.check(); + check(); if (this.state != NoState.AWAITING_CONFIRMATION) { throw new NoSessionNotAwaitingConfirmationException(); } @@ -137,23 +132,8 @@ public final class NoSession implements Serializable { NoUtil.wipeChars(password); if (confirmed.createHashString().equals(this.current.createHashString())) { this.state = NoState.CONFIRMED; - /* 5.2: confirmed! */ - if (!this.newUserSession) { - /* 5.2.1: remove old hash from array */ - try { - NoCore.hashSphere.removeHash(this.original.createHashString()); - } catch (IOException e) { - throw new NoDashFatalException("Unable to remove hash on confirm.", e); - } - } - /* 5.2.2: add new hash to array */ - try { - NoCore.hashSphere.insertHash(this.current.createHashString()); - } catch (IOException e) { - throw new NoDashFatalException("Unable to remove hash on confirm.", e); - } - /* 5.2.3: clear influences as they will not need to be re-applied */ + this.incoming = new ArrayList(); List actions = this.current.getNoActions(); this.incoming = null; this.original = null; @@ -164,7 +144,7 @@ public final class NoSession implements Serializable { * It is assumed that actions are not long-running tasks It is also assumed that actions * have the information they need without the user objects */ - action.execute(); + action.execute(adapter); action.purge(); } } else { @@ -173,29 +153,34 @@ public final class NoSession implements Serializable { } public NoState getNoState() throws NoSessionConfirmedException, NoSessionExpiredException { - this.touchState(); + touchState(); return this.state; } public NoUser getNoUser() throws NoSessionConfirmedException, NoSessionExpiredException { - this.check(); + check(); return this.current; } - - public UUID getUuid() { + + public NoUser getNoUserSafe() { + return this.current; + } + + public Collection getIncoming() throws NoSessionConfirmedException, NoSessionExpiredException { + check(); + return this.incoming; + } + + public Collection getIncomingSafe() { + return this.incoming; + } + + public String getUuid() { return this.uuid; } - public String getUuidAsString() { - return this.uuid.toString(); - } - public byte[] getEncryptedUuid() { - return NoUtil.encrypt(Base64.encodeBase64(this.uuid.toString().getBytes())); - } - - public String getEncryptedUuidAsString() { - return new String(this.getEncryptedUuid()); + return NoUtil.encrypt(Base64.decodeBase64(getUuid())); } public byte[] getOriginalHash() { @@ -205,24 +190,33 @@ public final class NoSession implements Serializable { return null; } } + + private static String decryptUuid(String data) throws NoDashSessionBadUuidException { + return decryptUuid(Base64.decodeBase64(data)); + } - public static UUID decryptUuid(byte[] data) throws NoDashSessionBadUUIDException { + private static String decryptUuid(byte[] data) throws NoDashSessionBadUuidException { if (data == null) { - throw new NoDashSessionBadUUIDException(); + throw new NoDashSessionBadUuidException(); } try { - return UUID.fromString(new String(Base64.decodeBase64(NoUtil.decrypt(data)))); + return Base64.encodeBase64String(NoUtil.decrypt(data)); } catch (IllegalArgumentException e) { - throw new NoDashSessionBadUUIDException(); + throw new NoDashSessionBadUuidException(); } catch (IllegalBlockSizeException e) { - throw new NoDashSessionBadUUIDException(); + throw new NoDashSessionBadUuidException(); } catch (BadPaddingException e) { - throw new NoDashSessionBadUUIDException(); + throw new NoDashSessionBadUuidException(); } } + + public void setIncoming(Collection incoming) { + this.incoming = incoming; + } - public void consume(NoByteSet byteSet) throws NoByteSetBadDecryptionException { + public void consume(NoByteSet byteSet) throws NoByteSetBadDecryptionException, NoSessionConfirmedException, NoSessionExpiredException { + check(); this.current.consume(byteSet); } diff --git a/src/nodash/test/NoCoreTest.java b/src/nodash/test/NoCoreTest.java new file mode 100644 index 0000000..80558ac --- /dev/null +++ b/src/nodash/test/NoCoreTest.java @@ -0,0 +1,142 @@ +package nodash.test; + +import static org.junit.Assert.*; + +import java.util.Arrays; + +import nodash.core.NoAdapter; +import nodash.core.NoCore; +import nodash.core.NoDefaultAdapter; +import nodash.core.NoRegister; +import nodash.exceptions.NoDashSessionBadUuidException; +import nodash.exceptions.NoSessionAlreadyAwaitingConfirmationException; +import nodash.exceptions.NoSessionConfirmedException; +import nodash.exceptions.NoSessionExpiredException; +import nodash.exceptions.NoSessionNotAwaitingConfirmationException; +import nodash.exceptions.NoSessionNotChangedException; +import nodash.exceptions.NoUserAlreadyOnlineException; +import nodash.exceptions.NoUserNotValidException; +import nodash.models.NoSession; +import nodash.models.NoUser; + +import org.junit.Test; + +public class NoCoreTest { + + @Test + public void testLogin() { + NoCore core = new NoCore(new NoDefaultAdapter()); + fail("Not yet implemented"); + } + + @Test + public void testRegister() { + NoCore core = new NoCore(new NoDefaultAdapter()); + + NoUser user1 = new NoUser(); + NoRegister registration1 = core.register(user1, "password".toCharArray()); + assertNotNull(registration1.cookie); + assertNotNull(registration1.data); + + NoUser user2 = new NoUser(); + NoRegister registration2 = core.register(user2, "password".toCharArray()); + + assertFalse(Arrays.equals(registration1.cookie, registration2.cookie)); + assertFalse(Arrays.equals(registration2.data, registration2.data)); + + NoUser user3 = new NoUser(); + try { + core.register(null, "password".toCharArray()); + fail("Did not throw NullPointerException."); + } catch (NullPointerException e) { + // Do nothing, correct + } + + try { + core.register(user3, null); + fail("Did not throw NullPointerException."); + } catch (NullPointerException e) { + // Do nothing, correct + } + + try { + core.register(null, null); + fail("Did not throw NullPointerException."); + } catch (NullPointerException e) { + // Do nothing, correct + } + } + + @Test + public void testSaveAndConfirm() throws NoSessionExpiredException, NoSessionConfirmedException, + NoSessionNotAwaitingConfirmationException, NoUserNotValidException, + NoDashSessionBadUuidException, NoUserAlreadyOnlineException, NoSessionNotChangedException, NoSessionAlreadyAwaitingConfirmationException { + NoAdapter adapter = new NoDefaultAdapter(); + NoCore core = new NoCore(adapter); + + NoUser newUser = new NoUser(); + NoRegister registration = core.register(newUser, "password".toCharArray()); + byte[] newUserFile = Arrays.copyOf(registration.data, registration.data.length); + core.confirm(registration.cookie, "password".toCharArray(), newUserFile); + byte[] newUserHash = newUser.createHash(); + assertTrue(adapter.checkHash(newUserHash)); + + NoUser newUserBadPass = new NoUser(); + registration = core.register(newUserBadPass, "password".toCharArray()); + byte[] newUserBadPassFile = Arrays.copyOf(registration.data, registration.data.length); + try { + core.confirm(registration.cookie, "badpassword".toCharArray(), newUserBadPassFile); + fail("Confirmed with a bad password without throwing an exception."); + } catch (NoUserNotValidException e) { + // Do nothing, true + } + + try { + core.confirm(new byte[] {'b', 'a', 'd', 'c', 'o', 'o', 'k', 'i', 'e'}, "password".toCharArray(), + newUserBadPassFile); + fail("Confirmed on bad cookie without throwing exception."); + } catch (NoSessionExpiredException e) { + // Do nothing, true + } + + NoUser oldUser = new NoUser(); + registration = core.register(oldUser, "password".toCharArray()); + byte[] oldUserFile = Arrays.copyOf(registration.data, registration.data.length); + core.confirm(registration.cookie, "password".toCharArray(), oldUserFile); + + oldUserFile = Arrays.copyOf(registration.data, registration.data.length); + byte[] oldUserCookie = core.login(oldUserFile, "password".toCharArray()); + assertNotNull(adapter.getNoSession(oldUserCookie)); + oldUser.createFile("password".toCharArray()); // Touch the randomizer + + NoUser oldUserRevisited = core.getUser(oldUserCookie); + byte[] currentHash = oldUserRevisited.createHash(); + oldUserRevisited.createFile("password".toCharArray()); + byte[] oldCreatedFile = core.save(oldUserCookie, "new-password".toCharArray()); + byte[] oldUserHash = oldUserRevisited.createHash(); + core.confirm(oldUserCookie, "new-password".toCharArray(), oldCreatedFile); + assertFalse(adapter.containsNoSession(oldUserCookie)); + assertTrue(adapter.checkHash(oldUserHash)); + assertFalse(adapter.checkHash(currentHash)); + } + + + @Test + public void testGetUser() { + NoCore core = new NoCore(new NoDefaultAdapter()); + fail("Not yet implemented"); + } + + @Test + public void testGetSessionState() { + NoCore core = new NoCore(new NoDefaultAdapter()); + fail("Not yet implemented"); + } + + @Test + public void testShred() { + NoCore core = new NoCore(new NoDefaultAdapter()); + fail("Not yet implemented"); + } + +} diff --git a/src/nodash/test/NoSessionTest.java b/src/nodash/test/NoSessionTest.java new file mode 100644 index 0000000..120db9c --- /dev/null +++ b/src/nodash/test/NoSessionTest.java @@ -0,0 +1,72 @@ +package nodash.test; + +import static org.junit.Assert.*; +import nodash.core.NoCore; +import nodash.exceptions.NoSessionConfirmedException; +import nodash.exceptions.NoSessionExpiredException; +import nodash.models.NoSession; + +import org.junit.Before; +import org.junit.Test; + +public class NoSessionTest { + + @Before + public void setup() { + NoCore.setup(); + } + + @Test + public void testNoSession() throws NoSessionConfirmedException, NoSessionExpiredException { + NoSession session = new NoSession(); + assertNotNull(session.getUuid()); + assertNull(session.getNoUser()); + + } + + @Test + public void testNoSessionNoUser() { + fail("Not yet implemented"); + } + + @Test + public void testNoSessionByteArrayCharArray() { + fail("Not yet implemented"); + } + + @Test + public void testCheck() { + fail("Not yet implemented"); + } + + @Test + public void testTouchState() { + fail("Not yet implemented"); + } + + @Test + public void testInitiateSaveAttempt() { + fail("Not yet implemented"); + } + + @Test + public void testConfirmSave() { + fail("Not yet implemented"); + } + + @Test + public void testDecryptUuid() { + fail("Not yet implemented"); + } + + @Test + public void testConsume() { + fail("Not yet implemented"); + } + + @Test + public void testClose() { + fail("Not yet implemented"); + } + +}