What happens
KeePassJava2 reads KDBX 3.1, 4 and 4.1, but only ever writes a file version of 0x00030001 (KDBX 3.1) or 0x00040000 (KDBX 4.0). There is no 4.1 constant:
// KdbxSerializer (2.x kdbx module; 3.1.0 kdbx-io, org.linguafranca.pwdb.format)
ledos.writeInt(kdbxHeader.getVersion() == 3 ? FILE_VERSION_32 : FILE_VERSION_4);
- On read only the major version is kept (
kdbxHeader.setVersion(fullVersion >> 16)), so a 4.1 file is treated as "4".
- A 4.1 database written back is labelled 4.0, but the Jackson model still holds and writes its 4.1 content (group
Tags and PreviousParentGroup; entry PreviousParentGroup and QualityCheck), so the file says 4.0 and contains 4.1 elements.
- A new database saved with
save/write(credentials, stream) is written as 4.0 (JacksonDatabase/KdbxDatabase default to new KdbxHeader(4)), while new KdbxHeader() and new KdbxStreamFormat() default to 3.1.
Affects 2.2.6 and 3.1.0 (same serializer code).
Fix
To be fixed in 3.1.1. v3-develop (3.2.0-SNAPSHOT) already has a fix to port: the KDBX minor version is kept on read and written back; a new KDBX 4 database is written as 4.1 only if it uses 4.1 features, otherwise 4.0, as KeePass does (KdbxHeader.isMinorVersionAutomatic(), KdbxHeaderOpts.V4_1_AES_ARGON_CHA_CHA); and content a version can't hold is left out of the file, kept in the database and reported through System.Logger. Whether 2.x also gets the fix is to be decided.
Documentation to update once fixed
The readmes are inaccurate about this now and are left as they are until the fix:
v3-master readme, Features: "Read and write KeePass 2.x format (KDBX file formats V3.1, V4 and V4.1)" overstates 3.1.0, which doesn't write 4.1. After the fix: "Read and write the KeePass 2.x format: KDBX 3.1, 4 and 4.1".
master readme, Features: "Read and write KeePass 2.x format (KDBX file formats V3 and V4)" doesn't say 4.1 is read; it should say what 2.x reads and writes (depending on whether 2.x gets the fix).
- The GitHub repository description ("Read/Write 2.x (File versions 3 and 4), Read 1.x").
At the same time, use one way of naming versions throughout, since three numberings get mixed up: KeePass 1.x / 2.x for the application, KDB and KDBX 3.1 / 4 / 4.1 for file formats (no "V4", "format version 4"), and KeePassJava2 2.x / 3.x for this library (not "V2 code"/"V3"). Places to change:
v3-master readme: line 48 ("Upgrade to V3 requires minor changes to V2 code"), line 57 ("File format version 4 support"), lines 175–176 ("the KeePass V2 KDB format": KDB is the KeePass 1.x format, file version 3, e.g. 0x00030004; also mention the experimental, unpublished basic), line 299 ("KeePass KDB format" → "the KeePass 1.x KDB format (read only)"), and a short "Versions and formats" note near the top stating the convention.
master readme: lines 21 and 23 (as above), line 149 ("KDB, KDBX 3.1 and KDBX 4 (KeePass 2)" reads as if KDB were KeePass 2).
What happens
KeePassJava2 reads KDBX 3.1, 4 and 4.1, but only ever writes a file version of
0x00030001(KDBX 3.1) or0x00040000(KDBX 4.0). There is no 4.1 constant:kdbxHeader.setVersion(fullVersion >> 16)), so a 4.1 file is treated as "4".TagsandPreviousParentGroup; entryPreviousParentGroupandQualityCheck), so the file says 4.0 and contains 4.1 elements.save/write(credentials, stream)is written as 4.0 (JacksonDatabase/KdbxDatabasedefault tonew KdbxHeader(4)), whilenew KdbxHeader()andnew KdbxStreamFormat()default to 3.1.Affects 2.2.6 and 3.1.0 (same serializer code).
Fix
To be fixed in 3.1.1.
v3-develop(3.2.0-SNAPSHOT) already has a fix to port: the KDBX minor version is kept on read and written back; a new KDBX 4 database is written as 4.1 only if it uses 4.1 features, otherwise 4.0, as KeePass does (KdbxHeader.isMinorVersionAutomatic(),KdbxHeaderOpts.V4_1_AES_ARGON_CHA_CHA); and content a version can't hold is left out of the file, kept in the database and reported throughSystem.Logger. Whether 2.x also gets the fix is to be decided.Documentation to update once fixed
The readmes are inaccurate about this now and are left as they are until the fix:
v3-masterreadme, Features: "Read and write KeePass 2.x format (KDBX file formats V3.1, V4 and V4.1)" overstates 3.1.0, which doesn't write 4.1. After the fix: "Read and write the KeePass 2.x format: KDBX 3.1, 4 and 4.1".masterreadme, Features: "Read and write KeePass 2.x format (KDBX file formats V3 and V4)" doesn't say 4.1 is read; it should say what 2.x reads and writes (depending on whether 2.x gets the fix).At the same time, use one way of naming versions throughout, since three numberings get mixed up: KeePass 1.x / 2.x for the application, KDB and KDBX 3.1 / 4 / 4.1 for file formats (no "V4", "format version 4"), and KeePassJava2 2.x / 3.x for this library (not "V2 code"/"V3"). Places to change:
v3-masterreadme: line 48 ("Upgrade to V3 requires minor changes to V2 code"), line 57 ("File format version 4 support"), lines 175–176 ("the KeePass V2 KDB format": KDB is the KeePass 1.x format, file version 3, e.g.0x00030004; also mention the experimental, unpublishedbasic), line 299 ("KeePass KDB format" → "the KeePass 1.x KDB format (read only)"), and a short "Versions and formats" note near the top stating the convention.masterreadme: lines 21 and 23 (as above), line 149 ("KDB, KDBX 3.1 and KDBX 4 (KeePass 2)" reads as if KDB were KeePass 2).