mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-21 20:21:27 +00:00
defined keychain access interfaces
This commit is contained in:
39
main/keychain/pom.xml
Normal file
39
main/keychain/pom.xml
Normal file
@@ -0,0 +1,39 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>keychain</artifactId>
|
||||
<name>System Keychain Access</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<version>1.54</version>
|
||||
</dependency>
|
||||
|
||||
<!-- DI -->
|
||||
<dependency>
|
||||
<groupId>com.google.dagger</groupId>
|
||||
<artifactId>dagger</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.dagger</groupId>
|
||||
<artifactId>dagger-compiler</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>commons-test</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.cryptomator.keychain;
|
||||
|
||||
public interface KeychainAccess {
|
||||
|
||||
/**
|
||||
* Associates a passphrase with a given key.
|
||||
*
|
||||
* @param key Key used to retrieve the passphrase via {@link #loadPassphrase(String)}.
|
||||
* @param passphrase The secret to store in this keychain.
|
||||
*/
|
||||
void storePassphrase(String key, CharSequence passphrase);
|
||||
|
||||
/**
|
||||
* @param key Unique key previously used while {@link #storePassphrase(String, CharSequence) storing a passphrase}.
|
||||
* @return The stored passphrase for the given key or <code>null</code> if no value for the given key could be found.
|
||||
*/
|
||||
CharSequence loadPassphrase(String key);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.cryptomator.keychain;
|
||||
|
||||
interface KeychainAccessStrategy extends KeychainAccess {
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if this KeychainAccessStrategy works on the current machine.
|
||||
*/
|
||||
boolean isSupported();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.cryptomator.keychain;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Component;
|
||||
|
||||
@Singleton
|
||||
@Component(modules = KeychainModule.class)
|
||||
public interface KeychainComponent {
|
||||
|
||||
Optional<KeychainAccess> keychainAccess();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.cryptomator.keychain;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import dagger.multibindings.ElementsIntoSet;
|
||||
|
||||
@Module
|
||||
public class KeychainModule {
|
||||
|
||||
@Provides
|
||||
@ElementsIntoSet
|
||||
Set<KeychainAccessStrategy> provideKeychainAccessStrategies(MacSystemKeychainAccess macKeychain, WindowsSystemKeychainAccess winKeychain) {
|
||||
return Sets.newHashSet(macKeychain, winKeychain);
|
||||
}
|
||||
|
||||
@Provides
|
||||
public Optional<KeychainAccess> provideSupportedKeychain(Set<KeychainAccessStrategy> keychainAccessStrategies) {
|
||||
return keychainAccessStrategies.stream().filter(KeychainAccessStrategy::isSupported).map(KeychainAccess.class::cast).findFirst();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.cryptomator.keychain;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyStore;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
@Singleton
|
||||
class MacSystemKeychainAccess implements KeychainAccessStrategy {
|
||||
|
||||
private final KeyStore keyStore;
|
||||
|
||||
@Inject
|
||||
public MacSystemKeychainAccess() {
|
||||
KeyStore ks;
|
||||
try {
|
||||
ks = KeyStore.getInstance("KeychainStore", "Apple");
|
||||
ks.load(null);
|
||||
} catch (GeneralSecurityException | IOException e) {
|
||||
ks = null;
|
||||
}
|
||||
this.keyStore = ks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storePassphrase(String key, CharSequence passphrase) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence loadPassphrase(String key) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return SystemUtils.IS_OS_MAC_OSX && keyStore != null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.cryptomator.keychain;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyStore;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
@Singleton
|
||||
class WindowsSystemKeychainAccess implements KeychainAccessStrategy {
|
||||
|
||||
private final KeyStore keyStore;
|
||||
|
||||
@Inject
|
||||
public WindowsSystemKeychainAccess() {
|
||||
KeyStore ks;
|
||||
try {
|
||||
ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
|
||||
ks.load(null);
|
||||
} catch (GeneralSecurityException | IOException e) {
|
||||
ks = null;
|
||||
}
|
||||
this.keyStore = ks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storePassphrase(String key, CharSequence passphrase) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence loadPassphrase(String key) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return SystemUtils.IS_OS_WINDOWS && keyStore != null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.cryptomator.keychain;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class KeychainModuleTest {
|
||||
|
||||
@Test
|
||||
public void testGetKeychain() {
|
||||
Optional<KeychainAccess> keychainAccess = DaggerKeychainComponent.builder().keychainModule(new KeychainTestModule()).build().keychainAccess();
|
||||
Assert.assertTrue(keychainAccess.isPresent());
|
||||
Assert.assertTrue(keychainAccess.get() instanceof MapKeychainAccess);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.cryptomator.keychain;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
public class KeychainTestModule extends KeychainModule {
|
||||
|
||||
@Override
|
||||
Set<KeychainAccessStrategy> provideKeychainAccessStrategies(MacSystemKeychainAccess macKeychain, WindowsSystemKeychainAccess winKeychain) {
|
||||
return Sets.newHashSet(new MapKeychainAccess());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.cryptomator.keychain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
class MapKeychainAccess implements KeychainAccessStrategy {
|
||||
|
||||
private final Map<String, CharSequence> map = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void storePassphrase(String key, CharSequence passphrase) {
|
||||
map.put(key, passphrase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence loadPassphrase(String key) {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -273,6 +273,7 @@
|
||||
<module>frontend-webdav</module>
|
||||
<module>ui</module>
|
||||
<module>filesystem-charsets</module>
|
||||
<module>keychain</module>
|
||||
</modules>
|
||||
|
||||
<profiles>
|
||||
|
||||
Reference in New Issue
Block a user