KeePass is a well known password safe for your passwords. It has a lot of features, proved security and is really a good way of storing your passwords and login information. Personally, I’m using KeePass for a long time now.
Java API for KeePass
However, sometimes there is a need that you have to access the KeePass database programmatically. And there comes the problem. There are really good frameworks available for C# but if you’ve ever looked for an opensource java library that is capable of reading KeePass 2.x databases you were probably surprised that there are only libraries out there that can read KeePass 1.x databases.
I guess this has to do with the fact that the file format of KeePass 2.x has dramatically changed since the old 1.x version and is now based on XML. However, since there is no alternative available I’ve managed to write my own java API for KeePass 2.x files.
Openkeepass for reading KeePass files
With the library you will get a quick way to access the database files. I’ve tried to make the API as simple as possible to use.
If you want to read all password entries from a KeePass database you can achieve that with the following code:
KeePassFile database = KeePassDatabase.getInstance("Database.kdbx").openDatabase("MasterPassword");
// Retrieve all entries
List<Entry> entries = database.getEntries();
If you want to search for a specific entry you can do that as well:
Entry sampleEntry = database.getEntryByTitle("Sample Entry");
Looking for entries that contain a specific string? No problem:
List<Entry> entries = keePassFile.getEntriesByTitle("entry", false);
You could also work with groups:
List<Group> groups = keePassFile.getTopGroups();
There are more examples available on GitHub.
Installation
If you want to use openkeepass, you can grab it directly from GitHub or even simpler just add it as a maven dependency.
<groupId>de.slackspace</groupId>
<artifactId>openkeepass</artifactId>
<version>0.4.0</version>
</dependency>
Pitfalls
There is one pitfall that you could fall into while using the library. While KeePass is using strong cryptography, you have to make sure that you’ve installed the Java Cryptography Extension (JCE) on your system. You can download it directly from Oracle.
If you have not installed it, you will run into an InvalidKeyException:
OpenSource
As always the whole source code is opensource and available on GitHub.
12 Comments
org.bouncycastle.util.encoders.DecoderException: unable to decode base64 data: -4
at org.bouncycastle.util.encoders.Base64.decode(Base64.java:112)
at de.slackspace.openkeepass.crypto.Salsa20.decrypt(Salsa20.java:41)
at de.slackspace.openkeepass.parser.KeePassDatabaseXmlParser.decryptAndSetValues(KeePassDatabaseXmlParser.java:42)
at de.slackspace.openkeepass.parser.KeePassDatabaseXmlParser.parse(KeePassDatabaseXmlParser.java:24)
at de.slackspace.openkeepass.KeePassDatabase.decryptAndParseDatabase(KeePassDatabase.java:291)
at de.slackspace.openkeepass.KeePassDatabase.openDatabase(KeePassDatabase.java:208)
Every time I try an entry with a blank password
Thank you for your report. This bug is fixed in version 0.4.2
Nice work, are you thinking of adding the option to write to the keepass database?
I’ve recently added support for writing.
Hello,
thank you for this article
i need to write entrees to keepass database,
do you know any API that can help me please ?
regards
HASSAI
You can just use openkeepass. See this follow up article http://slackspace.de/articles/openkeepass-feature-release-with-write-support/
OK,
my aim is to add entry without creating a new keepassfile. (add new entry to existing keepassfile)
is this possible ?
Hello
I’m trying to open a password protected DB following the example provided on GitHub but I keep getting below exception on the openDatabase instruction.
Exception in thread “main” java.lang.RuntimeException: Could not move right because the last node at this level has already been reached
at de.slackspace.openkeepass.domain.zipper.GroupZipper.right(GroupZipper.java:140)
at de.slackspace.openkeepass.domain.zipper.GroupZipper$GroupIterator.getNextRightNode(GroupZipper.java:287)
at de.slackspace.openkeepass.domain.zipper.GroupZipper$GroupIterator.getNextRightNode(GroupZipper.java:289)
at de.slackspace.openkeepass.domain.zipper.GroupZipper$GroupIterator.getNextRightNode(GroupZipper.java:289)
at de.slackspace.openkeepass.domain.zipper.GroupZipper$GroupIterator.next(GroupZipper.java:321)
at de.slackspace.openkeepass.domain.zipper.GroupZipper$GroupIterator.next(GroupZipper.java:1)
at de.slackspace.openkeepass.domain.enricher.IconEnricher.enrichNodesWithIconData(IconEnricher.java:45)
at de.slackspace.openkeepass.xml.KeePassDatabaseXmlParser.fromXml(KeePassDatabaseXmlParser.java:25)
at de.slackspace.openkeepass.KeePassDatabase.decryptAndParseDatabase(KeePassDatabase.java:317)
at de.slackspace.openkeepass.KeePassDatabase.openDatabase(KeePassDatabase.java:172)
Any hint?
Thanks,
Mika
Hey Mika,
Could you create an issue on GitHub for this? I guess there must be something special in your KeePass database. It would be ideal if you could provide the KeePass database also (of course with obfuscated passwords/usernames etc.).
Hello
Is it possible to access attributes like creation time / last modification time?
Thanks,
Mika
How can we add entry to existing group without overwriting existing entries PLZ ?
I used this API to read expiry information as well as add new groups to existing Keepass database file.
KeePassFile database = KeePassDatabase.getInstance(kpsDatabaseFile).openDatabase(kpsDatabasePasswd);
// Retrieve all entries
List entries = database.getEntries();
for (Entry entry : entries) {
System.out.println(“Title: ” + entry.getTitle() + ” Password: ” + entry.getPassword() + ” Expiry: ”
+ SimpleDateFormat.getDateInstance().format(entry.getTimes().getExpiryTime().getTime()));
}
// Retrieve all top groups
List groups = database.getTopGroups();
for (Group group : groups) {
System.out.println(group.getName());
}
Group groupWrite = new GroupBuilder(“Test Group”).build();
groups.add(groupWrite);
KeePassFile keePassFile = new KeePassFileBuilder(database).build();
KeePassDatabase.write(keePassFile, kpsDatabasePasswd, kpsDatabaseFile);