How to manipulate KeePass databases (kdbx) in Java

How to manipulate KeePass databases (kdbx) in Java

KeePass is a free open source password manager, which helps you to manage your passwords in a secure way. You can put all your passwords in one database, which is locked with one master key or a key file. This application features:

  • KeePass supports the Advanced Encryption Standard (AES, Rijndael) and the Twofish algorithm to encrypt its password databases. Both of these ciphers are regarded as being very secure. AES e.g. became effective as a U.S. Federal government standard and is approved by the National Security Agency (NSA) for top secret information.
  • The complete database is encrypted, not only the password fields. So, your user names, notes, etc. are encrypted, too.
  • SHA-256 is used to hash the master key components. SHA-256 is a 256-bit cryptographically secure one-way hash function. No attacks are known yet against SHA-256. The output is transformed using a key derivation function.
  • Protection against dictionary and guessing attacks: by transforming the master key component hash using a key derivation function (AES-KDF, Argon2, ...), dictionary and guessing attacks can be made harder.
  • Process memory protection: your passwords are encrypted while KeePass is running, so even when the operating system dumps the KeePass process to disk, your passwords aren't revealed.
  • [2.x] Protected in-memory streams: when loading the inner XML format, passwords are encrypted using a session key.
  • Security-enhanced password edit controls: KeePass is the first password manager that features security-enhanced password edit controls. None of the available password edit control spies work against these controls. The passwords entered in those controls aren't even visible in the process memory of KeePass.
  • The master key dialog can be shown on a secure desktop, on which almost no keylogger works. Auto-Type can be protected against keyloggers, too.

As the application uses a public logic, there are libraries to manipulate this kind of file with different programming languages, and Java is not the exception. In this article, we will explain you how to manipulate KeePass databases with Java, either to create your own similar application or just to extract the information from kdbx files.

1. Install Open KeePass library

In order to manipulate KeePass databases, you will need to install the openkeepass library. openkeepass is a java library for reading and writing KeePass databases. It is an intuitive java library that supports KeePass 2.x database files. The library offers support so far for:

  • Reading and writing support for KeePass 2.x
  • Password or Keyfile credentials: openkeepass can open password protected databases as well as keyfile protected databases.
  • Android Support: Will run on Android devices.
  • Easy to learn API: openkeepass has a simple API with convenient methods that makes it easy to read data from a KeePass database.
  • Very lean: openkeepass tries to keep the necessary dependencies to an absolute minimum.
  • Backward compatible until Java 6

You can either download the jar file of the package from the maven repository and include it manually in your project or if your project is maven based, you may edit the pom.xml file and add the dependency:

<!-- https://mvnrepository.com/artifact/de.slackspace/openkeepass -->
<dependency>
    <groupId>de.slackspace</groupId>
        <artifactId>openkeepass</artifactId>
    <version>0.8.1</version>
</dependency>

For more information about this project, please visit the official repository at Github here.

2. Extracting information

As everything in Our Code World, you will learn by doing, so we will explain you how to handle the most basic needs when you try to work with these files:

Printing all credentials

If you just obtained a KeePass database from someone and you only need to obtain the information without worrying about categorization, you can easily print all the stored credentials in the file with the following logic:

package com.ourcodeworld.mavensandbox;

// Import required class
import de.slackspace.openkeepass.KeePassDatabase;
import de.slackspace.openkeepass.domain.Entry;
import de.slackspace.openkeepass.domain.KeePassFile;
import java.util.List;

public class Index {
    
    public static void main(String[] args){
        
        // 1. Open a KeePass database file through a plain text password
        KeePassFile database = KeePassDatabase
            .getInstance("C:\\Users\\sdkca\\Documents\\Database.kdbx")
            .openDatabase("12345");
		
        // 2. Retrieve all entries
        List<Entry> entries = database.getEntries();
            
        // 3. Print every entry
        for (Entry entry : entries) {
            System.out.println("    * Credential: " + entry.getTitle());
                System.out.println("        Username: " + entry.getUsername());
                System.out.println("        Password: " + entry.getPassword());
        }
    }
}

This logic will generate the following output in the terminal:

* Credential: Sample Entry
    Username: User Name
    Password: Password
* Credential: Sample Entry #2
    Username: Michael321
    Password: 12345
* Credential: Windows User
    Username: cheese@outlook.com
    Password: 123456
* Credential: Wi-Fi
    Username: bathouse
    Password: 654321
* Credential: Contact Email
    Username: dev@ourcodeworld.com
    Password: 123456
* Credential: Info Email
    Username: info@ourcodeworld.com
    Password: 123456789
* Credential: Bank Of America
    Username: ourcodeworld
    Password: 123456

Printing information in a structured way (By Groups)

As a regular user of the Keepass application, i love to categorize the credentials that i store on my file using groups and subgroups. For example, separating the credentials from my personal life with job related accounts:

KeePass Categories or Groups

You can extract the information in this way as well iterating as first by groups and then obtaining the entries inside the group:

package com.ourcodeworld.mavensandbox;

// Import required class
import de.slackspace.openkeepass.KeePassDatabase;
import de.slackspace.openkeepass.domain.Entry;
import de.slackspace.openkeepass.domain.Group;
import de.slackspace.openkeepass.domain.KeePassFile;
import java.util.List;

public class Index {
    
    public static void main(String[] args){
        
        // 1. Open a KeePass database file through a plain text password
        KeePassFile database = KeePassDatabase
            .getInstance("C:\\Users\\sdkca\\Documents\\Database.kdbx")
            .openDatabase("12345");
		 
        // 2. Obtain the top groups in the database
        List<Group> keePassGroups = database.getTopGroups();
            
        // 3. Iterate over theme
        for (Group group : keePassGroups) {

            // 4. Print the name of the Group
            System.out.println(" - " + group.getName());

            // 5. List credentials inside this group
            List<Entry> groupEntries = group.getEntries();
            
            // 6. Print every credential inside the group
            for (Entry entry : groupEntries) {
                System.out.println("    * Credential: " + entry.getTitle());
                System.out.println("        Username: " + entry.getUsername());
                System.out.println("        Password: " + entry.getPassword());
            }
        }
    }
}

This code will generate the following output in the terminal:

 - Windows
    * Credential: Windows User
        Username: cheese@outlook.com
        Password: 123456
 - Network
    * Credential: Wi-Fi
        Username: bathouse
        Password: 654321
 - eMail
    * Credential: Contact Email
        Username: dev@ourcodeworld.com
        Password: 123456
    * Credential: Info Email
        Username: info@ourcodeworld.com
        Password: 123456789
 - Homebanking
    * Credential: Bank Of America
        Username: ourcodeworld
        Password: 123456
 - Recycle Bin

Obtaining a single credential by its title

As there's no indexation through ID's or something numerical, the only way to obtain a single credential from the database is through it's title, for example:

package com.ourcodeworld.mavensandbox;

// Import required class
import de.slackspace.openkeepass.KeePassDatabase;
import de.slackspace.openkeepass.domain.Entry;
import de.slackspace.openkeepass.domain.KeePassFile;
import java.util.List;

public class Index {
    
    public static void main(String[] args){
        
        // 1. Open a KeePass database file through a plain text password
        KeePassFile database = KeePassDatabase
            .getInstance("C:\\Users\\sdkca\\Documents\\Database.kdbx")
            .openDatabase("12345");
	
        // 2. Find single credential by title
        Entry sampleEntry = database.getEntryByTitle("Sample Entry");
	    System.out.println("Title: " + sampleEntry.getTitle() + " Password: " + sampleEntry.getPassword());
    }
}

This will print in the terminal:

Title: Sample Entry Password: Password

However, what if you have more than a single credential that has the same name or contains the same string? Then you will need to obtain the entries that contain the specific text and iterate over the result to know which credential match with the search:

package com.ourcodeworld.mavensandbox;

// Import required class
import de.slackspace.openkeepass.KeePassDatabase;
import de.slackspace.openkeepass.domain.Entry;
import de.slackspace.openkeepass.domain.KeePassFile;
import java.util.List;

public class Index {
    
    public static void main(String[] args){
        
        // 1. Open a KeePass database file through a plain text password
        KeePassFile database = KeePassDatabase
            .getInstance("C:\\Users\\sdkca\\Documents\\Database.kdbx")
            .openDatabase("12345");
	
        // 2. Search for all entries that contain 'Sample' in title
        List<Entry> entriesByTitle = database.getEntriesByTitle("Sample", false);
        for (Entry entry : entriesByTitle) {
                System.out.println("Title: " + entry.getTitle() + " Password: " + entry.getPassword());
        }
    }
}

This will print instead:

Title: Sample Entry Password: Password
Title: Sample Entry #2 Password: 12345

Happy coding !

This could interest you

Become a more social person