mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-03-09 22:00:20 +01:00
#979 rename KeyStore to SecretKeyStore
This commit is contained in:
@@ -78,15 +78,15 @@ final class ConfigFiles {
|
||||
/**
|
||||
* Decrypt and parse v1 configuration file.
|
||||
*
|
||||
* @param keyStore key store
|
||||
* @param secretKeyStore key store
|
||||
* @param file configuration file
|
||||
*
|
||||
* @return client configuration
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
static ScmClientConfig parseV1(KeyStore keyStore, File file) throws IOException {
|
||||
String secretKey = secretKey(keyStore);
|
||||
static ScmClientConfig parseV1(SecretKeyStore secretKeyStore, File file) throws IOException {
|
||||
String secretKey = secretKey(secretKeyStore);
|
||||
CipherStreamHandler cipherStreamHandler = new WeakCipherStreamHandler(secretKey);
|
||||
return decrypt(cipherStreamHandler, new FileInputStream(file));
|
||||
}
|
||||
@@ -94,15 +94,15 @@ final class ConfigFiles {
|
||||
/**
|
||||
* Decrypt and parse v12configuration file.
|
||||
*
|
||||
* @param keyStore key store
|
||||
* @param secretKeyStore key store
|
||||
* @param file configuration file
|
||||
*
|
||||
* @return client configuration
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
static ScmClientConfig parseV2(KeyStore keyStore, File file) throws IOException {
|
||||
String secretKey = secretKey(keyStore);
|
||||
static ScmClientConfig parseV2(SecretKeyStore secretKeyStore, File file) throws IOException {
|
||||
String secretKey = secretKey(secretKeyStore);
|
||||
CipherStreamHandler cipherStreamHandler = new AesCipherStreamHandler(secretKey);
|
||||
try (InputStream input = new FileInputStream(file)) {
|
||||
input.skip(VERSION_IDENTIFIER.length);
|
||||
@@ -114,24 +114,24 @@ final class ConfigFiles {
|
||||
* Store encrypt and write the configuration to the given file.
|
||||
* Note the method uses always the latest available format.
|
||||
*
|
||||
* @param keyStore key store
|
||||
* @param secretKeyStore key store
|
||||
* @param config configuration
|
||||
* @param file configuration file
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
static void store(KeyStore keyStore, ScmClientConfig config, File file) throws IOException {
|
||||
static void store(SecretKeyStore secretKeyStore, ScmClientConfig config, File file) throws IOException {
|
||||
String secretKey = keyGenerator.createKey();
|
||||
CipherStreamHandler cipherStreamHandler = new AesCipherStreamHandler(secretKey);
|
||||
try (OutputStream output = new FileOutputStream(file)) {
|
||||
output.write(VERSION_IDENTIFIER);
|
||||
encrypt(cipherStreamHandler, output, config);
|
||||
}
|
||||
keyStore.set(secretKey);
|
||||
secretKeyStore.set(secretKey);
|
||||
}
|
||||
|
||||
private static String secretKey(KeyStore keyStore) {
|
||||
String secretKey = keyStore.get();
|
||||
private static String secretKey(SecretKeyStore secretKeyStore) {
|
||||
String secretKey = secretKeyStore.get();
|
||||
Preconditions.checkState(!Strings.isNullOrEmpty(secretKey), "no stored secret key found");
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
@@ -47,14 +47,14 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* The EncryptionKeyStoreWrapper is a wrapper around the {@link KeyStore} interface. The wrapper will encrypt the passed
|
||||
* keys, before they are written to the underlying {@link KeyStore} implementation. The wrapper will also honor old
|
||||
* unencrypted keys.
|
||||
* The EncryptionSecretKeyStoreWrapper is a wrapper around the {@link SecretKeyStore} interface. The wrapper will
|
||||
* encrypt the passed secret keys, before they are written to the underlying {@link SecretKeyStore} implementation. The
|
||||
* wrapper will also honor old unencrypted keys.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.60
|
||||
*/
|
||||
public class EncryptionKeyStoreWrapper implements KeyStore {
|
||||
public class EncryptionSecretKeyStoreWrapper implements SecretKeyStore {
|
||||
|
||||
private static final String ALGORITHM = "AES";
|
||||
|
||||
@@ -70,16 +70,16 @@ public class EncryptionKeyStoreWrapper implements KeyStore {
|
||||
@VisibleForTesting
|
||||
static final String ENCRYPTED_PREFIX = "SKV2:";
|
||||
|
||||
private KeyStore wrappedKeyStore;
|
||||
private SecretKeyStore wrappedSecretKeyStore;
|
||||
|
||||
EncryptionKeyStoreWrapper(KeyStore wrappedKeyStore) {
|
||||
this.wrappedKeyStore = wrappedKeyStore;
|
||||
EncryptionSecretKeyStoreWrapper(SecretKeyStore wrappedSecretKeyStore) {
|
||||
this.wrappedSecretKeyStore = wrappedSecretKeyStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String secretKey) {
|
||||
String encrypted = encrypt(secretKey);
|
||||
wrappedKeyStore.set(ENCRYPTED_PREFIX.concat(encrypted));
|
||||
wrappedSecretKeyStore.set(ENCRYPTED_PREFIX.concat(encrypted));
|
||||
}
|
||||
|
||||
private String encrypt(String value) {
|
||||
@@ -98,7 +98,7 @@ public class EncryptionKeyStoreWrapper implements KeyStore {
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
String value = wrappedKeyStore.get();
|
||||
String value = wrappedSecretKeyStore.get();
|
||||
if (Strings.nullToEmpty(value).startsWith(ENCRYPTED_PREFIX)) {
|
||||
String encrypted = value.substring(ENCRYPTED_PREFIX.length());
|
||||
return decrypt(encrypted);
|
||||
@@ -133,6 +133,6 @@ public class EncryptionKeyStoreWrapper implements KeyStore {
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
wrappedKeyStore.remove();
|
||||
wrappedSecretKeyStore.remove();
|
||||
}
|
||||
}
|
||||
@@ -34,15 +34,18 @@ package sonia.scm.cli.config;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
/**
|
||||
* KeyStore implementation with uses {@link Preferences}.
|
||||
* SecretKeyStore implementation with uses {@link Preferences}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.60
|
||||
*/
|
||||
public class PrefsKeyStore implements KeyStore {
|
||||
public class PrefsSecretKeyStore implements SecretKeyStore {
|
||||
|
||||
private static final String PREF_SECRET_KEY = "scm.client.key";
|
||||
|
||||
private final Preferences preferences;
|
||||
|
||||
public PrefsKeyStore() {
|
||||
PrefsSecretKeyStore() {
|
||||
// we use ScmClientConfigFileHandler as base for backward compatibility
|
||||
preferences = Preferences.userNodeForPackage(ScmClientConfigFileHandler.class);
|
||||
}
|
||||
@@ -57,20 +57,20 @@ public class ScmClientConfigFileHandler
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
|
||||
private final KeyStore keyStore;
|
||||
private final SecretKeyStore secretKeyStore;
|
||||
private final File file;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new ScmClientConfigFileHandler with a encrypted {@link java.util.prefs.Preferences} based
|
||||
* {@link KeyStore} and a determined default location.
|
||||
* {@link SecretKeyStore} and a determined default location.
|
||||
*/
|
||||
public ScmClientConfigFileHandler() {
|
||||
this(new EncryptionKeyStoreWrapper(new PrefsKeyStore()), getDefaultConfigFile());
|
||||
this(new EncryptionSecretKeyStoreWrapper(new PrefsSecretKeyStore()), getDefaultConfigFile());
|
||||
}
|
||||
|
||||
ScmClientConfigFileHandler(KeyStore keyStore,File file) {
|
||||
this.keyStore = keyStore;
|
||||
ScmClientConfigFileHandler(SecretKeyStore secretKeyStore, File file) {
|
||||
this.secretKeyStore = secretKeyStore;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ public class ScmClientConfigFileHandler
|
||||
throw new ScmConfigException("could not delete config file");
|
||||
}
|
||||
|
||||
keyStore.remove();
|
||||
secretKeyStore.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,10 +117,10 @@ public class ScmClientConfigFileHandler
|
||||
ScmClientConfig config;
|
||||
try {
|
||||
if (ConfigFiles.isFormatV2(file)) {
|
||||
config = ConfigFiles.parseV2(keyStore, file);
|
||||
config = ConfigFiles.parseV2(secretKeyStore, file);
|
||||
} else {
|
||||
config = ConfigFiles.parseV1(keyStore, file);
|
||||
ConfigFiles.store(keyStore, config, file);
|
||||
config = ConfigFiles.parseV1(secretKeyStore, file);
|
||||
ConfigFiles.store(secretKeyStore, config, file);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw new ScmConfigException("could not read config file", ex);
|
||||
@@ -136,7 +136,7 @@ public class ScmClientConfigFileHandler
|
||||
*/
|
||||
public void write(ScmClientConfig config) {
|
||||
try {
|
||||
ConfigFiles.store(keyStore, config, file);
|
||||
ConfigFiles.store(secretKeyStore, config, file);
|
||||
} catch (IOException ex) {
|
||||
throw new ScmConfigException("could not write config file", ex);
|
||||
}
|
||||
|
||||
@@ -32,9 +32,12 @@
|
||||
package sonia.scm.cli.config;
|
||||
|
||||
/**
|
||||
* KeyStore is able to read and write keys.
|
||||
* SecretKeyStore is able to read and write secret keys.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.60
|
||||
*/
|
||||
public interface KeyStore {
|
||||
public interface SecretKeyStore {
|
||||
|
||||
/**
|
||||
* Writes the given secret key to the store.
|
||||
@@ -69,7 +69,7 @@ public class ConfigFilesTest {
|
||||
|
||||
@Test
|
||||
public void testParseV1() throws IOException {
|
||||
InMemoryKeyStore keyStore = createKeyStore();
|
||||
InMemorySecretKeyStore keyStore = createKeyStore();
|
||||
WeakCipherStreamHandler handler = new WeakCipherStreamHandler(keyStore.get());
|
||||
|
||||
ScmClientConfig config = ClientConfigurationTests.createSampleConfig();
|
||||
@@ -82,7 +82,7 @@ public class ConfigFilesTest {
|
||||
|
||||
@Test
|
||||
public void storeAndParseV2() throws IOException {
|
||||
InMemoryKeyStore keyStore = new InMemoryKeyStore();
|
||||
InMemorySecretKeyStore keyStore = new InMemorySecretKeyStore();
|
||||
ScmClientConfig config = ClientConfigurationTests.createSampleConfig();
|
||||
File file = temporaryFolder.newFile();
|
||||
|
||||
@@ -95,9 +95,9 @@ public class ConfigFilesTest {
|
||||
ClientConfigurationTests.assertSampleConfig(config);
|
||||
}
|
||||
|
||||
private InMemoryKeyStore createKeyStore() {
|
||||
private InMemorySecretKeyStore createKeyStore() {
|
||||
String secretKey = new SecureRandomKeyGenerator().createKey();
|
||||
InMemoryKeyStore keyStore = new InMemoryKeyStore();
|
||||
InMemorySecretKeyStore keyStore = new InMemorySecretKeyStore();
|
||||
keyStore.set(secretKey);
|
||||
return keyStore;
|
||||
}
|
||||
|
||||
@@ -37,23 +37,23 @@ import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class EncryptionKeyStoreWrapperTest {
|
||||
public class EncryptionSecretKeyStoreWrapperTest {
|
||||
|
||||
private KeyStore keyStore = new InMemoryKeyStore();
|
||||
private SecretKeyStore secretKeyStore = new InMemorySecretKeyStore();
|
||||
|
||||
@Test
|
||||
public void testEncryptionKeyStoreWrapper() {
|
||||
EncryptionKeyStoreWrapper wrapper = new EncryptionKeyStoreWrapper(keyStore);
|
||||
EncryptionSecretKeyStoreWrapper wrapper = new EncryptionSecretKeyStoreWrapper(secretKeyStore);
|
||||
wrapper.set("mysecretkey");
|
||||
|
||||
assertEquals("mysecretkey", wrapper.get());
|
||||
assertTrue(keyStore.get().startsWith(EncryptionKeyStoreWrapper.ENCRYPTED_PREFIX));
|
||||
assertTrue(secretKeyStore.get().startsWith(EncryptionSecretKeyStoreWrapper.ENCRYPTED_PREFIX));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncryptionKeyStoreWrapperWithOldUnencryptedKey() {
|
||||
keyStore.set("mysecretkey");
|
||||
EncryptionKeyStoreWrapper wrapper = new EncryptionKeyStoreWrapper(keyStore);
|
||||
secretKeyStore.set("mysecretkey");
|
||||
EncryptionSecretKeyStoreWrapper wrapper = new EncryptionSecretKeyStoreWrapper(secretKeyStore);
|
||||
assertEquals("mysecretkey", wrapper.get());
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
package sonia.scm.cli.config;
|
||||
|
||||
public class InMemoryKeyStore implements KeyStore {
|
||||
public class InMemorySecretKeyStore implements SecretKeyStore {
|
||||
|
||||
private String secretKey;
|
||||
|
||||
@@ -54,7 +54,7 @@ public class ScmClientConfigFileHandlerTest {
|
||||
File configFile = temporaryFolder.newFile();
|
||||
|
||||
ScmClientConfigFileHandler handler = new ScmClientConfigFileHandler(
|
||||
new EncryptionKeyStoreWrapper(new InMemoryKeyStore()), configFile
|
||||
new EncryptionSecretKeyStoreWrapper(new InMemorySecretKeyStore()), configFile
|
||||
);
|
||||
|
||||
ScmClientConfig config = new ScmClientConfig();
|
||||
@@ -90,18 +90,18 @@ public class ScmClientConfigFileHandlerTest {
|
||||
|
||||
assertFalse(ConfigFiles.isFormatV2(configFile));
|
||||
|
||||
KeyStore keyStore = new EncryptionKeyStoreWrapper(new InMemoryKeyStore());
|
||||
keyStore.set(key);
|
||||
SecretKeyStore secretKeyStore = new EncryptionSecretKeyStoreWrapper(new InMemorySecretKeyStore());
|
||||
secretKeyStore.set(key);
|
||||
|
||||
ScmClientConfigFileHandler handler = new ScmClientConfigFileHandler(
|
||||
keyStore, configFile
|
||||
secretKeyStore, configFile
|
||||
);
|
||||
|
||||
ScmClientConfig config = handler.read();
|
||||
ClientConfigurationTests.assertSampleConfig(config);
|
||||
|
||||
// ensure key has changed
|
||||
assertNotEquals(key, keyStore.get());
|
||||
assertNotEquals(key, secretKeyStore.get());
|
||||
|
||||
// ensure config rewritten with v2
|
||||
assertTrue(ConfigFiles.isFormatV2(configFile));
|
||||
@@ -116,11 +116,11 @@ public class ScmClientConfigFileHandlerTest {
|
||||
Files.write(bytes, configFile);
|
||||
|
||||
String key = "358e018a-0c3c-4339-8266-3874e597305f";
|
||||
KeyStore keyStore = new EncryptionKeyStoreWrapper(new InMemoryKeyStore());
|
||||
keyStore.set(key);
|
||||
SecretKeyStore secretKeyStore = new EncryptionSecretKeyStoreWrapper(new InMemorySecretKeyStore());
|
||||
secretKeyStore.set(key);
|
||||
|
||||
ScmClientConfigFileHandler handler = new ScmClientConfigFileHandler(
|
||||
keyStore, configFile
|
||||
secretKeyStore, configFile
|
||||
);
|
||||
|
||||
ScmClientConfig config = handler.read();
|
||||
@@ -130,7 +130,7 @@ public class ScmClientConfigFileHandlerTest {
|
||||
assertEquals("trillian123", defaultConfig.getPassword());
|
||||
|
||||
// ensure key has changed
|
||||
assertNotEquals(key, keyStore.get());
|
||||
assertNotEquals(key, secretKeyStore.get());
|
||||
|
||||
// ensure config rewritten with v2
|
||||
assertTrue(ConfigFiles.isFormatV2(configFile));
|
||||
|
||||
Reference in New Issue
Block a user