added GSON, assorted changes to try get a different file system working
This commit is contained in:
BIN
lib/gson-2.5.jar
Normal file
BIN
lib/gson-2.5.jar
Normal file
Binary file not shown.
@@ -285,6 +285,7 @@ public final class NoCore {
|
|||||||
byte[] oldHash = session.getOriginalHash();
|
byte[] oldHash = session.getOriginalHash();
|
||||||
byte[] newHash = session.getNoUserSafe().createHash();
|
byte[] newHash = session.getNoUserSafe().createHash();
|
||||||
|
|
||||||
|
try {
|
||||||
session.confirmSave(adapter, data, password);
|
session.confirmSave(adapter, data, password);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -292,7 +293,7 @@ public final class NoCore {
|
|||||||
} catch (NoAdapterException e) {
|
} catch (NoAdapterException e) {
|
||||||
throw new NoDashFatalException("Could not insert confirmed hash.", e);
|
throw new NoDashFatalException("Could not insert confirmed hash.", e);
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
try {
|
try {
|
||||||
adapter.shredNoSession(cookie);
|
adapter.shredNoSession(cookie);
|
||||||
} catch (NoAdapterException e) {
|
} catch (NoAdapterException e) {
|
||||||
@@ -304,6 +305,8 @@ public final class NoCore {
|
|||||||
} catch (NoAdapterException e) {
|
} catch (NoAdapterException e) {
|
||||||
throw new NoDashFatalException("Could not go offline.", e);
|
throw new NoDashFatalException("Could not go offline.", e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!session.isNewUser()) {
|
if (!session.isNewUser()) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package nodash.core;
|
package nodash.core;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
@@ -37,6 +38,7 @@ import javax.crypto.spec.SecretKeySpec;
|
|||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
import nodash.exceptions.NoDashFatalException;
|
import nodash.exceptions.NoDashFatalException;
|
||||||
|
import nodash.models.NoUser;
|
||||||
|
|
||||||
public final class NoUtil {
|
public final class NoUtil {
|
||||||
public static final SecretKey SECRET_KEY = setupSecretKey();
|
public static final SecretKey SECRET_KEY = setupSecretKey();
|
||||||
@@ -51,6 +53,18 @@ public final class NoUtil {
|
|||||||
public static final int RSA_STRENGTH = setupRsaStrength();
|
public static final int RSA_STRENGTH = setupRsaStrength();
|
||||||
public static final int AES_STRENGTH = 256;
|
public static final int AES_STRENGTH = 256;
|
||||||
public static final byte BLANK_BYTE = 'A';
|
public static final byte BLANK_BYTE = 'A';
|
||||||
|
public static final Class<? extends NoUser> NO_USER_CLASS = setupNoUserClass();
|
||||||
|
|
||||||
|
private static Class<? extends NoUser> setupNoUserClass() {
|
||||||
|
String secretEnv = System.getenv("NODASH_USER_CLASS");
|
||||||
|
try {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Class<? extends NoUser> clazz = (Class<? extends NoUser>) Class.forName(secretEnv);
|
||||||
|
return clazz;
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException("Can't find NODASH_USER_CLASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static SecretKey setupSecretKey() {
|
private static SecretKey setupSecretKey() {
|
||||||
String secretEnv = System.getenv("NODASH_SECRET");
|
String secretEnv = System.getenv("NODASH_SECRET");
|
||||||
@@ -71,6 +85,14 @@ public final class NoUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] toBytes(String string) {
|
||||||
|
return string.getBytes(Charset.forName("UTF-8"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String fromBytes(byte[] bytes) {
|
||||||
|
return new String(bytes, Charset.forName("UTF-8"));
|
||||||
|
}
|
||||||
|
|
||||||
public static char[] bytesToChars(byte[] array) {
|
public static char[] bytesToChars(byte[] array) {
|
||||||
char[] result = new char[array.length];
|
char[] result = new char[array.length];
|
||||||
for (int x = 0; x < array.length; x++) {
|
for (int x = 0; x < array.length; x++) {
|
||||||
@@ -126,8 +148,8 @@ public final class NoUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] decrypt(byte[] data, char[] password) throws IllegalBlockSizeException,
|
public static byte[] decrypt(byte[] data, char[] password)
|
||||||
BadPaddingException {
|
throws IllegalBlockSizeException, BadPaddingException {
|
||||||
byte[] passwordByte = NoUtil.getPbeKeyFromPassword(password);
|
byte[] passwordByte = NoUtil.getPbeKeyFromPassword(password);
|
||||||
byte[] response = NoUtil.decrypt(NoUtil.decrypt(data), passwordByte);
|
byte[] response = NoUtil.decrypt(NoUtil.decrypt(data), passwordByte);
|
||||||
NoUtil.wipeBytes(passwordByte);
|
NoUtil.wipeBytes(passwordByte);
|
||||||
@@ -170,8 +192,8 @@ public final class NoUtil {
|
|||||||
return NoUtil.encrypt(data, SECRET_KEY.getEncoded());
|
return NoUtil.encrypt(data, SECRET_KEY.getEncoded());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] decrypt(byte[] data, byte[] key) throws IllegalBlockSizeException,
|
public static byte[] decrypt(byte[] data, byte[] key)
|
||||||
BadPaddingException {
|
throws IllegalBlockSizeException, BadPaddingException {
|
||||||
Cipher cipher;
|
Cipher cipher;
|
||||||
try {
|
try {
|
||||||
cipher = Cipher.getInstance(NoUtil.CIPHER_TYPE);
|
cipher = Cipher.getInstance(NoUtil.CIPHER_TYPE);
|
||||||
@@ -202,7 +224,8 @@ public final class NoUtil {
|
|||||||
throw new NoDashFatalException("Value for CIPHER_RSA_TYPE is not valid (no such algorithm).",
|
throw new NoDashFatalException("Value for CIPHER_RSA_TYPE is not valid (no such algorithm).",
|
||||||
e);
|
e);
|
||||||
} catch (NoSuchPaddingException e) {
|
} catch (NoSuchPaddingException e) {
|
||||||
throw new NoDashFatalException("Value for CIPHER_RSA_TYPE is not valid (no such padding).", e);
|
throw new NoDashFatalException("Value for CIPHER_RSA_TYPE is not valid (no such padding).",
|
||||||
|
e);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||||
@@ -216,8 +239,8 @@ public final class NoUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] decryptRsa(byte[] data, PrivateKey privateKey) throws InvalidKeyException,
|
public static byte[] decryptRsa(byte[] data, PrivateKey privateKey)
|
||||||
IllegalBlockSizeException, BadPaddingException {
|
throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
|
||||||
Cipher cipher;
|
Cipher cipher;
|
||||||
try {
|
try {
|
||||||
cipher = Cipher.getInstance(NoUtil.CIPHER_RSA_TYPE);
|
cipher = Cipher.getInstance(NoUtil.CIPHER_RSA_TYPE);
|
||||||
@@ -225,7 +248,8 @@ public final class NoUtil {
|
|||||||
throw new NoDashFatalException("Value for CIPHER_RSA_TYPE is not valid (no such algorithm).",
|
throw new NoDashFatalException("Value for CIPHER_RSA_TYPE is not valid (no such algorithm).",
|
||||||
e);
|
e);
|
||||||
} catch (NoSuchPaddingException e) {
|
} catch (NoSuchPaddingException e) {
|
||||||
throw new NoDashFatalException("Value for CIPHER_RSA_TYPE is not valid (no such padding).", e);
|
throw new NoDashFatalException("Value for CIPHER_RSA_TYPE is not valid (no such padding).",
|
||||||
|
e);
|
||||||
}
|
}
|
||||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||||
return cipher.doFinal(data);
|
return cipher.doFinal(data);
|
||||||
|
|||||||
9
src/nodash/models/NoHash.java
Normal file
9
src/nodash/models/NoHash.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package nodash.models;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface NoHash {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package nodash.models;
|
package nodash.models;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -13,6 +12,8 @@ import javax.crypto.IllegalBlockSizeException;
|
|||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
import nodash.core.NoAdapter;
|
import nodash.core.NoAdapter;
|
||||||
import nodash.core.NoUtil;
|
import nodash.core.NoUtil;
|
||||||
import nodash.exceptions.NoByteSetBadDecryptionException;
|
import nodash.exceptions.NoByteSetBadDecryptionException;
|
||||||
@@ -60,19 +61,16 @@ public final class NoSession implements Serializable {
|
|||||||
try {
|
try {
|
||||||
byte[] originalData = Arrays.copyOf(data, data.length);
|
byte[] originalData = Arrays.copyOf(data, data.length);
|
||||||
char[] originalPassword = Arrays.copyOf(password, password.length);
|
char[] originalPassword = Arrays.copyOf(password, password.length);
|
||||||
this.original = NoUser.createUserFromFile(originalData, originalPassword);
|
this.original =
|
||||||
this.current = NoUser.createUserFromFile(data, password);
|
NoUser.createUserFromFile(originalData, originalPassword, NoUtil.NO_USER_CLASS);
|
||||||
|
this.current = NoUser.createUserFromFile(data, password, NoUtil.NO_USER_CLASS);
|
||||||
NoUtil.wipeBytes(data);
|
NoUtil.wipeBytes(data);
|
||||||
NoUtil.wipeChars(password);
|
NoUtil.wipeChars(password);
|
||||||
this.uuid = UUID.randomUUID().toString();
|
this.uuid = UUID.randomUUID().toString();
|
||||||
} catch (IOException e) {
|
|
||||||
throw new NoUserNotValidException(e);
|
|
||||||
} catch (IllegalBlockSizeException e) {
|
} catch (IllegalBlockSizeException e) {
|
||||||
throw new NoUserNotValidException();
|
throw new NoUserNotValidException();
|
||||||
} catch (BadPaddingException e) {
|
} catch (BadPaddingException e) {
|
||||||
throw new NoUserNotValidException();
|
throw new NoUserNotValidException();
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
throw new NoUserNotValidException();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,8 +101,8 @@ public final class NoSession implements Serializable {
|
|||||||
return this.state;
|
return this.state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] initiateSaveAttempt(char[] password) throws NoSessionConfirmedException,
|
public byte[] initiateSaveAttempt(char[] password)
|
||||||
NoSessionExpiredException {
|
throws NoSessionConfirmedException, NoSessionExpiredException {
|
||||||
touchState();
|
touchState();
|
||||||
this.state = NoState.AWAITING_CONFIRMATION;
|
this.state = NoState.AWAITING_CONFIRMATION;
|
||||||
byte[] file = this.current.createFile(password);
|
byte[] file = this.current.createFile(password);
|
||||||
@@ -112,8 +110,9 @@ public final class NoSession implements Serializable {
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void confirmSave(NoAdapter adapter, byte[] confirmData, char[] password) throws NoSessionConfirmedException,
|
public void confirmSave(NoAdapter adapter, byte[] confirmData, char[] password)
|
||||||
NoSessionExpiredException, NoSessionNotAwaitingConfirmationException, NoUserNotValidException {
|
throws NoSessionConfirmedException, NoSessionExpiredException,
|
||||||
|
NoSessionNotAwaitingConfirmationException, NoUserNotValidException {
|
||||||
check();
|
check();
|
||||||
if (this.state != NoState.AWAITING_CONFIRMATION) {
|
if (this.state != NoState.AWAITING_CONFIRMATION) {
|
||||||
throw new NoSessionNotAwaitingConfirmationException();
|
throw new NoSessionNotAwaitingConfirmationException();
|
||||||
@@ -121,30 +120,27 @@ public final class NoSession implements Serializable {
|
|||||||
|
|
||||||
NoUser confirmed;
|
NoUser confirmed;
|
||||||
try {
|
try {
|
||||||
confirmed = NoUser.createUserFromFile(confirmData, password);
|
confirmed = NoUser.createUserFromFile(confirmData, password, NoUtil.NO_USER_CLASS);
|
||||||
} catch (IOException e) {
|
|
||||||
throw new NoUserNotValidException(e);
|
|
||||||
} catch (IllegalBlockSizeException e) {
|
} catch (IllegalBlockSizeException e) {
|
||||||
throw new NoUserNotValidException();
|
throw new NoUserNotValidException();
|
||||||
} catch (BadPaddingException e) {
|
} catch (BadPaddingException e) {
|
||||||
throw new NoUserNotValidException();
|
throw new NoUserNotValidException();
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
throw new NoUserNotValidException(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NoUtil.wipeBytes(confirmData);
|
NoUtil.wipeBytes(confirmData);
|
||||||
NoUtil.wipeChars(password);
|
NoUtil.wipeChars(password);
|
||||||
if (confirmed.createHashString().equals(this.current.createHashString())) {
|
|
||||||
|
if (confirmed.createHashString().equals(current.createHashString())) {
|
||||||
this.state = NoState.CONFIRMED;
|
this.state = NoState.CONFIRMED;
|
||||||
/* 5.2.3: clear influences as they will not need to be re-applied */
|
/* 5.2.3: clear influences as they will not need to be re-applied */
|
||||||
this.incoming = new ArrayList<NoByteSet>();
|
this.incoming = new ArrayList<NoByteSet>();
|
||||||
List<NoAction> actions = this.current.getNoActions();
|
List<NoAction> actions = current.getNoActions();
|
||||||
this.incoming = null;
|
this.incoming = null;
|
||||||
/* 5.2.4: execute NoActions */
|
/* 5.2.4: execute NoActions */
|
||||||
for (NoAction action : actions) {
|
for (NoAction action : actions) {
|
||||||
/*
|
/*
|
||||||
* It is assumed that actions are not long-running tasks It is also assumed that actions
|
* It is assumed that actions are not long-running tasks
|
||||||
* have the information they need without the user objects
|
* It is also assumed that actions have the information they need without the user objects
|
||||||
*/
|
*/
|
||||||
action.execute(adapter);
|
action.execute(adapter);
|
||||||
action.purge();
|
action.purge();
|
||||||
@@ -168,7 +164,8 @@ public final class NoSession implements Serializable {
|
|||||||
return this.current;
|
return this.current;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<NoByteSet> getIncoming() throws NoSessionConfirmedException, NoSessionExpiredException {
|
public Collection<NoByteSet> getIncoming()
|
||||||
|
throws NoSessionConfirmedException, NoSessionExpiredException {
|
||||||
check();
|
check();
|
||||||
return this.incoming;
|
return this.incoming;
|
||||||
}
|
}
|
||||||
@@ -197,7 +194,8 @@ public final class NoSession implements Serializable {
|
|||||||
this.incoming = incoming;
|
this.incoming = incoming;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void consume(NoByteSet byteSet) throws NoByteSetBadDecryptionException, NoSessionConfirmedException, NoSessionExpiredException {
|
public void consume(NoByteSet byteSet) throws NoByteSetBadDecryptionException,
|
||||||
|
NoSessionConfirmedException, NoSessionExpiredException {
|
||||||
check();
|
check();
|
||||||
this.current.consume(byteSet);
|
this.current.consume(byteSet);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,13 +18,14 @@
|
|||||||
|
|
||||||
package nodash.models;
|
package nodash.models;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectInputStream;
|
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.KeyPairGenerator;
|
import java.security.KeyPairGenerator;
|
||||||
@@ -34,6 +35,8 @@ import java.security.PrivateKey;
|
|||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
@@ -43,6 +46,9 @@ import javax.crypto.spec.SecretKeySpec;
|
|||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
import sun.security.rsa.RSAPrivateCrtKeyImpl;
|
||||||
import sun.security.rsa.RSAPublicKeyImpl;
|
import sun.security.rsa.RSAPublicKeyImpl;
|
||||||
import nodash.core.NoUtil;
|
import nodash.core.NoUtil;
|
||||||
import nodash.exceptions.NoByteSetBadDecryptionException;
|
import nodash.exceptions.NoByteSetBadDecryptionException;
|
||||||
@@ -50,13 +56,17 @@ import nodash.exceptions.NoDashFatalException;
|
|||||||
|
|
||||||
public class NoUser implements Serializable {
|
public class NoUser implements Serializable {
|
||||||
private static final long serialVersionUID = 7132405837081692211L;
|
private static final long serialVersionUID = 7132405837081692211L;
|
||||||
private PublicKey publicKey;
|
@NoHash
|
||||||
private PrivateKey privateKey;
|
private RSAPublicKeyImpl publicKey;
|
||||||
@SuppressWarnings("unused")
|
@NoHash
|
||||||
|
private RSAPrivateCrtKeyImpl privateKey;
|
||||||
|
@NoHash
|
||||||
private String randomized;
|
private String randomized;
|
||||||
|
|
||||||
|
@NoHash
|
||||||
private int influences;
|
private int influences;
|
||||||
@SuppressWarnings("unused")
|
|
||||||
|
@NoHash
|
||||||
private int actions;
|
private int actions;
|
||||||
|
|
||||||
private List<NoAction> outgoing = new ArrayList<NoAction>();
|
private List<NoAction> outgoing = new ArrayList<NoAction>();
|
||||||
@@ -79,11 +89,11 @@ public class NoUser implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KeyPair keyPair = kpg.generateKeyPair();
|
KeyPair keyPair = kpg.generateKeyPair();
|
||||||
this.publicKey = keyPair.getPublic();
|
this.publicKey = (RSAPublicKeyImpl) keyPair.getPublic();
|
||||||
this.privateKey = keyPair.getPrivate();
|
this.privateKey = (RSAPrivateCrtKeyImpl) keyPair.getPrivate();
|
||||||
this.influences = 0;
|
this.influences = 0;
|
||||||
this.actions = 0;
|
this.actions = 0;
|
||||||
this.touchRandomizer();
|
touchRandomizer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void touchRandomizer() {
|
private void touchRandomizer() {
|
||||||
@@ -93,42 +103,70 @@ public class NoUser implements Serializable {
|
|||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
throw new NoDashFatalException("Value for SECURERANDOM_ALGORITHM not valid.", e);
|
throw new NoDashFatalException("Value for SECURERANDOM_ALGORITHM not valid.", e);
|
||||||
}
|
}
|
||||||
this.randomized = new String(randomBytes);
|
randomized = new String(randomBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final byte[] createFile(char[] password) {
|
public final byte[] createFile(char[] password) {
|
||||||
List<NoAction> temp = this.outgoing;
|
List<NoAction> tempActions = outgoing;
|
||||||
try {
|
int tempActionCount = actions;
|
||||||
this.touchRandomizer();
|
|
||||||
this.outgoing = new ArrayList<NoAction>();
|
touchRandomizer();
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
outgoing = new ArrayList<NoAction>();
|
||||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
actions = 0;
|
||||||
oos.writeObject(this);
|
|
||||||
byte[] encrypted = NoUtil.encrypt(baos.toByteArray(), password);
|
Gson gson = new Gson();
|
||||||
oos.close();
|
byte[] json = NoUtil.toBytes(gson.toJson(this));
|
||||||
baos.close();
|
byte[] encrypted = NoUtil.encrypt(json, password);
|
||||||
|
|
||||||
|
actions = tempActionCount;
|
||||||
|
outgoing = tempActions;
|
||||||
return encrypted;
|
return encrypted;
|
||||||
} catch (IOException e) {
|
|
||||||
throw new NoDashFatalException(
|
|
||||||
"IO Exception encountered while generating encrypted user file byte stream.", e);
|
|
||||||
} finally {
|
|
||||||
this.outgoing = temp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final byte[] createHash() {
|
public final byte[] createHash() {
|
||||||
List<NoAction> temp = this.outgoing;
|
|
||||||
try {
|
try {
|
||||||
this.outgoing = new ArrayList<NoAction>();
|
List<Object> items = new ArrayList<Object>();
|
||||||
|
Comparator<Field> fieldComp = new Comparator<Field>() {
|
||||||
|
@Override
|
||||||
|
public int compare(Field o1, Field o2) {
|
||||||
|
return o1.getName().compareTo(o2.getName());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Class<? extends NoUser> userClass = getClass();
|
||||||
|
|
||||||
|
while (userClass != null) {
|
||||||
|
Field[] noHashFields = userClass.getDeclaredFields();
|
||||||
|
|
||||||
|
Arrays.sort(noHashFields, fieldComp);
|
||||||
|
|
||||||
|
for (Field field : noHashFields) {
|
||||||
|
if (field.isAnnotationPresent(NoHash.class)) {
|
||||||
|
field.setAccessible(true);
|
||||||
|
items.add(field.get(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userClass == NoUser.class) {
|
||||||
|
userClass = null;
|
||||||
|
} else {
|
||||||
|
userClass = (Class<? extends NoUser>) userClass.getSuperclass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||||
oos.writeObject(this);
|
oos.writeObject(items);
|
||||||
byte[] userBytes = baos.toByteArray();
|
byte[] itemBytes = baos.toByteArray();
|
||||||
return NoUtil.getHashFromByteArray(userBytes);
|
|
||||||
|
return NoUtil.getHashFromByteArray(itemBytes);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new NoDashFatalException("IO Exception encountered while generating user hash.", e);
|
throw new NoDashFatalException("IO Exception encountered while generating user hash.", e);
|
||||||
} finally {
|
} catch (IllegalArgumentException e) {
|
||||||
this.outgoing = temp;
|
throw new NoDashFatalException("IllegalArgument Exception encountered while generating user hash.", e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new NoDashFatalException("IllegalAccess Exception encountered while generating user hash.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,28 +220,28 @@ public class NoUser implements Serializable {
|
|||||||
return influences;
|
return influences;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final byte[] decryptRsa(byte[] data) throws InvalidKeyException,
|
private final byte[] decryptRsa(byte[] data)
|
||||||
IllegalBlockSizeException, BadPaddingException {
|
throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
|
||||||
return NoUtil.decryptRsa(data, this.privateKey);
|
return NoUtil.decryptRsa(data, this.privateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NoUser createUserFromFile(byte[] data, char[] password)
|
public static NoUser createUserFromFile(byte[] data, char[] password, Class<? extends NoUser> clazz)
|
||||||
throws IllegalBlockSizeException, BadPaddingException, IOException, ClassNotFoundException {
|
throws IllegalBlockSizeException, BadPaddingException {
|
||||||
byte[] decrypted = NoUtil.decrypt(data, password);
|
byte[] decrypted = NoUtil.decrypt(data, password);
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(decrypted);
|
|
||||||
ObjectInputStream ois = new ObjectInputStream(bais);
|
Gson gson = new Gson();
|
||||||
NoUser noUser = (NoUser) ois.readObject();
|
String json = NoUtil.fromBytes(decrypted);
|
||||||
ois.close();
|
NoUser noUser = gson.fromJson(json, clazz);
|
||||||
bais.close();
|
|
||||||
return noUser;
|
return noUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String createHashString() {
|
public String createHashString() {
|
||||||
return Base64.encodeBase64URLSafeString(this.createHash());
|
return Base64.encodeBase64URLSafeString(createHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object otherUser) {
|
public final boolean equals(Object otherUser) {
|
||||||
if (otherUser == null) {
|
if (otherUser == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ package nodash.test;
|
|||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import nodash.core.NoAdapter;
|
import nodash.core.NoAdapter;
|
||||||
@@ -84,7 +86,8 @@ public class NoCoreTest {
|
|||||||
public void testSaveAndConfirm() throws NoSessionExpiredException, NoSessionConfirmedException,
|
public void testSaveAndConfirm() throws NoSessionExpiredException, NoSessionConfirmedException,
|
||||||
NoSessionNotAwaitingConfirmationException, NoUserNotValidException,
|
NoSessionNotAwaitingConfirmationException, NoUserNotValidException,
|
||||||
NoDashSessionBadUuidException, NoUserAlreadyOnlineException, NoSessionNotChangedException,
|
NoDashSessionBadUuidException, NoUserAlreadyOnlineException, NoSessionNotChangedException,
|
||||||
NoSessionAlreadyAwaitingConfirmationException, NoAdapterException {
|
NoSessionAlreadyAwaitingConfirmationException, NoAdapterException, NoSuchMethodException,
|
||||||
|
SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||||
NoAdapter adapter = new NoDefaultAdapter();
|
NoAdapter adapter = new NoDefaultAdapter();
|
||||||
NoCore core = new NoCore(adapter);
|
NoCore core = new NoCore(adapter);
|
||||||
|
|
||||||
@@ -135,6 +138,11 @@ public class NoCoreTest {
|
|||||||
NoUser oldUserRevisited = core.getNoUser(oldUserCookie);
|
NoUser oldUserRevisited = core.getNoUser(oldUserCookie);
|
||||||
byte[] currentHash = oldUserRevisited.createHash();
|
byte[] currentHash = oldUserRevisited.createHash();
|
||||||
oldUserRevisited.createFile("password".toCharArray());
|
oldUserRevisited.createFile("password".toCharArray());
|
||||||
|
|
||||||
|
Method touchRandomizer = NoUser.class.getDeclaredMethod("touchRandomizer");
|
||||||
|
touchRandomizer.setAccessible(true);
|
||||||
|
touchRandomizer.invoke(adapter.getNoSession(oldUserCookie).getNoUser());
|
||||||
|
|
||||||
byte[] oldCreatedFile = core.save(oldUserCookie, "new-password".toCharArray());
|
byte[] oldCreatedFile = core.save(oldUserCookie, "new-password".toCharArray());
|
||||||
byte[] oldUserHash = oldUserRevisited.createHash();
|
byte[] oldUserHash = oldUserRevisited.createHash();
|
||||||
core.confirm(oldUserCookie, "new-password".toCharArray(), oldCreatedFile);
|
core.confirm(oldUserCookie, "new-password".toCharArray(), oldCreatedFile);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import java.util.Arrays;
|
|||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
|
|
||||||
|
import nodash.core.NoUtil;
|
||||||
import nodash.models.NoUser;
|
import nodash.models.NoUser;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
@@ -80,8 +81,8 @@ public class NoUserTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateUserFromFile() throws IllegalBlockSizeException, BadPaddingException,
|
public void testCreateUserFromFile()
|
||||||
ClassNotFoundException, IOException {
|
throws IllegalBlockSizeException, BadPaddingException, ClassNotFoundException, IOException {
|
||||||
NoUser user = new NoUser();
|
NoUser user = new NoUser();
|
||||||
final byte[] originalFile = user.createFile("password".toCharArray());
|
final byte[] originalFile = user.createFile("password".toCharArray());
|
||||||
byte[] file = Arrays.copyOf(originalFile, originalFile.length);
|
byte[] file = Arrays.copyOf(originalFile, originalFile.length);
|
||||||
@@ -90,34 +91,34 @@ public class NoUserTest {
|
|||||||
user = null;
|
user = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
user = NoUser.createUserFromFile(file, "wrongpassword".toCharArray());
|
user = NoUser.createUserFromFile(file, "wrongpassword".toCharArray(), NoUtil.NO_USER_CLASS);
|
||||||
fail("Should have thrown an error when given wrong password.");
|
fail("Should have thrown an error when given wrong password.");
|
||||||
} catch (BadPaddingException e) {
|
} catch (BadPaddingException e) {
|
||||||
// Do nothing, correct
|
// Do nothing, correct
|
||||||
}
|
}
|
||||||
|
|
||||||
file = Arrays.copyOf(originalFile, originalFile.length);
|
file = Arrays.copyOf(originalFile, originalFile.length);
|
||||||
user = NoUser.createUserFromFile(file, "password".toCharArray());
|
user = NoUser.createUserFromFile(file, "password".toCharArray(), NoUtil.NO_USER_CLASS);
|
||||||
assertTrue(Arrays.equals(hash, user.createHash()));
|
assertTrue(Arrays.equals(hash, user.createHash()));
|
||||||
assertEquals(hashString, user.createHashString());
|
assertEquals(hashString, user.createHashString());
|
||||||
|
|
||||||
file = Arrays.copyOf(originalFile, originalFile.length);
|
file = Arrays.copyOf(originalFile, originalFile.length);
|
||||||
try {
|
try {
|
||||||
NoUser.createUserFromFile(file, null);
|
NoUser.createUserFromFile(file, null, NoUtil.NO_USER_CLASS);
|
||||||
fail("Should have thrown a NullPointerException.");
|
fail("Should have thrown a NullPointerException.");
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
// Do nothing, correct
|
// Do nothing, correct
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
NoUser.createUserFromFile(null, "password".toCharArray());
|
NoUser.createUserFromFile(null, "password".toCharArray(), NoUtil.NO_USER_CLASS);
|
||||||
fail("Should have thrown a IllegalArgumentException.");
|
fail("Should have thrown a IllegalArgumentException.");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// Do nothing, correct
|
// Do nothing, correct
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
NoUser.createUserFromFile(null, null);
|
NoUser.createUserFromFile(null, null, NoUtil.NO_USER_CLASS);
|
||||||
fail("Should have thrown a IllegalArgumentException.");
|
fail("Should have thrown a IllegalArgumentException.");
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
// Do nothing, correct
|
// Do nothing, correct
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ public class TestNoUser extends NoUser {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private String username;
|
private String username;
|
||||||
private int money;
|
private int money;
|
||||||
private List<String> receipts;
|
private List<String> receipts;
|
||||||
|
|||||||
Reference in New Issue
Block a user