diff --git a/main/buildkit/pom.xml b/main/buildkit/pom.xml
index 32fa59d67..4c9dac1ce 100644
--- a/main/buildkit/pom.xml
+++ b/main/buildkit/pom.xml
@@ -62,6 +62,7 @@
${project.build.directory}/libs
linux,mac,win
+ dbus-java,secret-service,hkdf,java-utils
@@ -76,6 +77,17 @@
linux
+
+ copy-linux-secret-service
+ prepare-package
+
+ copy-dependencies
+
+
+ ${project.build.directory}/linux-libs
+ dbus-java,secret-service,hkdf,java-utils
+
+
copy-mac-libs
prepare-package
diff --git a/main/keychain/pom.xml b/main/keychain/pom.xml
index 29471ed1d..01e276cc9 100644
--- a/main/keychain/pom.xml
+++ b/main/keychain/pom.xml
@@ -39,7 +39,14 @@
com.google.dagger
dagger
-
+
+
+
+ de.swiesend
+ secret-service
+ 1.0.0-RC.3
+
+
org.slf4j
diff --git a/main/keychain/src/main/java/org/cryptomator/keychain/GnomeKeyringAccess.java b/main/keychain/src/main/java/org/cryptomator/keychain/GnomeKeyringAccess.java
new file mode 100644
index 000000000..998fdfab7
--- /dev/null
+++ b/main/keychain/src/main/java/org/cryptomator/keychain/GnomeKeyringAccess.java
@@ -0,0 +1,9 @@
+package org.cryptomator.keychain;
+
+public interface GnomeKeyringAccess {
+ public void storePassword(String key, CharSequence passphrase);
+
+ public char[] loadPassword(String key);
+
+ public void deletePassword(String key);
+}
diff --git a/main/keychain/src/main/java/org/cryptomator/keychain/GnomeKeyringAccessImpl.java b/main/keychain/src/main/java/org/cryptomator/keychain/GnomeKeyringAccessImpl.java
new file mode 100644
index 000000000..34dcdb5fa
--- /dev/null
+++ b/main/keychain/src/main/java/org/cryptomator/keychain/GnomeKeyringAccessImpl.java
@@ -0,0 +1,52 @@
+package org.cryptomator.keychain;
+
+import org.freedesktop.secret.simple.SimpleCollection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class GnomeKeyringAccessImpl implements GnomeKeyringAccess {
+ private static final Logger LOG = LoggerFactory.getLogger(GnomeKeyringAccessImpl.class);
+ private SimpleCollection keyring;
+
+ public GnomeKeyringAccessImpl() {
+ try {
+ keyring = new SimpleCollection();
+ } catch (IOException e) {
+ LOG.error("D-Bus reports a problem.", e);
+ }
+ }
+
+ public void storePassword(String key, CharSequence passphrase) {
+ List list = keyring.getItems(createAttributes(key));
+ if (list == null) {
+ keyring.createItem("Cryptomator", passphrase, createAttributes(key));
+ }
+ }
+
+ public char[] loadPassword(String key) {
+ List list = keyring.getItems(createAttributes(key));
+ if (list != null) {
+ return keyring.getSecret(list.get(0));
+ } else {
+ return null;
+ }
+ }
+
+ public void deletePassword(String key) {
+ List list = keyring.getItems(createAttributes(key));
+ if (list != null) {
+ keyring.deleteItem(list.get(0));
+ }
+ }
+
+ private Map createAttributes(String key) {
+ Map attributes = new HashMap();
+ attributes.put("Vault", key);
+ return attributes;
+ }
+}
diff --git a/main/keychain/src/main/java/org/cryptomator/keychain/KeychainModule.java b/main/keychain/src/main/java/org/cryptomator/keychain/KeychainModule.java
index 5db7bc372..f05a90f1f 100644
--- a/main/keychain/src/main/java/org/cryptomator/keychain/KeychainModule.java
+++ b/main/keychain/src/main/java/org/cryptomator/keychain/KeychainModule.java
@@ -31,8 +31,8 @@ public class KeychainModule {
@Provides
@ElementsIntoSet
- Set provideKeychainAccessStrategies(MacSystemKeychainAccess macKeychain, WindowsProtectedKeychainAccess winKeychain) {
- return Sets.newHashSet(macKeychain, winKeychain);
+ Set provideKeychainAccessStrategies(MacSystemKeychainAccess macKeychain, WindowsProtectedKeychainAccess winKeychain, LinuxSecretServiceAccess linKeychain) {
+ return Sets.newHashSet(macKeychain, winKeychain, linKeychain);
}
@Provides
diff --git a/main/keychain/src/main/java/org/cryptomator/keychain/LinuxKeychainTester.java b/main/keychain/src/main/java/org/cryptomator/keychain/LinuxKeychainTester.java
new file mode 100644
index 000000000..1466e895c
--- /dev/null
+++ b/main/keychain/src/main/java/org/cryptomator/keychain/LinuxKeychainTester.java
@@ -0,0 +1,25 @@
+package org.cryptomator.keychain;
+
+import java.util.Optional;
+
+public class LinuxKeychainTester {
+ public static boolean secretServiceIsAvailable() {
+ try {
+ Class.forName("org.freedesktop.secret.simple.SimpleCollection");
+ return true;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
+ public static Optional getSecretService() {
+ if (!secretServiceIsAvailable()) return Optional.empty();
+ try {
+ Class clazz = Class.forName("org.cryptomator.keychain.GnomeKeyringAccessImpl");
+ GnomeKeyringAccess keyring = (GnomeKeyringAccess) clazz.getDeclaredConstructor().newInstance();
+ return Optional.of(keyring);
+ } catch (Exception e) {
+ return Optional.empty();
+ }
+ }
+}
diff --git a/main/keychain/src/main/java/org/cryptomator/keychain/LinuxSecretServiceAccess.java b/main/keychain/src/main/java/org/cryptomator/keychain/LinuxSecretServiceAccess.java
new file mode 100644
index 000000000..ef8dcb092
--- /dev/null
+++ b/main/keychain/src/main/java/org/cryptomator/keychain/LinuxSecretServiceAccess.java
@@ -0,0 +1,39 @@
+package org.cryptomator.keychain;
+
+import com.google.common.base.Preconditions;
+import org.apache.commons.lang3.SystemUtils;
+
+import javax.inject.Inject;
+import java.util.Optional;
+
+public class LinuxSecretServiceAccess implements KeychainAccessStrategy {
+ private final Optional gnomeLoginKeyring;
+
+ @Inject
+ public LinuxSecretServiceAccess() {
+ gnomeLoginKeyring = LinuxKeychainTester.getSecretService();
+ }
+
+ @Override
+ public boolean isSupported() {
+ return SystemUtils.IS_OS_LINUX && LinuxKeychainTester.getSecretService().isPresent();
+ }
+
+ @Override
+ public void storePassphrase(String key, CharSequence passphrase) {
+ Preconditions.checkState(gnomeLoginKeyring.isPresent());
+ gnomeLoginKeyring.get().storePassword(key, passphrase);
+ }
+
+ @Override
+ public char[] loadPassphrase(String key) {
+ Preconditions.checkState(gnomeLoginKeyring.isPresent());
+ return gnomeLoginKeyring.get().loadPassword(key);
+ }
+
+ @Override
+ public void deletePassphrase(String key) {
+ Preconditions.checkState(gnomeLoginKeyring.isPresent());
+ gnomeLoginKeyring.get().deletePassword(key);
+ }
+}
diff --git a/main/keychain/src/test/java/org/cryptomator/keychain/TestKeychainModule.java b/main/keychain/src/test/java/org/cryptomator/keychain/TestKeychainModule.java
index 66addc62a..80c4e6aa3 100644
--- a/main/keychain/src/test/java/org/cryptomator/keychain/TestKeychainModule.java
+++ b/main/keychain/src/test/java/org/cryptomator/keychain/TestKeychainModule.java
@@ -7,13 +7,11 @@ package org.cryptomator.keychain;
import java.util.Set;
-import com.google.common.collect.Sets;
-
public class TestKeychainModule extends KeychainModule {
@Override
- Set provideKeychainAccessStrategies(MacSystemKeychainAccess macKeychain, WindowsProtectedKeychainAccess winKeychain) {
- return Sets.newHashSet(new MapKeychainAccess());
+ Set provideKeychainAccessStrategies(MacSystemKeychainAccess macKeychain, WindowsProtectedKeychainAccess winKeychain, LinuxSecretServiceAccess linKeychain) {
+ return Set.of(new MapKeychainAccess());
}
}