diff --git a/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTransitTemplate.java b/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTransitTemplate.java index 9c2d18d9..7c39ff59 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTransitTemplate.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTransitTemplate.java @@ -56,6 +56,7 @@ import org.springframework.vault.support.VaultTransitKeyCreationRequest; * @author Sven Schürmann * @author Praveendra Singh * @author Luander Ribeiro + * @author Mikko Koli */ public class VaultTransitTemplate implements VaultTransitOperations { @@ -266,7 +267,7 @@ public class VaultTransitTemplate implements VaultTransitOperations { byte[] plaintext = decrypt(keyName, ciphertext.getCiphertext(), ciphertext.getContext()); - return toPlaintext(plaintext, ciphertext.getContext()); + return Plaintext.of(plaintext).with(ciphertext.getContext()); } @Override @@ -525,20 +526,9 @@ public class VaultTransitTemplate implements VaultTransitOperations { VaultDecryptionResult encrypted; Ciphertext ciphertext = batchRequest.get(i); - if (batchData.size() > i) { - Map data = batchData.get(i); - if (StringUtils.hasText(data.get("error"))) { - encrypted = new VaultDecryptionResult(new VaultException( - data.get("error"))); - } - else if (StringUtils.hasText(data.get("plaintext"))) { - encrypted = new VaultDecryptionResult(toPlaintext( - Base64Utils.decodeFromString(data.get("plaintext")), - ciphertext.getContext())); - } else { - encrypted = new VaultDecryptionResult(toPlaintext("",ciphertext.getContext())); - } + if (batchData.size() > i) { + encrypted = getDecryptionResult(batchData.get(i), ciphertext); } else { encrypted = new VaultDecryptionResult(new VaultException( @@ -551,21 +541,29 @@ public class VaultTransitTemplate implements VaultTransitOperations { return result; } - private static Ciphertext toCiphertext(String ciphertext, VaultTransitContext context) { + private static VaultDecryptionResult getDecryptionResult(Map data, + Ciphertext ciphertext) { + + if (StringUtils.hasText(data.get("error"))) { + return new VaultDecryptionResult(new VaultException(data.get("error"))); + } + + if (StringUtils.hasText(data.get("plaintext"))) { + + byte[] plaintext = Base64Utils.decodeFromString(data.get("plaintext")); + return new VaultDecryptionResult(Plaintext.of(plaintext).with( + ciphertext.getContext())); + } + + return new VaultDecryptionResult(Plaintext.empty().with(ciphertext.getContext())); + } + + private static Ciphertext toCiphertext(String ciphertext, + @Nullable VaultTransitContext context) { return context != null ? Ciphertext.of(ciphertext).with(context) : Ciphertext .of(ciphertext); } - private static Plaintext toPlaintext(byte[] plaintext, VaultTransitContext context) { - return context != null ? Plaintext.of(plaintext).with(context) : Plaintext - .of(plaintext); - } - - private static Plaintext toPlaintext(String plaintext, VaultTransitContext context) { - return context != null ? Plaintext.of(plaintext).with(context) : Plaintext - .of(plaintext); - } - @SuppressWarnings("unchecked") private static List> getBatchData(VaultResponse vaultResponse) { return (List>) vaultResponse.getRequiredData().get( @@ -654,5 +652,4 @@ public class VaultTransitTemplate implements VaultTransitOperations { @Nullable private String name; } - } diff --git a/spring-vault-core/src/main/java/org/springframework/vault/support/Ciphertext.java b/spring-vault-core/src/main/java/org/springframework/vault/support/Ciphertext.java index 9e6e9618..7dbfcc1d 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/support/Ciphertext.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/support/Ciphertext.java @@ -64,10 +64,13 @@ public class Ciphertext { * Create a new {@link Ciphertext} object from this ciphertext associated with the * given {@link VaultTransitContext}. * - * @param context transit context. + * @param context transit context, must not be {@literal null}. * @return the new {@link Ciphertext} object. */ public Ciphertext with(VaultTransitContext context) { + + Assert.notNull(context, "VaultTransitContext must not be null"); + return new Ciphertext(getCiphertext(), context); } } diff --git a/spring-vault-core/src/main/java/org/springframework/vault/support/Plaintext.java b/spring-vault-core/src/main/java/org/springframework/vault/support/Plaintext.java index 1159e834..1c36add3 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/support/Plaintext.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/support/Plaintext.java @@ -30,6 +30,9 @@ import org.springframework.util.Assert; @EqualsAndHashCode public class Plaintext { + private static final Plaintext EMPTY = new Plaintext(new byte[0], + VaultTransitContext.empty()); + private final byte[] plaintext; private final VaultTransitContext context; @@ -40,6 +43,16 @@ public class Plaintext { this.context = context; } + /** + * Factory method to create an empty {@link Plaintext}. + * + * @return the empty {@link Plaintext} object. + * @since 1.1.2 + */ + public static Plaintext empty() { + return EMPTY; + } + /** * Factory method to create {@link Plaintext} from a byte sequence. * @@ -50,6 +63,10 @@ public class Plaintext { Assert.notNull(plaintext, "Plaintext must not be null"); + if (plaintext.length == 0) { + return empty(); + } + return new Plaintext(plaintext, VaultTransitContext.empty()); } @@ -65,6 +82,10 @@ public class Plaintext { Assert.notNull(plaintext, "Plaintext must not be null"); + if (plaintext.length() == 0) { + return empty(); + } + return of(plaintext.getBytes()); } diff --git a/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTemplateTransitIntegrationTests.java b/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTemplateTransitIntegrationTests.java index 0676a693..7818f765 100644 --- a/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTemplateTransitIntegrationTests.java +++ b/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTemplateTransitIntegrationTests.java @@ -106,7 +106,7 @@ public class VaultTemplateTransitIntegrationTests extends IntegrationTestSupport Collections.singletonMap("plaintext", Base64.encodeBase64String("that message is secret".getBytes()))); - assertThat((String) response.getData().get("ciphertext")).isNotEmpty(); + assertThat((String) response.getRequiredData().get("ciphertext")).isNotEmpty(); } @Test @@ -120,9 +120,9 @@ public class VaultTemplateTransitIntegrationTests extends IntegrationTestSupport VaultResponse decrypted = vaultOperations.write( "transit/decrypt/mykey", Collections.singletonMap("ciphertext", - response.getData().get("ciphertext"))); + response.getRequiredData().get("ciphertext"))); - assertThat((String) decrypted.getData().get("plaintext")).isEqualTo( + assertThat((String) decrypted.getRequiredData().get("plaintext")).isEqualTo( Base64.encodeBase64String("that message is secret".getBytes())); } } diff --git a/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTransitTemplateIntegrationTests.java b/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTransitTemplateIntegrationTests.java index 680d31f9..c4cbe675 100644 --- a/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTransitTemplateIntegrationTests.java +++ b/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTransitTemplateIntegrationTests.java @@ -59,6 +59,7 @@ import static org.junit.Assume.assumeTrue; * @author Mark Paluch * @author Praveendra Singh * @author Luander Ribeiro + * @author Mikko Koli */ @RunWith(SpringRunner.class) @ContextConfiguration(classes = VaultIntegrationTestConfiguration.class) @@ -547,43 +548,43 @@ public class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport } @Test - public void shouldBatchDecryptEmptyPlaintext() { - assumeTrue(vaultVersion.isGreaterThanOrEqualTo(BATCH_INTRODUCED_IN_VERSION)); + public void shouldBatchDecryptEmptyPlaintext() { - transitOperations.createKey("mykey"); + assumeTrue(vaultVersion.isGreaterThanOrEqualTo(BATCH_INTRODUCED_IN_VERSION)); - Ciphertext empty = transitOperations.encrypt("mykey", Plaintext.of("")); + transitOperations.createKey("mykey"); - List decrypted = transitOperations.decrypt("mykey", - Arrays.asList(empty)); + Ciphertext empty = transitOperations.encrypt("mykey", Plaintext.empty()); - assertThat(decrypted.get(0).getAsString()).isEqualTo(""); - } + List decrypted = transitOperations.decrypt("mykey", + Collections.singletonList(empty)); - @Test - public void shouldBatchDecryptEmpltyPlaintextWithContext() { + assertThat(decrypted.get(0).getAsString()).isEqualTo(""); + } - assumeTrue(vaultVersion.isGreaterThanOrEqualTo(BATCH_INTRODUCED_IN_VERSION)); + @Test + public void shouldBatchDecryptEmptyPlaintextWithContext() { - VaultTransitKeyCreationRequest request = VaultTransitKeyCreationRequest.builder() // - .derived(true) // - .build(); + assumeTrue(vaultVersion.isGreaterThanOrEqualTo(BATCH_INTRODUCED_IN_VERSION)); - transitOperations.createKey("mykey", request); + VaultTransitKeyCreationRequest request = VaultTransitKeyCreationRequest.builder() // + .derived(true) // + .build(); - Plaintext empty = Plaintext.of("").with( - VaultTransitContext.builder().context("oneContext".getBytes()).build()); + transitOperations.createKey("mykey", request); - List encrypted = transitOperations.encrypt("mykey", - Arrays.asList(empty)); - List decrypted = transitOperations.decrypt("mykey", - Arrays.asList(encrypted.get(0).get())); + Plaintext empty = Plaintext.empty().with( + VaultTransitContext.builder().context("oneContext".getBytes()).build()); - assertThat(decrypted.get(0).get()).isEqualTo(empty); - } + List encrypted = transitOperations.encrypt("mykey", + Collections.singletonList(empty)); + List decrypted = transitOperations.decrypt("mykey", + Collections.singletonList(encrypted.get(0).get())); + assertThat(decrypted.get(0).get()).isEqualTo(empty); + } - @Test + @Test public void generateHmacShouldCreateHmac() { assumeTrue(vaultVersion.isGreaterThanOrEqualTo(SIGN_VERIFY_INTRODUCED_IN_VERSION));