Swiesend Secret Service Save

A Java library for storing secrets under linux in the gnome-keyring over D-Bus. Like libsecret, but for Java.

Project README

Secret Service

Maven Central

A Java library for storing secrets in a keyring over the D-Bus.

The library is conforming to the freedesktop.org Secret Service API 0.2 and thus compatible with Gnome linux systems.

The Secret Service itself is implemented by the gnome-keyring and provided by the gnome-keyring-daemon.

This library can be seen as the functional equivalent to the libsecret C client library.

For KDE systems there is the kdewallet client library, kindly provided by @purejava.

Security Issues

CVE-2018-19358 (Vulnerability)

There is a current investigation on the behaviour of the Secret Service API, as other applications can easily read any secret, if the keyring is unlocked (if a user is logged in, then the login/default collection is unlocked). Available D-Bus protection mechanisms (involving the busconfig and policy XML elements) are not used by default. The Secret Service API was never designed with a secure retrieval mechanism.

Usage

The library provides a simplified high-level API, which sends only transport encrypted secrets over the D-Bus.

Dependency

Add the secret-service as dependency to your project. You may want to exclude the slf4j-api if you use an incompatible version. The current version requires at least JDK 17.

<dependency>
    <groupId>de.swiesend</groupId>
    <artifactId>secret-service</artifactId>
    <version>2.0.1-alpha</version>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>

High-Level API

public class Example {

    @Test
    @DisplayName("Create a password in the user's default collection (/org/freedesktop/secrets/aliases/default).")
    public void createPasswordInDefaultCollection() throws IOException, AccessControlException, IllegalArgumentException {
        try (SimpleCollection collection = new SimpleCollection()) {
            String item = collection.createItem("My Item", "secret");

            char[] actual = collection.getSecret(item);
            assertEquals("secret", new String(actual));
            assertEquals("My Item", collection.getLabel(item));

            collection.deleteItem(item);
        } // clears automatically all session secrets in memory, but does not close the D-Bus connection.
    }

    @Test
    @DisplayName("Create a password in a non-default collection (/org/freedesktop/secrets/collection/xxx).")
    public void createPasswordInNonDefaultCollection() throws IOException, AccessControlException, IllegalArgumentException {
        try (SimpleCollection collection = new SimpleCollection("My Collection", "super secret")) {
            String item = collection.createItem("My Item", "secret");

            char[] actual = collection.getSecret(item);
            assertEquals("secret", new String(actual));
            assertEquals("My Item", collection.getLabel(item));

            collection.deleteItem(item);
            collection.delete();
        } // clears automatically all session secrets in memory, but does not close the D-Bus connection.
    }

    @Test
    @DisplayName("Create a password with additional attributes.")
    public void createPasswordWithAttributes() throws IOException, AccessControlException, IllegalArgumentException {
        try (SimpleCollection collection = new SimpleCollection("My Collection", "super secret")) {
            // define unique attributes
            Map<String, String> attributes = new HashMap();
            attributes.put("uuid", "42");

            // create and forget
            collection.createItem("My Item", "secret", attributes);

            // find by attributes
            List<String> items = collection.getItems(attributes);
            assertEquals(1, items.size());
            String item = items.get(0);

            char[] actual = collection.getSecret(item);
            assertEquals("secret", new String(actual));
            assertEquals("My Item", collection.getLabel(item));
            assertEquals("42", collection.getAttributes(item).get("uuid"));

            collection.deleteItem(item);
            collection.delete();
        } // clears automatically all session secrets in memory, but does not close the D-Bus connection.
    }

    // The D-Bus connection gets closed at the end of the static lifetime of `SimpleCollection` by a shutdown hook.

}

Closing the D-Bus connection:

The D-Bus connection is closed eventually at end of the static lifetime of SimpleCollection with a shutdown hook and not by auto-close. One can also close the D-Bus connection manually by calling SimpleCollection.disconnect(), but once disconnected it is not possible to reconnect.

SimpleCollection-Interface:

For Further methods and attributes checkout the SimpleCollection-Interface.

Transport Encryption:

For the details of the transport encryption see: Transfer of Secrets, Transport Encryption Example

Low-Level API

The low-level API gives access to all defined D-Bus Methods, Properties and Signals of the Secret Service interface:

For the usage of the low-level API see the tests:

D-Bus Interfaces

The underlying introspected XML D-Bus interfaces are available as resources.

Contributing

You are welcome to point out issues, file PRs and comment on the project.

Please keep in mind that this is a non-profit effort in my spare time and thus it may take some time until issues are addressed.

Thank You

Special thanks goes out to

Open Source Agenda is not affiliated with "Swiesend Secret Service" Project. README Source: swiesend/secret-service

Open Source Agenda Badge

Open Source Agenda Rating