Passwd::Keyring backend API

This document describes the API Passwd::Keyring::Something modules should implement to be usable via Passwd::Keyring::Auto and to be easily swappable.

API

Constructor

Passwd::Keyring::Backend->new();

Passwd::Keyring::Backend->new(app=>'some app', group=>'passwords group/folder', %other_args);

The constructor initializes the backend, and constructs the object via which the further processing is to happen.

The constructor should perform sufficient initialization to ensure it can work properly and should fail (croak or die) in case given backend is not available (for example because some daemon is not running or some app not installed).

    The Passwd::Keyring::Auto module may try loading and initiating a few keyring types, and settle on the first which loaded and constructed succesfully.

Named arguments should be accepted and handled, but are all optional (the module should work without them providing some sane defaults). Two of those are standarized:

app - the name of the application using the library to store passwords
group - the name of folder/group/pack/...

app should be used as the calling application name in any interactive prompts, if they may happen (for example in KDEWallet's "Application X is asking to ..." prompt). If possible, it should also be used in some comment or label field of secure storage, but not inside a key (it should be possible to save the password under one app name, and recover using another app name, after all a few apps may share some password).

group should be used to separate the passwords (entries for the password of the same user in the same domain, but with different group, should be separate), and - if only possible - to label the password in secure storage. Preferrable implementation is to use group for folder name if secure storage has some notion of folders.

If app and/or group are not specified, some sensible defaults should be applied (like Passwd::Keyring::Backend for application name and Passwd::Keyring::Passwords for group).

Backend is free to handle any other named arguments, but should function properly if they are omitted.

set_password

$keyring->set_password("John", "verysecret", "gmail.com");

Persistently set and save the password (or update previously saved password).

The method takes 3 arguments:

user_id - in most cases actually the user login id of a kind, but in general any identifier allowing to distinguish between different users
password - the password itself
password_domain - indicator of the kind/target of the password. In (frequent) case of internet passwords, it can be the domain name of web application, but backend should not assume any specific format.

In case underlying API places strict requirements on format of any of those values, the backend should appropriately modify them (escape, prefix, wrap, ...) to be as forgiving, as possible.

The only strict requirement is that get_password appropriately matches those operation, and that different user_id or password_domain (or group given in constructor) leads to separate password.

If possible, password should be labelled using parameters set in the constructor.

    Actual key for the password should be built from group given in new, password_domain and user_id. Changing any of those params should mean separate password.

get_password

$keyring->get_password("John", "gmail.com");

Reads previously saved password. The routine takes two arguments:

user_id
password_domain

and should recover the exact password which was saved with the same user_id and password_domain (and group) by earlier call to set_password.

In case no such password was saved, the method should return undef.

clear_password

$keyring->clear_password("John", "some password identifier");

Remove previously saved password. The routine takes two arguments:

user_id
password_domain

and should wipe password for this key if it is saved (and do nothing otherwise).

is_persistent

if( $keyring->is_persistent() ) {
    # ...
}

This helper method should return 1 (or any true boolean value) if passwords are really saved persistently and will be available after the program is terminated.

Most backends are expected to provide this guarantee (and return 1), emergency backends like Passwd::Kering::Memory return 0.

Work context

Multiple objects per program

If possible, keyring objects should behave sensibly if more than one object is created within single program (do not crash, do not destroy data, share updates).

If this is impossible or difficult, it is recommended to disallow creation many objects (throw an exception on attempt to create second one).

Multithreading

Single keyring object is not required to provide any multithreading guarantees, users are expected to perform appropriate locking.

Separate keyring objects should function sensibly when simultaneously used in different threads. If this is difficult, the backend should not allow to create many objects in single program.

Multiple processes

Keyring objects should work properly when a few processes try to use the same data simultaneously.

    In all practical cases this guarantee should be provided by underlying secure storage API.