Author image Peter C. Jones
and 1 contributors

NAME

WWW::KeePassHttp - Interface with KeePass PasswordSafe through the KeePassHttp plugin

SYNOPSIS

    use WWW::KeePassHttp;

    my $kph = WWW::KeePassHttp->new(Key => $key);
    $kph->associate() unless $kph->test_associate();
    my @entries = @${ $kph->get_logins($search_string) };
    print $entry[0]->url;
    print $entry[0]->login;
    print $entry[0]->password;

DESCRIPTION

Interface with KeePass PasswordSafe through the KeePassHttp plugin. Allows reading entries based on URL or TITLE, and creating a new entry as well.

REQUIREMENTS

You need to have KeePass (or compatible) on your system, with the KeePassHttp plugin installed.

INTERFACE

CONSTRUCTOR AND CONFIGURATION

new
    my $kph = WWW::KeePassHttp->new( Key => $key, %options);
    my $kph = WWW::KeePassHttp->new( Key => $key, keep_alive => 0, %options);

Creates a new KeePassHttp connection, and sets up the AES encryption.

The Key => $key is required; pass in a string of 32 octets that represent a 256-bit key value. If you have your key as 64 hex nibbles, then use $key = pack 'H*', $hexnibbles; to convert it to the value. If you have your key as a Base64 string, use $key = decode_base64($base64string); to convert it to the value.

There is also a keep_alive option, which will tell the HTTP user agent to keep the connection alive when the option is set to 1 (or when it's not specified); setting the option to a 0 will disable that feature of the user agent.

The %options share the same name and purposes with the configuration methods that follow, and can be individually specified in the constructor as key/value pairs, or passing in an %options hash.

appid
    %options = ( ...,  appid => 'name of your app', ... );
        or
    $kph->appid('name of your app');

Changes the appid, which is the name that is used to map your application with the stored key in the KeePassHttp settings in KeePass.

If not defined in the initial options or via this method, the module will use a default appid of WWW::KeePassHttp.

request_base
    %options = ( ...,  request_base => 'localhost', ... );
        or
    $kph->request_base('127.0.0.1');

Changes the protocol and host: the KeePassHttp plugin defaults to http://localhost, but can be configured differently, so you will need to make your object match your plugin settings.

request_port
    %options = ( ...,  request_port => 19455, ... );
        or
    $kph->request_port(19455);

Changes the port: the KeePassHttp plugin defaults to port 19455, but can be configured differently, so you will need to make your object match your plugin settings.

USER INTERFACE

These methods implement the KeePassHttp plugin's commmunication protocol, with one method for each RequestType.

test_associate
    $kph->associate unless $kph->test_associate();

Sends the test-assocate request to the KeePassHttp server, which is used to see whether or not your application has been associated with the KeePassHttp plugin or not. Returns a true value if your application is already associated, or a false value otherwise.

associate
    $kph->associate unless $kph->test_associate();

Sends the assocate request to the KeePassHttp server, which is used to give your application's key to the KeePassHttp plugin.

When this request is received, KeePass will pop up a dialog asking for a name -- this name should match the appid value that you defined for the $kph instance. All requests sent to the plugin will include this appid so that KeePassHttp can look up your application's key, so it must match exactly. As per the KeePassHttp plugin docs|https://github.com/pfn/keepasshttp/, the server saves your application's key in the KeePassHttp Settings entry, in the Advanced > String Fields with a name of AES Key: XXXX, where XXXX is the name you type in the dialog box (which needs to match your appid).

Please note: this associate communication is insecure, since KeePassHttp plugin is not using HTTPS. Every other communication between your application and the plugin uses the key (which both your application and the plugin know) to encrypt the critical data (usernames, passwords, titles, etc), and is thus secure; but the associate interaction, because it happens before the plugin has your key, by its nature cannot be encrypted by that key, so it sends the encoded key unencrypted. If this worries you, I suggest that you manually insert the key: do an assocate once with a dummy key, then manually overwrite the encoded key that it stores with the encoded version of your real key. (This limitation is due to the design of the KeePassHttp plugin and its protocol for the associate command, not due to the wrapper around that protocol that this module implements.)

get_logins
    my @entries = @${ $kph->get_logins($search_string) };
    print $entry[0]->url;
    print $entry[0]->login;
    print $entry[0]->password;

Sends the get-logins request, which returns the Name, Login, and Password for each of the matching entries.

$entries is an array reference containing WWW::KeePassHttp::Entry objects, from which you can extract the url/name, login, and password for each matched entry.

The rules for the matching of the search string are defined in the KeePassHttp plugin documentation. But, in brief, it will do a fuzzy match on the URL, and an exact match on the entry title. (The plugin was designed to be used for browser plugins to request passwords for URLs from KeePass, hence its focus on URLs.)

get_logins_count
    my $count = $kph->get_logins_count($search_string);

Sends the get-logins request, which returns a count of the number of matches for the search string.

The rules for the matching of the search string are defined in the KeePassHttp plugin documentation. But, in brief, it will do a fuzzy match on the URL, and an exact match on the entry title. (The plugin was designed to be used for browser plugins to request passwords for URLs from KeePass, hence its focus on URLs.)

This method is useful when the fuzzy-URL-match might match a large number of entries in the database; if after seeing this count, you would rather refine your search instead of requesting that many entries, this method enables knowing that right away, rather than after you accidentally matched virtually every entry in your database by searching for www.

set_login
    $kph->set_login( Login => $username, Url => $url_and_title, Password => $password );
    # or
    $kph->set_login( $entry );

Sends the set-login request, which adds a new entry to your KeePass database, in the "KeePassHttp Passwords" group (folder).

As far as I know, the plugin doesn't allow choosing a different group for your entry. The plugin uses the URL that you supply as both the entry title and the URL field in that entry. (Once again, the plugin was designed around browser password needs, and thus is URL-focused). I don't know if that's a deficiency in the plugin's implementation, or just its documentation, or my interpretation of that documentation.

The arguments to the method define the Login (username), Url (for entry title and URL field), and Password (secret value) for the new entry. All three of those parameters are required by the protocol, and thus by this method. Alernately, you can just pass it a WWW::KeePassHttp::Entry object as the single argument.

If you would prefer not to give one or more of those parameters a value, just pass an empty string. You could afterword then manually access your KeePass database and edit the entry yourself.

request
    my $results = $kph->request( $type, %options );

This is the generic method for making a request of the KeePassHttp plugin. In general, other methods should handle most requests. However, maybe a new method has been exposed in the plugin but not yet implemented here, so you can use this method for handling that.

The $type indicates the RequestType, which include test-associate, associate, get-logins, get-logins-count, and set-login.

This method automatically fills out the RequestType, TriggerUnlock, Id, Nonce, and Verifier parameters. If your RequestType requires any other parameters, add them to the %options.

It then encodes the request into the JSON payload, and sends that request to the KeePassHttp plugin, and gets the response, decoding the JSON content back into a Perl hashref. It verifies that the response's Nonce and Verifier parameters are appropriate for the communication channel, to make sure communications from the plugin are properly encrypted.

Returns the hashref decoded from the JSON

HELPER METHODS

In general, most users won't need these. But maybe you will.

generate_nonce
    my ($iv, $base64) = $kph->generate_nonce();

This is used by the "request" method to generate the IV nonce for communication. I don't think you need to use it yourself, but it's available to you, if you find a need for it.

The $iv is the string of octets (the actual 128 IV nonce value).

The $base64 is the base64 representation of the $iv.

SEE ALSO

ACKNOWLEDGEMENTS

Thank you to KeePass for providing a free password manager with plugin capability.

Thank you to the KeePassHttp Plugin for providing a free and open source plugin which allows for easy communication between an external application and the KeePass application, enabling the existence of this module (and the ability for it to give applications access to the passwords stored in KeePass).

This module and author are not affiliated with either KeePass or KeePassHttp except as a user of those fine products.

TODO

The entries should be full-fledged objects, with method-based access to the underlying Login, Url, and Password values.

AUTHOR

Peter C. Jones <petercj AT cpan DOT org>

Please report any bugs or feature requests thru the repository's interface at https://github.com/pryrt/WWW-KeePassHttp/issues.

Coverage Status github perl-ci

COPYRIGHT

Copyright (C) 2021 Peter C. Jones

LICENSE

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License. See http://dev.perl.org/licenses/ for more information.