mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Register UUID of database version in KDF parameter
This commit is contained in:
@@ -58,6 +58,8 @@ public class AesKdf extends KdfEngine {
|
|||||||
@Override
|
@Override
|
||||||
public KdfParameters getDefaultParameters() {
|
public KdfParameters getDefaultParameters() {
|
||||||
KdfParameters p = new KdfParameters(uuid);
|
KdfParameters p = new KdfParameters(uuid);
|
||||||
|
|
||||||
|
p.setParamUUID();
|
||||||
p.setUInt32(ParamRounds, DEFAULT_ROUNDS);
|
p.setUInt32(ParamRounds, DEFAULT_ROUNDS);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
|
|||||||
@@ -79,10 +79,11 @@ public class Argon2Kdf extends KdfEngine {
|
|||||||
public KdfParameters getDefaultParameters() {
|
public KdfParameters getDefaultParameters() {
|
||||||
KdfParameters p = new KdfParameters(uuid);
|
KdfParameters p = new KdfParameters(uuid);
|
||||||
|
|
||||||
p.setUInt32(ParamVersion, MaxVersion);
|
p.setParamUUID();
|
||||||
p.setUInt64(ParamMemory, DefaultMemory);
|
|
||||||
p.setUInt32(ParamParallelism, DefaultParallelism);
|
p.setUInt32(ParamParallelism, DefaultParallelism);
|
||||||
|
p.setUInt64(ParamMemory, DefaultMemory);
|
||||||
p.setUInt64(ParamIterations, DefaultIterations);
|
p.setUInt64(ParamIterations, DefaultIterations);
|
||||||
|
p.setUInt32(ParamVersion, MaxVersion);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ public class KdfParameters extends VariantDictionary {
|
|||||||
kdfUUID = uuid;
|
kdfUUID = uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setParamUUID() {
|
||||||
|
setByteArray(ParamUUID, Types.UUIDtoBytes(kdfUUID));
|
||||||
|
}
|
||||||
|
|
||||||
public static KdfParameters deserialize(byte[] data) throws IOException {
|
public static KdfParameters deserialize(byte[] data) throws IOException {
|
||||||
ByteArrayInputStream bis = new ByteArrayInputStream(data);
|
ByteArrayInputStream bis = new ByteArrayInputStream(data);
|
||||||
LEDataInputStream lis = new LEDataInputStream(bis);
|
LEDataInputStream lis = new LEDataInputStream(bis);
|
||||||
|
|||||||
@@ -152,11 +152,11 @@ public class Database {
|
|||||||
loadData(ctx, is, password, kfIs, status, debug, roundsFix);
|
loadData(ctx, is, password, kfIs, status, debug, roundsFix);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadData(Context ctx, InputStream is, String password, InputStream kfIs, boolean debug) throws IOException, InvalidDBException {
|
public void loadData(Context ctx, InputStream is, String password, InputStream keyFileInputStream, boolean debug) throws IOException, InvalidDBException {
|
||||||
loadData(ctx, is, password, kfIs, null, debug, 0);
|
loadData(ctx, is, password, keyFileInputStream, null, debug, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadData(Context ctx, InputStream is, String password, InputStream kfIs, ProgressTaskUpdater progressTaskUpdater, boolean debug, long roundsFix) throws IOException, InvalidDBException {
|
private void loadData(Context ctx, InputStream is, String password, InputStream keyFileInputStream, ProgressTaskUpdater progressTaskUpdater, boolean debug, long roundsFix) throws IOException, InvalidDBException {
|
||||||
BufferedInputStream bis = new BufferedInputStream(is);
|
BufferedInputStream bis = new BufferedInputStream(is);
|
||||||
|
|
||||||
if ( ! bis.markSupported() ) {
|
if ( ! bis.markSupported() ) {
|
||||||
@@ -166,11 +166,11 @@ public class Database {
|
|||||||
// We'll end up reading 8 bytes to identify the header. Might as well use two extra.
|
// We'll end up reading 8 bytes to identify the header. Might as well use two extra.
|
||||||
bis.mark(10);
|
bis.mark(10);
|
||||||
|
|
||||||
Importer imp = ImporterFactory.createImporter(bis, debug);
|
Importer databaseImporter = ImporterFactory.createImporter(bis, debug);
|
||||||
|
|
||||||
bis.reset(); // Return to the start
|
bis.reset(); // Return to the start
|
||||||
|
|
||||||
pm = imp.openDatabase(bis, password, kfIs, progressTaskUpdater, roundsFix);
|
pm = databaseImporter.openDatabase(bis, password, keyFileInputStream, progressTaskUpdater, roundsFix);
|
||||||
if ( pm != null ) {
|
if ( pm != null ) {
|
||||||
try {
|
try {
|
||||||
switch (pm.getVersion()) {
|
switch (pm.getVersion()) {
|
||||||
@@ -392,6 +392,7 @@ public class Database {
|
|||||||
switch (getPwDatabase().getVersion()) {
|
switch (getPwDatabase().getVersion()) {
|
||||||
case V4:
|
case V4:
|
||||||
PwDatabaseV4 db = ((PwDatabaseV4) getPwDatabase());
|
PwDatabaseV4 db = ((PwDatabaseV4) getPwDatabase());
|
||||||
|
if (!db.getKdfParameters().kdfUUID.equals(kdfEngine.getDefaultParameters().kdfUUID))
|
||||||
db.setKdfParameters(kdfEngine.getDefaultParameters());
|
db.setKdfParameters(kdfEngine.getDefaultParameters());
|
||||||
setNumberKeyEncryptionRounds(kdfEngine.getDefaultKeyRounds());
|
setNumberKeyEncryptionRounds(kdfEngine.getDefaultKeyRounds());
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -738,64 +738,4 @@ public class PwDatabaseV4 extends PwDatabase<PwGroupV4, PwEntryV4> {
|
|||||||
return filename.substring(0, lastExtDot);
|
return filename.substring(0, lastExtDot);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class GroupHasCustomData extends GroupHandler<PwGroupV4> {
|
|
||||||
|
|
||||||
public boolean hasCustomData = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean operate(PwGroupV4 group) {
|
|
||||||
if (group == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (group.containsCustomData()) {
|
|
||||||
hasCustomData = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class EntryHasCustomData extends EntryHandler<PwEntryV4> {
|
|
||||||
|
|
||||||
public boolean hasCustomData = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean operate(PwEntryV4 entry) {
|
|
||||||
if (entry == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.containsCustomData()) {
|
|
||||||
hasCustomData = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMinKdbxVersion() {
|
|
||||||
if (kdfParameters != null && !AesKdf.CIPHER_UUID.equals(kdfParameters.kdfUUID)) {
|
|
||||||
return PwDbHeaderV4.FILE_VERSION_32;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (publicCustomData.size() > 0) {
|
|
||||||
return PwDbHeaderV4.FILE_VERSION_32;
|
|
||||||
}
|
|
||||||
|
|
||||||
EntryHasCustomData entryHandler = new EntryHasCustomData();
|
|
||||||
GroupHasCustomData groupHandler = new GroupHasCustomData();
|
|
||||||
|
|
||||||
if (rootGroup == null ) {
|
|
||||||
return PwDbHeaderV4.FILE_VERSION_32_3;
|
|
||||||
}
|
|
||||||
rootGroup.preOrderTraverseTree(groupHandler, entryHandler);
|
|
||||||
if (groupHandler.hasCustomData || entryHandler.hasCustomData) {
|
|
||||||
return PwDbHeaderV4.FILE_VERSION_32;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PwDbHeaderV4.FILE_VERSION_32_3;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -92,12 +92,82 @@ public class PwDbHeaderV4 extends PwDbHeader {
|
|||||||
public CrsAlgorithm innerRandomStream;
|
public CrsAlgorithm innerRandomStream;
|
||||||
public long version;
|
public long version;
|
||||||
|
|
||||||
public PwDbHeaderV4(PwDatabaseV4 d) {
|
public PwDbHeaderV4(PwDatabaseV4 databaseV4) {
|
||||||
this.db = d;
|
this.db = databaseV4;
|
||||||
this.version = d.getMinKdbxVersion();
|
this.version = getMinKdbxVersion(databaseV4); // TODO move Only for writing
|
||||||
this.masterSeed = new byte[32];
|
this.masterSeed = new byte[32];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersion(long version) {
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class GroupHasCustomData extends GroupHandler<PwGroupV4> {
|
||||||
|
|
||||||
|
boolean hasCustomData = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean operate(PwGroupV4 group) {
|
||||||
|
if (group == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (group.containsCustomData()) {
|
||||||
|
hasCustomData = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class EntryHasCustomData extends EntryHandler<PwEntryV4> {
|
||||||
|
|
||||||
|
boolean hasCustomData = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean operate(PwEntryV4 entry) {
|
||||||
|
if (entry == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.containsCustomData()) {
|
||||||
|
hasCustomData = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getMinKdbxVersion(PwDatabaseV4 databaseV4) {
|
||||||
|
// Return v4 if AES is not use
|
||||||
|
if (databaseV4.getKdfParameters() != null) {
|
||||||
|
return PwDbHeaderV4.FILE_VERSION_32;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return V4 if custom data are present
|
||||||
|
if (databaseV4.containsPublicCustomData()) {
|
||||||
|
return PwDbHeaderV4.FILE_VERSION_32;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntryHasCustomData entryHandler = new EntryHasCustomData();
|
||||||
|
GroupHasCustomData groupHandler = new GroupHasCustomData();
|
||||||
|
|
||||||
|
if (databaseV4.getRootGroup() == null ) {
|
||||||
|
return PwDbHeaderV4.FILE_VERSION_32_3;
|
||||||
|
}
|
||||||
|
databaseV4.getRootGroup().preOrderTraverseTree(groupHandler, entryHandler);
|
||||||
|
if (groupHandler.hasCustomData || entryHandler.hasCustomData) {
|
||||||
|
return PwDbHeaderV4.FILE_VERSION_32;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PwDbHeaderV4.FILE_VERSION_32_3;
|
||||||
|
}
|
||||||
|
|
||||||
/** Assumes the input stream is at the beginning of the .kdbx file
|
/** Assumes the input stream is at the beginning of the .kdbx file
|
||||||
* @param is
|
* @param is
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
@@ -123,7 +193,7 @@ public class PwDbHeaderV4 extends PwDbHeader {
|
|||||||
throw new InvalidDBVersionException();
|
throw new InvalidDBVersionException();
|
||||||
}
|
}
|
||||||
|
|
||||||
version = lis.readUInt();
|
version = lis.readUInt(); // Erase previous value
|
||||||
if ( ! validVersion(version) ) {
|
if ( ! validVersion(version) ) {
|
||||||
throw new InvalidDBVersionException();
|
throw new InvalidDBVersionException();
|
||||||
}
|
}
|
||||||
@@ -279,8 +349,7 @@ public class PwDbHeaderV4 extends PwDbHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean matchesHeader(int sig1, int sig2) {
|
public static boolean matchesHeader(int sig1, int sig2) {
|
||||||
return (sig1 == PWM_DBSIG_1) && ( (sig2 == DBSIG_2) );
|
return (sig1 == PWM_DBSIG_1) && ( (sig2 == DBSIG_PRE2) || (sig2 == DBSIG_2) ); // TODO verify add DBSIG_PRE2
|
||||||
//return (sig1 == PWM_DBSIG_1) && ( (sig2 == DBSIG_PRE2) || (sig2 == DBSIG_2) ); // TODO verify add DBSIG_PRE2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] computeHeaderHmac(byte[] header, byte[] key) throws IOException{
|
public static byte[] computeHeaderHmac(byte[] header, byte[] key) throws IOException{
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import android.content.Context;
|
|||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
import android.support.annotation.StringRes;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.kunzisoft.keepass.R;
|
import com.kunzisoft.keepass.R;
|
||||||
import com.kunzisoft.keepass.app.App;
|
import com.kunzisoft.keepass.app.App;
|
||||||
@@ -41,6 +43,8 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class LoadDBRunnable extends RunnableOnFinish {
|
public class LoadDBRunnable extends RunnableOnFinish {
|
||||||
|
private static final String TAG = LoadDBRunnable.class.getName();
|
||||||
|
|
||||||
private Uri mUri;
|
private Uri mUri;
|
||||||
private String mPass;
|
private String mPass;
|
||||||
private Uri mKey;
|
private Uri mKey;
|
||||||
@@ -69,42 +73,46 @@ public class LoadDBRunnable extends RunnableOnFinish {
|
|||||||
saveFileData(mUri, mKey);
|
saveFileData(mUri, mKey);
|
||||||
|
|
||||||
} catch (ArcFourException e) {
|
} catch (ArcFourException e) {
|
||||||
finish(false, mCtx.getString(R.string.error_arc4));
|
catchError(e, R.string.error_arc4);
|
||||||
return;
|
return;
|
||||||
} catch (InvalidPasswordException e) {
|
} catch (InvalidPasswordException e) {
|
||||||
finish(false, mCtx.getString(R.string.InvalidPassword));
|
catchError(e, R.string.InvalidPassword);
|
||||||
return;
|
return;
|
||||||
} catch (ContentFileNotFoundException e) {
|
} catch (ContentFileNotFoundException e) {
|
||||||
finish(false, mCtx.getString(R.string.file_not_found_content));
|
catchError(e, R.string.file_not_found_content);
|
||||||
return;
|
return;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
finish(false, mCtx.getString(R.string.file_not_found));
|
catchError(e, R.string.file_not_found);
|
||||||
return;
|
return;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "Database can't be read", e);
|
||||||
finish(false, e.getMessage());
|
finish(false, e.getMessage());
|
||||||
return;
|
return;
|
||||||
} catch (KeyFileEmptyException e) {
|
} catch (KeyFileEmptyException e) {
|
||||||
finish(false, mCtx.getString(R.string.keyfile_is_empty));
|
catchError(e, R.string.keyfile_is_empty);
|
||||||
return;
|
return;
|
||||||
} catch (InvalidAlgorithmException e) {
|
} catch (InvalidAlgorithmException e) {
|
||||||
finish(false, mCtx.getString(R.string.invalid_algorithm));
|
catchError(e, R.string.invalid_algorithm);
|
||||||
return;
|
return;
|
||||||
} catch (InvalidKeyFileException e) {
|
} catch (InvalidKeyFileException e) {
|
||||||
finish(false, mCtx.getString(R.string.keyfile_does_not_exist));
|
catchError(e, R.string.keyfile_does_not_exist);
|
||||||
return;
|
return;
|
||||||
} catch (InvalidDBSignatureException e) {
|
} catch (InvalidDBSignatureException e) {
|
||||||
finish(false, mCtx.getString(R.string.invalid_db_sig));
|
catchError(e, R.string.invalid_db_sig);
|
||||||
return;
|
return;
|
||||||
} catch (InvalidDBVersionException e) {
|
} catch (InvalidDBVersionException e) {
|
||||||
finish(false, mCtx.getString(R.string.unsupported_db_version));
|
catchError(e, R.string.unsupported_db_version);
|
||||||
return;
|
return;
|
||||||
} catch (InvalidDBException e) {
|
} catch (InvalidDBException e) {
|
||||||
finish(false, mCtx.getString(R.string.error_invalid_db));
|
catchError(e, R.string.error_invalid_db);
|
||||||
return;
|
return;
|
||||||
} catch (OutOfMemoryError e) {
|
} catch (OutOfMemoryError e) {
|
||||||
finish(false, mCtx.getString(R.string.error_out_of_memory));
|
String errorMessage = mCtx.getString(R.string.error_out_of_memory);
|
||||||
|
Log.e(TAG, errorMessage, e);
|
||||||
|
finish(false, errorMessage);
|
||||||
return;
|
return;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Database can't be load", e);
|
||||||
finish(false, e.getMessage());
|
finish(false, e.getMessage());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -112,6 +120,12 @@ public class LoadDBRunnable extends RunnableOnFinish {
|
|||||||
finish(true);
|
finish(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void catchError(Exception e, @StringRes int messageId) {
|
||||||
|
String errorMessage = mCtx.getString(messageId);
|
||||||
|
Log.e(TAG, errorMessage, e);
|
||||||
|
finish(false, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
private void saveFileData(Uri uri, Uri key) {
|
private void saveFileData(Uri uri, Uri key) {
|
||||||
if ( ! mRememberKeyfile ) {
|
if ( ! mRememberKeyfile ) {
|
||||||
key = null;
|
key = null;
|
||||||
|
|||||||
@@ -28,13 +28,11 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class ImporterFactory {
|
public class ImporterFactory {
|
||||||
public static Importer createImporter(InputStream is) throws InvalidDBSignatureException, IOException
|
public static Importer createImporter(InputStream is) throws InvalidDBSignatureException, IOException {
|
||||||
{
|
|
||||||
return createImporter(is, false);
|
return createImporter(is, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Importer createImporter(InputStream is, boolean debug) throws InvalidDBSignatureException, IOException
|
public static Importer createImporter(InputStream is, boolean debug) throws InvalidDBSignatureException, IOException {
|
||||||
{
|
|
||||||
int sig1 = LEDataInputStream.readInt(is);
|
int sig1 = LEDataInputStream.readInt(is);
|
||||||
int sig2 = LEDataInputStream.readInt(is);
|
int sig2 = LEDataInputStream.readInt(is);
|
||||||
|
|
||||||
@@ -49,6 +47,5 @@ public class ImporterFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
throw new InvalidDBSignatureException();
|
throw new InvalidDBSignatureException();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ public class ImporterV4 extends Importer {
|
|||||||
db.getBinPool().clear();
|
db.getBinPool().clear();
|
||||||
|
|
||||||
PwDbHeaderV4.HeaderAndHash hh = header.loadFromFile(inStream);
|
PwDbHeaderV4.HeaderAndHash hh = header.loadFromFile(inStream);
|
||||||
version = header.version;
|
version = header.getVersion();
|
||||||
|
|
||||||
hashOfHeader = hh.hash;
|
hashOfHeader = hh.hash;
|
||||||
pbHeader = hh.header;
|
pbHeader = hh.header;
|
||||||
|
|||||||
@@ -88,25 +88,26 @@ public class PwDbHeaderOutputV4 extends PwDbHeaderOutput {
|
|||||||
|
|
||||||
los.writeUInt(PwDbHeader.PWM_DBSIG_1);
|
los.writeUInt(PwDbHeader.PWM_DBSIG_1);
|
||||||
los.writeUInt(PwDbHeaderV4.DBSIG_2);
|
los.writeUInt(PwDbHeaderV4.DBSIG_2);
|
||||||
los.writeUInt(header.version);
|
los.writeUInt(header.getVersion());
|
||||||
|
|
||||||
|
|
||||||
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.CipherID, Types.UUIDtoBytes(db.getDataCipher()));
|
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.CipherID, Types.UUIDtoBytes(db.getDataCipher()));
|
||||||
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.CompressionFlags, LEDataOutputStream.writeIntBuf(db.getCompressionAlgorithm().id));
|
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.CompressionFlags, LEDataOutputStream.writeIntBuf(db.getCompressionAlgorithm().id));
|
||||||
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.MasterSeed, header.masterSeed);
|
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.MasterSeed, header.masterSeed);
|
||||||
|
|
||||||
if (header.version < PwDbHeaderV4.FILE_VERSION_32_4) {
|
if (header.getVersion() < PwDbHeaderV4.FILE_VERSION_32_4) {
|
||||||
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.TransformSeed, header.getTransformSeed());
|
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.TransformSeed, header.getTransformSeed());
|
||||||
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.TransformRounds, LEDataOutputStream.writeLongBuf(db.getNumberKeyEncryptionRounds()));
|
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.TransformRounds, LEDataOutputStream.writeLongBuf(db.getNumberKeyEncryptionRounds()));
|
||||||
} else {
|
} else {
|
||||||
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.KdfParameters, KdfParameters.serialize(db.getKdfParameters()));
|
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.KdfParameters, KdfParameters.serialize(db.getKdfParameters()));
|
||||||
|
// TODO verify serialize in all cases
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.encryptionIV.length > 0) {
|
if (header.encryptionIV.length > 0) {
|
||||||
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.EncryptionIV, header.encryptionIV);
|
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.EncryptionIV, header.encryptionIV);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.version < PwDbHeaderV4.FILE_VERSION_32_4) {
|
if (header.getVersion() < PwDbHeaderV4.FILE_VERSION_32_4) {
|
||||||
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.InnerRandomstreamKey, header.innerRandomStreamKey);
|
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.InnerRandomstreamKey, header.innerRandomStreamKey);
|
||||||
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.StreamStartBytes, header.streamStartBytes);
|
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.StreamStartBytes, header.streamStartBytes);
|
||||||
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.InnerRandomStreamID, LEDataOutputStream.writeIntBuf(header.innerRandomStream.id));
|
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.InnerRandomStreamID, LEDataOutputStream.writeIntBuf(header.innerRandomStream.id));
|
||||||
@@ -139,7 +140,7 @@ public class PwDbHeaderOutputV4 extends PwDbHeaderOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void writeHeaderFieldSize(int size) throws IOException {
|
private void writeHeaderFieldSize(int size) throws IOException {
|
||||||
if (header.version < PwDbHeaderV4.FILE_VERSION_32_4) {
|
if (header.getVersion() < PwDbHeaderV4.FILE_VERSION_32_4) {
|
||||||
los.writeUShort(size);
|
los.writeUShort(size);
|
||||||
} else {
|
} else {
|
||||||
los.writeInt(size);
|
los.writeInt(size);
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class PwDbV4Output extends PwDbOutput<PwDbHeaderV4> {
|
|||||||
header = outputHeader(mOS);
|
header = outputHeader(mOS);
|
||||||
|
|
||||||
OutputStream osPlain;
|
OutputStream osPlain;
|
||||||
if (header.version < PwDbHeaderV4.FILE_VERSION_32_4) {
|
if (header.getVersion() < PwDbHeaderV4.FILE_VERSION_32_4) {
|
||||||
CipherOutputStream cos = attachStreamEncryptor(header, mOS);
|
CipherOutputStream cos = attachStreamEncryptor(header, mOS);
|
||||||
cos.write(header.streamStartBytes);
|
cos.write(header.streamStartBytes);
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ public class PwDbV4Output extends PwDbOutput<PwDbHeaderV4> {
|
|||||||
osXml = osPlain;
|
osXml = osPlain;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.version >= PwDbHeaderV4.FILE_VERSION_32_4) {
|
if (header.getVersion() >= PwDbHeaderV4.FILE_VERSION_32_4) {
|
||||||
PwDbInnerHeaderOutputV4 ihOut = new PwDbInnerHeaderOutputV4(mPM, header, osXml);
|
PwDbInnerHeaderOutputV4 ihOut = new PwDbInnerHeaderOutputV4(mPM, header, osXml);
|
||||||
ihOut.output();
|
ihOut.output();
|
||||||
}
|
}
|
||||||
@@ -258,7 +258,7 @@ public class PwDbV4Output extends PwDbOutput<PwDbHeaderV4> {
|
|||||||
writeObject(PwDatabaseV4XML.ElemLastSelectedGroup, mPM.getLastSelectedGroup());
|
writeObject(PwDatabaseV4XML.ElemLastSelectedGroup, mPM.getLastSelectedGroup());
|
||||||
writeObject(PwDatabaseV4XML.ElemLastTopVisibleGroup, mPM.getLastTopVisibleGroup());
|
writeObject(PwDatabaseV4XML.ElemLastTopVisibleGroup, mPM.getLastTopVisibleGroup());
|
||||||
|
|
||||||
if (header.version < PwDbHeaderV4.FILE_VERSION_32_4) {
|
if (header.getVersion() < PwDbHeaderV4.FILE_VERSION_32_4) {
|
||||||
writeBinPool();
|
writeBinPool();
|
||||||
}
|
}
|
||||||
writeList(PwDatabaseV4XML.ElemCustomData, mPM.getCustomData());
|
writeList(PwDatabaseV4XML.ElemCustomData, mPM.getCustomData());
|
||||||
@@ -296,7 +296,7 @@ public class PwDbV4Output extends PwDbOutput<PwDbHeaderV4> {
|
|||||||
KdfEngine kdf = KdfFactory.get(mPM.getKdfParameters());
|
KdfEngine kdf = KdfFactory.get(mPM.getKdfParameters());
|
||||||
kdf.randomize(mPM.getKdfParameters());
|
kdf.randomize(mPM.getKdfParameters());
|
||||||
|
|
||||||
if (header.version < PwDbHeaderV4.FILE_VERSION_32_4) {
|
if (header.getVersion() < PwDbHeaderV4.FILE_VERSION_32_4) {
|
||||||
header.innerRandomStream = CrsAlgorithm.Salsa20;
|
header.innerRandomStream = CrsAlgorithm.Salsa20;
|
||||||
header.innerRandomStreamKey = new byte[32];
|
header.innerRandomStreamKey = new byte[32];
|
||||||
} else {
|
} else {
|
||||||
@@ -310,7 +310,7 @@ public class PwDbV4Output extends PwDbOutput<PwDbHeaderV4> {
|
|||||||
throw new PwDbOutputException("Invalid random cipher");
|
throw new PwDbOutputException("Invalid random cipher");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( header.version < PwDbHeaderV4.FILE_VERSION_32_4) {
|
if ( header.getVersion() < PwDbHeaderV4.FILE_VERSION_32_4) {
|
||||||
random.nextBytes(header.streamStartBytes);
|
random.nextBytes(header.streamStartBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,7 +463,7 @@ public class PwDbV4Output extends PwDbOutput<PwDbHeaderV4> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void writeObject(String name, Date value) throws IllegalArgumentException, IllegalStateException, IOException {
|
private void writeObject(String name, Date value) throws IllegalArgumentException, IllegalStateException, IOException {
|
||||||
if (header.version < PwDbHeaderV4.FILE_VERSION_32_4) {
|
if (header.getVersion() < PwDbHeaderV4.FILE_VERSION_32_4) {
|
||||||
writeObject(name, PwDatabaseV4XML.dateFormatter.get().format(value));
|
writeObject(name, PwDatabaseV4XML.dateFormatter.get().format(value));
|
||||||
} else {
|
} else {
|
||||||
DateTime dt = new DateTime(value);
|
DateTime dt = new DateTime(value);
|
||||||
|
|||||||
Reference in New Issue
Block a user