UI for setting and entering the password that encrypts the database key.

This commit is contained in:
akwizgran
2013-04-16 14:49:14 +01:00
parent e343c9f4bb
commit 374bff2fb6
16 changed files with 328 additions and 87 deletions

View File

@@ -65,7 +65,7 @@ class CryptoComponentImpl implements CryptoComponent {
private static final String STORAGE_CIPHER_ALGO = "AES/GCM/NoPadding";
private static final int STORAGE_IV_BYTES = 16; // 128 bits
private static final int PBKDF_SALT_BYTES = 16; // 128 bits
private static final int PBKDF_ITERATIONS = 10 * 1000; // FIXME: How many?
private static final int PBKDF_ITERATIONS = 1000;
private static final String KEY_DERIVATION_ALGO = "AES/CTR/NoPadding";
private static final int KEY_DERIVATION_IV_BYTES = 16; // 128 bits

View File

@@ -5,13 +5,13 @@ import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Properties;
import net.sf.briar.api.clock.Clock;
import net.sf.briar.api.db.DatabaseConfig;
import net.sf.briar.api.db.DbException;
import net.sf.briar.util.FileUtils;
import net.sf.briar.util.StringUtils;
import com.google.inject.Inject;
@@ -23,23 +23,23 @@ class H2Database extends JdbcDatabase {
private static final String COUNTER_TYPE = "INT NOT NULL AUTO_INCREMENT";
private static final String SECRET_TYPE = "BINARY(32)";
private final File dir;
private final DatabaseConfig config;
private final String url;
private final char[] password;
private final long maxSize;
@Inject
H2Database(DatabaseConfig config, Clock clock) {
super(HASH_TYPE, BINARY_TYPE, COUNTER_TYPE, SECRET_TYPE, config, clock);
dir = config.getDatabaseDirectory();
url = "jdbc:h2:split:" + new File(dir, "db").getPath()
super(HASH_TYPE, BINARY_TYPE, COUNTER_TYPE, SECRET_TYPE, clock);
this.config = config;
String path = new File(config.getDatabaseDirectory(), "db").getPath();
url = "jdbc:h2:split:" + path
+ ";CIPHER=AES;MULTI_THREADED=1;DB_CLOSE_ON_EXIT=false";
password = config.getPassword();
maxSize = config.getMaxSize();
}
public boolean open() throws DbException, IOException {
return super.open("org.h2.Driver");
boolean reopen = config.databaseExists();
if(!reopen) config.getDatabaseDirectory().mkdirs();
super.open("org.h2.Driver", reopen);
return reopen;
}
public void close() throws DbException {
@@ -52,6 +52,8 @@ class H2Database extends JdbcDatabase {
}
public long getFreeSpace() throws DbException {
File dir = config.getDatabaseDirectory();
long maxSize = config.getMaxSize();
try {
long free = FileUtils.getFreeSpace(dir);
long used = getDiskSpace(dir);
@@ -73,14 +75,28 @@ class H2Database extends JdbcDatabase {
@Override
protected Connection createConnection() throws SQLException {
char[] passwordCopy = password.clone();
char[] password = encodePassword(config.getEncryptionKey());
Properties props = new Properties();
props.setProperty("user", "user");
props.put("password", passwordCopy);
props.put("password", password);
try {
return DriverManager.getConnection(url, props);
} finally {
Arrays.fill(passwordCopy, (char) 0);
for(int i = 0; i < password.length; i++) password[i] = 0;
}
}
private char[] encodePassword(byte[] key) {
// The database password is the hex-encoded key
char[] hex = StringUtils.toHexChars(key);
// Separate the database password from the user password with a space
char[] user = "password".toCharArray();
char[] combined = new char[hex.length + 1 + user.length];
System.arraycopy(hex, 0, combined, 0, hex.length);
combined[hex.length] = ' ';
System.arraycopy(user, 0, combined, hex.length + 1, user.length);
// Erase the hex-encoded key
for(int i = 0; i < hex.length; i++) hex[i] = 0;
return combined;
}
}

View File

@@ -34,7 +34,6 @@ import net.sf.briar.api.TransportConfig;
import net.sf.briar.api.TransportId;
import net.sf.briar.api.TransportProperties;
import net.sf.briar.api.clock.Clock;
import net.sf.briar.api.db.DatabaseConfig;
import net.sf.briar.api.db.DbClosedException;
import net.sf.briar.api.db.DbException;
import net.sf.briar.api.db.GroupMessageHeader;
@@ -360,7 +359,6 @@ abstract class JdbcDatabase implements Database<Connection> {
// Different database libraries use different names for certain types
private final String hashType, binaryType, counterType, secretType;
private final DatabaseConfig config;
private final Clock clock;
private final LinkedList<Connection> connections =
@@ -372,18 +370,16 @@ abstract class JdbcDatabase implements Database<Connection> {
protected abstract Connection createConnection() throws SQLException;
JdbcDatabase(String hashType, String binaryType, String counterType,
String secretType, DatabaseConfig config, Clock clock) {
String secretType, Clock clock) {
this.hashType = hashType;
this.binaryType = binaryType;
this.counterType = counterType;
this.secretType = secretType;
this.config = config;
this.clock = clock;
}
protected boolean open(String driverClass) throws DbException, IOException {
boolean reopen = config.databaseExists();
if(!reopen) config.getDatabaseDirectory().mkdirs();
protected void open(String driverClass, boolean reopen) throws DbException,
IOException {
// Load the JDBC driver
try {
Class.forName(driverClass);
@@ -399,7 +395,6 @@ abstract class JdbcDatabase implements Database<Connection> {
abortTransaction(txn);
throw e;
}
return reopen;
}
private void createTables(Connection txn) throws DbException {

View File

@@ -29,16 +29,19 @@ public class StringUtils {
else return s;
}
/** Converts the given byte array to a hex character array. */
public static char[] toHexChars(byte[] bytes) {
char[] hex = new char[bytes.length * 2];
for(int i = 0, j = 0; i < bytes.length; i++) {
hex[j++] = HEX[(bytes[i] >> 4) & 0xF];
hex[j++] = HEX[bytes[i] & 0xF];
}
return hex;
}
/** Converts the given byte array to a hex string. */
public static String toHexString(byte[] bytes) {
StringBuilder s = new StringBuilder(bytes.length * 2);
for(byte b : bytes) {
int high = (b >> 4) & 0xF;
s.append(HEX[high]);
int low = b & 0xF;
s.append(HEX[low]);
}
return s.toString();
return new String(toHexChars(bytes));
}
/** Converts the given hex string to a byte array. */