diff --git a/spring-cloud-cli/src/main/java/org/springframework/cloud/cli/command/encrypt/BaseEncryptOptionHandler.java b/spring-cloud-cli/src/main/java/org/springframework/cloud/cli/command/encrypt/BaseEncryptOptionHandler.java index 39c1961..f26b8e5 100644 --- a/spring-cloud-cli/src/main/java/org/springframework/cloud/cli/command/encrypt/BaseEncryptOptionHandler.java +++ b/spring-cloud-cli/src/main/java/org/springframework/cloud/cli/command/encrypt/BaseEncryptOptionHandler.java @@ -40,6 +40,8 @@ class BaseEncryptOptionHandler extends OptionHandler { private OptionSpec passwordOption; + private OptionSpec keyPassOption; + private Charset charset; { @@ -48,16 +50,18 @@ class BaseEncryptOptionHandler extends OptionHandler { @Override protected final void options() { - this.keyOption = option( - asList("key", "k"), + this.keyOption = option(asList("key", "k"), "Specify key (symmetric secret, or pem-encoded key). If the value starts with @ it is interpreted as a file location.") - .withRequiredArg(); + .withRequiredArg(); this.passwordOption = option("password", - "A password for the keyfile (assuming the --key option is a KetStore file).") - .withRequiredArg(); + "A password for the keyfile (assuming the --key option is a KeyStore file).") + .withRequiredArg(); + this.keyPassOption = option("keypass", + "A password for the key, defaults to the same as the store password (assuming the --key option is a KeyStore file).") + .withRequiredArg(); this.aliasOption = option("alias", - "An alias for the the key in a keyfile (assuming the --key option is a KetStore file).") - .withRequiredArg(); + "An alias for the the key in a keyfile (assuming the --key option is a KeyStore file).") + .withRequiredArg(); doOptions(); } @@ -66,17 +70,25 @@ class BaseEncryptOptionHandler extends OptionHandler { protected TextEncryptor createEncryptor(OptionSet options) { String value = keyOption.value(options); - if (value==null) { + if (value == null) { throw new MissingKeyException(); } if (options.has(passwordOption)) { // it's a keystore String password = options.valueOf(passwordOption); String alias = options.valueOf(aliasOption); - KeyStoreKeyFactory factory = new KeyStoreKeyFactory(new FileSystemResource( - value), password.toCharArray()); - RsaSecretEncryptor encryptor = new RsaSecretEncryptor( - factory.getKeyPair(alias)); - return encryptor; + KeyStoreKeyFactory factory = new KeyStoreKeyFactory( + new FileSystemResource(value), password.toCharArray()); + if (options.has(keyPassOption)) { + String keypass = options.valueOf(keyPassOption); + RsaSecretEncryptor encryptor = new RsaSecretEncryptor( + factory.getKeyPair(alias, keypass.toCharArray())); + return encryptor; + } + else { + RsaSecretEncryptor encryptor = new RsaSecretEncryptor( + factory.getKeyPair(alias)); + return encryptor; + } } boolean verbose = Boolean.getBoolean("debug"); if (value.startsWith("@")) { diff --git a/spring-cloud-cli/src/test/java/org/springframework/cloud/cli/command/encrypt/DecryptCommandTests.java b/spring-cloud-cli/src/test/java/org/springframework/cloud/cli/command/encrypt/DecryptCommandTests.java index d0ea7a7..3e33e85 100644 --- a/spring-cloud-cli/src/test/java/org/springframework/cloud/cli/command/encrypt/DecryptCommandTests.java +++ b/spring-cloud-cli/src/test/java/org/springframework/cloud/cli/command/encrypt/DecryptCommandTests.java @@ -22,6 +22,7 @@ import java.nio.charset.Charset; import org.junit.Test; import org.springframework.boot.cli.command.status.ExitStatus; import org.springframework.core.io.ClassPathResource; +import org.springframework.security.rsa.crypto.KeyStoreKeyFactory; import org.springframework.security.rsa.crypto.RsaSecretEncryptor; import org.springframework.util.StreamUtils; @@ -49,6 +50,19 @@ public class DecryptCommandTests { command.run("-k", "@src/test/resources/private.pem", cipher)); } + @Test + public void decryptsFromRsaKeyWithKeyStore() throws Exception { + KeyStoreKeyFactory factory = new KeyStoreKeyFactory( + new ClassPathResource("keystore.jks"), "letmein".toCharArray()); + RsaSecretEncryptor encryptor = new RsaSecretEncryptor( + factory.getKeyPair("mytestkey", "changeme".toCharArray())); + String cipher = encryptor.encrypt("foo"); + assertEquals(ExitStatus.OK, + command.run("-k", "src/test/resources/keystore.jks", "--password", + "letmein", "--keypass", "changeme", "--alias", "mytestkey", + cipher)); + } + @Test(expected = IllegalArgumentException.class) public void failsWithPlainText() throws Exception { assertEquals(ExitStatus.OK, command.run("-k", "deadbeef", "foo")); diff --git a/spring-cloud-cli/src/test/resources/keystore.jks b/spring-cloud-cli/src/test/resources/keystore.jks new file mode 100644 index 0000000..8cd9b5a Binary files /dev/null and b/spring-cloud-cli/src/test/resources/keystore.jks differ