kppy

A Python-module to provide an API to KeePass 1.x files commonly used by KeePassX.

Download as .zip Download as .tar.gz View on GitHub

Introduction

Basic usage

First of all you need to import KPDB, the database class. Also you should import KPError, the exception class.

from kppy import KPDB, KPError

Nearly everything can throw KPError-exceptions, that is you should execute such code always in a try block, for example let's open a database:

try: db = KPDB("foo.kdb", "bar") except KPError as err: print(err)

".kdb" is the standard file extension of KeePass/KeePassX databases. You should not break with this convention.

All methods (except __init__, of course) return "True" if everything went right or "False" if not.

Due to security reasons I recommend that you change the working directory with "os.chdir" to /var/empty to prevent the simple creating of core dumps.

Remark: In the following "db" means a KPDB-instance, "group" a StdGroup-instance and "entry" a StdEntry-instance (compare API-reference).

The database itself

You can open existing databases or create new ones. Both will be done with the KPDB-constructor. Also it's possible to open databases read-only. First, let's see how to open an existing database:

db = KPDB("foo.kdb", "bar")

In this case "foo.kdb" is the path to the file and "bar" is the password. Both will be stored in the database object in "db.filepath" respectively "db.masterkey". If you want to open the database read-only (default is you want not), do it like that:

db = KPDB("foo.kdb", "bar", read_only = True)

You can always change the read-only behaviour by setting "db.read_only" to "True" respecively "False".

It's possible to use keyfile authentication, too.

db = KPDB("foo.kdb", None, "bar")
db = KPDB("foo.kdb", "foo", "bar")

In the first example only a keyfile with the path "bar" is used, in the second a password and a keyfile are used

If you implement a program with kppy you should check if there is a file called "foo.kdb.lock" in the same directory with "foo.kdb". This file exists in two cases: Another program access the database or the database wasn't closed correctly. In any case you should ask the user, if the database should accessed read-only to prevent damage. That's the default behaviour of KeePass/KeePassX.

Creating a new database is very simple:

db = KPDB(new=True)

This initializes a new database object with a single group, called "Internet" (there must be at least one group). To save this new database simple call "save"

db.save("foo.kdb", "bar")

Here we used that we can parse a filepath and a password to "save". If you parse a filepath to "save" and "db.filepath" is not set, kppy will automatically set "db.filepath" to this filepath. Otherwise the database will be saved to that filepath but "db.filepath" remains unaffected. If you parse a passphrase it will always set "db.password" to this one. Also "save" creates the file "foo.kdb.lock" if it doesn't exists.

It's possible to lock a database, that is it is not possible to access the data but "foo.kdb.lock" remains, so that other programs know that another work with it.

db.lock()

Unlocking is just that simple, either set the masterkey to the original one and call "load" or just call "unlock" with the password:

db.unlock("bar")

To close a database correct call "close" before you delete the object with "del db":

db.close() del db

"close" expect that "db.filepath" is set, otherwise an error is raised, that is you can only close an opened database.

Groups

Creating a group is very simple, just call "create_group" with a title:

db.create_group("group_title")

Now the database has two groups (remember that the group "Internet" was created during database creation). Every database has a list which holds references to all groups called "groups". For example, to access the new group you can type the following:

db.groups[1]

Removing a group is easy. You just need the group object:

db.groups[0].remove_group()

Every group can contain sub-groups. Due to this a group has one parent and can have multiple children. You can access these via "group.parent" and "group.children", where the former is a StdGroup-instance and the latter is a list of StdGroup-instances. If you want to set the parent during creation of the database you can doing this by parsing the parent to "db.create_group"

db.create_group("foobar", db.groups[0])

The result would be the following order:
Internet
- foobar

You should never manipulate "db.groups" or "group.parent" respectively "group.children" with Python-methods. Instead use "group.move_group()". You must parse a valid index to "move_group" and can parse a new parent where "parent" is the parent-object. Simple example: You have following group order:
group_1
group_2
group_3

To put "group_3" to the beginning of the list do the following:

db.groups[2].move_group_in_parent(0)

The result is
group_3
group_1
group_2

Another example:

db.groups[2].move_group(db.groups[0])

The result is:
group_1
- group_3
group_2

One remark: If a group has children these will be moved with it parent automatically if you move the parent.

As I mentioned above every group has a title. If you want to edit it just use "group.set_title("foobar")". Also every group has an attribute called "image". This is a number used by KeePass/KeePassX to set a little image next to the group title. If you want to use this, just set it with "group.set_image()" where the argument must be an unsigned integer. The standard value is 1. If you want to set it during creation you can do this by "db.create_group("foobar", image = 5)". It's also possible to set the attributes directly (e.g. group.title = "foobar") but it's not recommend because "group.set_title" does some checks on the new attribute and changes also the modification-date.

Entries

All groups can contain entries. These holds information like a username and a corresponding password. You can access the entries via a list that every group contains, "group.entries". There are several methods to create an entry: You can call "db.create_entry" or "group.create_entry". In both cases you can parse the following arguments: a title, an image number (like image number for groups), an url, an username, a password, a comment and an expiration date (in this order). If you parse an expiration date you must parse a year, a month, a day, a hour, a minutes and a second (in this order). The standard value is "2999-12-28 23:59:59", that means the entry expires never. Attention: If you use "db.create_entry" the first argument must be a valid group object. You can change all values, information can be found in the API documentation, it's similar to the group stuff.

If you want to move an entry to another group use "entry.move_group". You must just parse the group object to this method.

This was only a small introduction. More information can be found in the API-reference created with pydoc: API-reference

Copyright (C) 2012 Karsten-Kai König <kkoenig@posteo.de>