mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-05-15 22:42:51 +00:00
Replace PBKDF2 with scrypt, provided by Spongy Castle
This commit is contained in:
parent
12dcf54cd3
commit
911b2fab78
6 changed files with 47 additions and 27 deletions
|
@ -26,11 +26,9 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:recyclerview-v7:25.0.0'
|
||||
compile 'com.android.support:recyclerview-v7:25.0.0'
|
||||
compile 'com.android.support:appcompat-v7:25.0.0'
|
||||
compile 'com.android.support:design:25.0.0'
|
||||
compile 'agency.tango.android:material-intro-screen:0.0.3'
|
||||
|
@ -40,5 +38,6 @@ dependencies {
|
|||
compile 'com.android.support:support-v4:25.0.0'
|
||||
compile 'com.yarolegovich:lovely-dialog:1.0.4'
|
||||
compile 'com.mattprecious.swirl:swirl:1.0.0'
|
||||
compile 'com.madgag.spongycastle:core:1.56.0.0'
|
||||
testCompile 'junit:junit:4.12'
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ public class CustomAuthenticatedSlide extends SlideFragment {
|
|||
InvalidKeyException, NoSuchPaddingException {
|
||||
char[] password = getPassword(true);
|
||||
byte[] salt = CryptoUtils.generateSalt();
|
||||
SecretKey key = slot.deriveKey(password, salt, CryptoUtils.CRYPTO_ITERATION_COUNT);
|
||||
SecretKey key = slot.deriveKey(password, salt, CryptoUtils.CRYPTO_SCRYPT_N, CryptoUtils.CRYPTO_SCRYPT_r, CryptoUtils.CRYPTO_SCRYPT_p);
|
||||
CryptoUtils.zero(password);
|
||||
|
||||
return Slot.createCipher(key, mode);
|
||||
|
|
|
@ -74,7 +74,7 @@ public class IntroActivity extends MaterialIntroActivity {
|
|||
private void setException(Exception e) {
|
||||
Intent result = new Intent();
|
||||
result.putExtra("exception", e);
|
||||
setResult(RESULT_OK, result);
|
||||
setResult(RESULT_EXCEPTION, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,12 +2,14 @@ package me.impy.aegis.crypto;
|
|||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
|
@ -16,26 +18,30 @@ import javax.crypto.IllegalBlockSizeException;
|
|||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.spongycastle.crypto.generators.SCrypt;
|
||||
|
||||
public class CryptoUtils {
|
||||
public static final String CRYPTO_CIPHER_RAW = "AES/ECB/NoPadding";
|
||||
public static final String CRYPTO_CIPHER_AEAD = "AES/GCM/NoPadding";
|
||||
public static final byte CRYPTO_TAG_SIZE = 16;
|
||||
public static final byte CRYPTO_KEY_SIZE = 32;
|
||||
public static final byte CRYPTO_NONCE_SIZE = 12;
|
||||
public static final byte CRYPTO_SALT_SIZE = 32;
|
||||
// TODO: decide on a 'secure-enough' iteration count
|
||||
public static final short CRYPTO_ITERATION_COUNT = 10000;
|
||||
public static final String CRYPTO_CIPHER_RAW = "AES/ECB/NoPadding";
|
||||
public static final String CRYPTO_CIPHER_AEAD = "AES/GCM/NoPadding";
|
||||
// TODO: use a separate library for an HMAC-SHA256 implementation
|
||||
public static final String CRYPTO_DERIVE_ALGO = "PBKDF2WithHmacSHA1";
|
||||
|
||||
public static SecretKey deriveKey(char[] password, byte[] salt, int iterations) throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
SecretKeyFactory factory = SecretKeyFactory.getInstance(CRYPTO_DERIVE_ALGO);
|
||||
KeySpec spec = new PBEKeySpec(password, salt, iterations, CRYPTO_KEY_SIZE * 8);
|
||||
return factory.generateSecret(spec);
|
||||
public static final int CRYPTO_SCRYPT_N = 2 << 14;
|
||||
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) throws NoSuchAlgorithmException, InvalidKeySpecException {
|
||||
byte[] bytes = toBytes(password);
|
||||
byte[] keyBytes = SCrypt.generate(bytes, salt, n, r, p, CRYPTO_KEY_SIZE);
|
||||
zero(bytes);
|
||||
SecretKey key = new SecretKeySpec(keyBytes, 0, keyBytes.length, "AES");
|
||||
zero(keyBytes);
|
||||
return key;
|
||||
}
|
||||
|
||||
public static Cipher createCipher(SecretKey key, int opmode) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException {
|
||||
|
@ -108,4 +114,12 @@ public class CryptoUtils {
|
|||
public static void zero(byte[] data) {
|
||||
Arrays.fill(data, (byte) 0);
|
||||
}
|
||||
|
||||
private static byte[] toBytes(char[] chars) {
|
||||
CharBuffer charBuf = CharBuffer.wrap(chars);
|
||||
ByteBuffer byteBuf = Charset.forName("UTF-8").encode(charBuf);
|
||||
byte[] bytes = Arrays.copyOfRange(byteBuf.array(), 0, byteBuf.limit());
|
||||
zero(byteBuf.array());
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,9 @@ import me.impy.aegis.crypto.CryptoUtils;
|
|||
import me.impy.aegis.util.LittleByteBuffer;
|
||||
|
||||
public class PasswordSlot extends RawSlot {
|
||||
private long _iterationCount;
|
||||
private int _n;
|
||||
private int _r;
|
||||
private int _p;
|
||||
private byte[] _salt;
|
||||
|
||||
public PasswordSlot() {
|
||||
|
@ -21,7 +23,9 @@ public class PasswordSlot extends RawSlot {
|
|||
byte[] bytes = super.serialize();
|
||||
LittleByteBuffer buffer = LittleByteBuffer.wrap(bytes);
|
||||
buffer.position(super.getSize());
|
||||
buffer.putLong(_iterationCount);
|
||||
buffer.putInt(_n);
|
||||
buffer.putInt(_r);
|
||||
buffer.putInt(_p);
|
||||
buffer.put(_salt);
|
||||
return buffer.array();
|
||||
}
|
||||
|
@ -31,26 +35,29 @@ public class PasswordSlot extends RawSlot {
|
|||
super.deserialize(data);
|
||||
LittleByteBuffer buffer = LittleByteBuffer.wrap(data);
|
||||
buffer.position(super.getSize());
|
||||
_iterationCount = buffer.getLong();
|
||||
_n = buffer.getInt();
|
||||
_r = buffer.getInt();
|
||||
_p = buffer.getInt();
|
||||
_salt = new byte[CryptoUtils.CRYPTO_SALT_SIZE];
|
||||
buffer.get(_salt);
|
||||
}
|
||||
|
||||
public SecretKey deriveKey(char[] password, byte[] salt, int iterations) throws InvalidKeySpecException, NoSuchAlgorithmException {
|
||||
SecretKey key = CryptoUtils.deriveKey(password, salt, iterations);
|
||||
_iterationCount = iterations;
|
||||
public SecretKey deriveKey(char[] password, byte[] salt, int n, int r, int p) throws InvalidKeySpecException, NoSuchAlgorithmException {
|
||||
SecretKey key = CryptoUtils.deriveKey(password, salt, n, r, p);
|
||||
_n = n;
|
||||
_r = r;
|
||||
_p = p;
|
||||
_salt = salt;
|
||||
return key;
|
||||
}
|
||||
|
||||
public SecretKey deriveKey(char[] password) throws InvalidKeySpecException, NoSuchAlgorithmException {
|
||||
SecretKey key = CryptoUtils.deriveKey(password, _salt, (int)_iterationCount);
|
||||
return key;
|
||||
return CryptoUtils.deriveKey(password, _salt, _n, _r, _p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return 1 + CryptoUtils.CRYPTO_KEY_SIZE + /* iterations */ 8 + CryptoUtils.CRYPTO_SALT_SIZE;
|
||||
return 1 + CryptoUtils.CRYPTO_KEY_SIZE + /* _n, _r, _p */ 4 + 4 + 4 + CryptoUtils.CRYPTO_SALT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue