mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-05-04 12:24:49 +00:00
Restructure the code in the Slot classes a bit
This commit is contained in:
parent
0434513820
commit
36907660e8
9 changed files with 120 additions and 69 deletions
|
@ -30,15 +30,14 @@ public class CryptoUtils {
|
|||
public static final String CRYPTO_AEAD = "AES/GCM/NoPadding";
|
||||
public static final byte CRYPTO_AEAD_KEY_SIZE = 32;
|
||||
public static final byte CRYPTO_AEAD_TAG_SIZE = 16;
|
||||
public static final byte CRYPTO_AEAD_NONCE_SIZE = 12;
|
||||
|
||||
public static final int CRYPTO_SCRYPT_N = 1 << 15;
|
||||
public static final int CRYPTO_SCRYPT_r = 8;
|
||||
public static final int CRYPTO_SCRYPT_p = 1;
|
||||
|
||||
public static SecretKey deriveKey(char[] password, byte[] salt, int n, int r, int p) {
|
||||
public static SecretKey deriveKey(char[] password, SCryptParameters params) {
|
||||
byte[] bytes = toBytes(password);
|
||||
byte[] keyBytes = SCrypt.generate(bytes, salt, n, r, p, CRYPTO_AEAD_KEY_SIZE);
|
||||
byte[] keyBytes = SCrypt.generate(bytes, params.getSalt(), params.getN(), params.getR(), params.getP(), CRYPTO_AEAD_KEY_SIZE);
|
||||
return new SecretKeySpec(keyBytes, 0, keyBytes.length, "AES");
|
||||
}
|
||||
|
||||
|
|
33
app/src/main/java/me/impy/aegis/crypto/SCryptParameters.java
Normal file
33
app/src/main/java/me/impy/aegis/crypto/SCryptParameters.java
Normal file
|
@ -0,0 +1,33 @@
|
|||
package me.impy.aegis.crypto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class SCryptParameters implements Serializable {
|
||||
private int _n;
|
||||
private int _r;
|
||||
private int _p;
|
||||
private byte[] _salt;
|
||||
|
||||
public SCryptParameters(int n, int r, int p, byte[] salt) {
|
||||
_n = n;
|
||||
_r = r;
|
||||
_p = p;
|
||||
_salt = salt;
|
||||
}
|
||||
|
||||
public byte[] getSalt() {
|
||||
return _salt;
|
||||
}
|
||||
|
||||
public int getN() {
|
||||
return _n;
|
||||
}
|
||||
|
||||
public int getR() {
|
||||
return _r;
|
||||
}
|
||||
|
||||
public int getP() {
|
||||
return _p;
|
||||
}
|
||||
}
|
|
@ -58,7 +58,6 @@ public class DatabaseManager {
|
|||
|
||||
public void lock() {
|
||||
assertState(false, true);
|
||||
// TODO: properly clear everything
|
||||
_creds = null;
|
||||
_db = null;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
package me.impy.aegis.db.slots;
|
||||
|
||||
public class FingerprintSlot extends RawSlot {
|
||||
import java.util.UUID;
|
||||
|
||||
import me.impy.aegis.crypto.CryptParameters;
|
||||
|
||||
public class FingerprintSlot extends RawSlot {
|
||||
public FingerprintSlot() {
|
||||
super();
|
||||
}
|
||||
|
||||
FingerprintSlot(UUID uuid, byte[] key, CryptParameters keyParams) {
|
||||
super(uuid, key, keyParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getType() {
|
||||
return TYPE_FINGERPRINT;
|
||||
|
|
|
@ -3,60 +3,50 @@ package me.impy.aegis.db.slots;
|
|||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import me.impy.aegis.crypto.CryptParameters;
|
||||
import me.impy.aegis.crypto.CryptoUtils;
|
||||
import me.impy.aegis.crypto.SCryptParameters;
|
||||
import me.impy.aegis.encoding.Hex;
|
||||
import me.impy.aegis.encoding.HexException;
|
||||
|
||||
public class PasswordSlot extends RawSlot {
|
||||
private int _n;
|
||||
private int _r;
|
||||
private int _p;
|
||||
private byte[] _salt;
|
||||
private SCryptParameters _params;
|
||||
|
||||
public PasswordSlot() {
|
||||
super();
|
||||
}
|
||||
|
||||
protected PasswordSlot(UUID uuid, byte[] key, CryptParameters keyParams, SCryptParameters scryptParams) {
|
||||
super(uuid, key, keyParams);
|
||||
_params = scryptParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject toJson() {
|
||||
try {
|
||||
JSONObject obj = super.toJson();
|
||||
obj.put("n", _n);
|
||||
obj.put("r", _r);
|
||||
obj.put("p", _p);
|
||||
obj.put("salt", Hex.encode(_salt));
|
||||
obj.put("n", _params.getN());
|
||||
obj.put("r", _params.getR());
|
||||
obj.put("p", _params.getP());
|
||||
obj.put("salt", Hex.encode(_params.getSalt()));
|
||||
return obj;
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(JSONObject obj) throws SlotException {
|
||||
try {
|
||||
super.deserialize(obj);
|
||||
_n = obj.getInt("n");
|
||||
_r = obj.getInt("r");
|
||||
_p = obj.getInt("p");
|
||||
_salt = Hex.decode(obj.getString("salt"));
|
||||
} catch (JSONException | HexException e) {
|
||||
throw new SlotException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public SecretKey deriveKey(char[] password, byte[] salt, int n, int r, int p) {
|
||||
SecretKey key = CryptoUtils.deriveKey(password, salt, n, r, p);
|
||||
_n = n;
|
||||
_r = r;
|
||||
_p = p;
|
||||
_salt = salt;
|
||||
public SecretKey deriveKey(char[] password, SCryptParameters params) {
|
||||
SecretKey key = CryptoUtils.deriveKey(password, params);
|
||||
_params = params;
|
||||
return key;
|
||||
}
|
||||
|
||||
public SecretKey deriveKey(char[] password) {
|
||||
return CryptoUtils.deriveKey(password, _salt, _n, _r, _p);
|
||||
return CryptoUtils.deriveKey(password, _params);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
package me.impy.aegis.db.slots;
|
||||
|
||||
public class RawSlot extends Slot {
|
||||
import java.util.UUID;
|
||||
|
||||
import me.impy.aegis.crypto.CryptParameters;
|
||||
|
||||
public class RawSlot extends Slot {
|
||||
public RawSlot() {
|
||||
super();
|
||||
}
|
||||
|
||||
protected RawSlot(UUID uuid, byte[] key, CryptParameters keyParams) {
|
||||
super(uuid, key, keyParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getType() {
|
||||
return TYPE_RAW;
|
||||
|
|
|
@ -21,6 +21,7 @@ import me.impy.aegis.crypto.CryptParameters;
|
|||
import me.impy.aegis.crypto.CryptResult;
|
||||
import me.impy.aegis.crypto.CryptoUtils;
|
||||
import me.impy.aegis.crypto.MasterKey;
|
||||
import me.impy.aegis.crypto.SCryptParameters;
|
||||
import me.impy.aegis.encoding.Hex;
|
||||
import me.impy.aegis.encoding.HexException;
|
||||
|
||||
|
@ -29,14 +30,20 @@ public abstract class Slot implements Serializable {
|
|||
public final static byte TYPE_DERIVED = 0x01;
|
||||
public final static byte TYPE_FINGERPRINT = 0x02;
|
||||
|
||||
protected UUID _uuid;
|
||||
protected byte[] _encryptedMasterKey;
|
||||
protected CryptParameters _encryptedMasterKeyParams;
|
||||
private UUID _uuid;
|
||||
private byte[] _encryptedMasterKey;
|
||||
private CryptParameters _encryptedMasterKeyParams;
|
||||
|
||||
protected Slot() {
|
||||
_uuid = UUID.randomUUID();
|
||||
}
|
||||
|
||||
protected Slot(UUID uuid, byte[] key, CryptParameters keyParams) {
|
||||
_uuid = uuid;
|
||||
_encryptedMasterKey = key;
|
||||
_encryptedMasterKeyParams = keyParams;
|
||||
}
|
||||
|
||||
// getKey decrypts the encrypted master key in this slot using the given cipher and returns it.
|
||||
public MasterKey getKey(Cipher cipher) throws SlotException, SlotIntegrityException {
|
||||
try {
|
||||
|
@ -87,36 +94,54 @@ public abstract class Slot implements Serializable {
|
|||
public JSONObject toJson() {
|
||||
try {
|
||||
JSONObject obj = new JSONObject();
|
||||
JSONObject paramObj = _encryptedMasterKeyParams.toJson();
|
||||
obj.put("type", getType());
|
||||
obj.put("uuid", _uuid.toString());
|
||||
obj.put("key", Hex.encode(_encryptedMasterKey));
|
||||
obj.put("key_params", paramObj);
|
||||
obj.put("key_params", _encryptedMasterKeyParams.toJson());
|
||||
return obj;
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void deserialize(JSONObject obj) throws SlotException {
|
||||
public static Slot fromJson(JSONObject obj) throws SlotException {
|
||||
Slot slot;
|
||||
|
||||
try {
|
||||
if (obj.getInt("type") != getType()) {
|
||||
throw new SlotException("slot type mismatch");
|
||||
}
|
||||
|
||||
// if there is no uuid, generate a new one
|
||||
UUID uuid;
|
||||
if (!obj.has("uuid")) {
|
||||
_uuid = UUID.randomUUID();
|
||||
uuid = UUID.randomUUID();
|
||||
} else {
|
||||
_uuid = UUID.fromString(obj.getString("uuid"));
|
||||
uuid = UUID.fromString(obj.getString("uuid"));
|
||||
}
|
||||
|
||||
JSONObject paramObj = obj.getJSONObject("key_params");
|
||||
_encryptedMasterKey = Hex.decode(obj.getString("key"));
|
||||
_encryptedMasterKeyParams = CryptParameters.fromJson(paramObj);
|
||||
byte[] key = Hex.decode(obj.getString("key"));
|
||||
CryptParameters keyParams = CryptParameters.fromJson(obj.getJSONObject("key_params"));
|
||||
|
||||
switch (obj.getInt("type")) {
|
||||
case Slot.TYPE_RAW:
|
||||
slot = new RawSlot(uuid, key, keyParams);
|
||||
break;
|
||||
case Slot.TYPE_DERIVED:
|
||||
SCryptParameters scryptParams = new SCryptParameters(
|
||||
obj.getInt("n"),
|
||||
obj.getInt("r"),
|
||||
obj.getInt("p"),
|
||||
Hex.decode(obj.getString("salt"))
|
||||
);
|
||||
slot = new PasswordSlot(uuid, key, keyParams, scryptParams);
|
||||
break;
|
||||
case Slot.TYPE_FINGERPRINT:
|
||||
slot = new FingerprintSlot(uuid, key, keyParams);
|
||||
break;
|
||||
default:
|
||||
throw new SlotException("unrecognized slot type");
|
||||
}
|
||||
} catch (JSONException | HexException e) {
|
||||
throw new SlotException(e);
|
||||
}
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
public abstract byte getType();
|
||||
|
|
|
@ -26,24 +26,8 @@ public class SlotList implements Iterable<Slot>, Serializable {
|
|||
|
||||
try {
|
||||
for (int i = 0; i < array.length(); i++) {
|
||||
Slot slot;
|
||||
JSONObject slotObj = array.getJSONObject(i);
|
||||
|
||||
switch (slotObj.getInt("type")) {
|
||||
case Slot.TYPE_RAW:
|
||||
slot = new RawSlot();
|
||||
break;
|
||||
case Slot.TYPE_DERIVED:
|
||||
slot = new PasswordSlot();
|
||||
break;
|
||||
case Slot.TYPE_FINGERPRINT:
|
||||
slot = new FingerprintSlot();
|
||||
break;
|
||||
default:
|
||||
throw new SlotException("unrecognized slot type");
|
||||
}
|
||||
|
||||
slot.deserialize(slotObj);
|
||||
JSONObject obj = array.getJSONObject(i);
|
||||
Slot slot = Slot.fromJson(obj);
|
||||
slots.add(slot);
|
||||
}
|
||||
} catch (SlotException | JSONException e) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.content.Context;
|
|||
import javax.crypto.SecretKey;
|
||||
|
||||
import me.impy.aegis.crypto.CryptoUtils;
|
||||
import me.impy.aegis.crypto.SCryptParameters;
|
||||
import me.impy.aegis.db.slots.PasswordSlot;
|
||||
|
||||
public class DerivationTask extends ProgressDialogTask<DerivationTask.Params, SecretKey> {
|
||||
|
@ -21,7 +22,13 @@ public class DerivationTask extends ProgressDialogTask<DerivationTask.Params, Se
|
|||
|
||||
Params params = args[0];
|
||||
byte[] salt = CryptoUtils.generateSalt();
|
||||
return params.getSlot().deriveKey(params.getPassword(), salt, CryptoUtils.CRYPTO_SCRYPT_N, CryptoUtils.CRYPTO_SCRYPT_r, CryptoUtils.CRYPTO_SCRYPT_p);
|
||||
SCryptParameters scryptParams = new SCryptParameters(
|
||||
CryptoUtils.CRYPTO_SCRYPT_N,
|
||||
CryptoUtils.CRYPTO_SCRYPT_r,
|
||||
CryptoUtils.CRYPTO_SCRYPT_p,
|
||||
salt
|
||||
);
|
||||
return params.getSlot().deriveKey(params.getPassword(), scryptParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue