Support prehashed for the Transit engine.

Closes gh-745
Original pull request: gh-791
This commit is contained in:
Nanne Baars
2023-05-28 19:23:34 +02:00
committed by Mark Paluch
parent 196d3c7470
commit 253e8665d4
5 changed files with 103 additions and 11 deletions

View File

@@ -425,7 +425,7 @@ public class VaultTransitTemplate implements VaultTransitOperations {
static Map<String, Object> toRequestBody(VaultSignRequest signRequest) {
Map<String, Object> request = new LinkedHashMap<>(3);
Map<String, Object> request = new LinkedHashMap<>(4);
PropertyMapper mapper = PropertyMapper.get();
mapper.from(signRequest.getPlaintext()::getPlaintext)
@@ -433,6 +433,7 @@ public class VaultTransitTemplate implements VaultTransitOperations {
.to("input", request);
mapper.from(signRequest::getHashAlgorithm).whenHasText().to("hash_algorithm", request);
mapper.from(signRequest::getSignatureAlgorithm).whenHasText().to("signature_algorithm", request);
mapper.from(signRequest::isPrehashed).to("prehashed", request);
return request;
}
@@ -482,6 +483,7 @@ public class VaultTransitTemplate implements VaultTransitOperations {
.to("signature", request);
mapper.from(verificationRequest::getHashAlgorithm).whenHasText().to("hash_algorithm", request);
mapper.from(verificationRequest::getSignatureAlgorithm).whenHasText().to("signature_algorithm", request);
mapper.from(verificationRequest::isPrehashed).to("prehashed", request);
return request;
}

View File

@@ -17,8 +17,8 @@ package org.springframework.vault.support;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Base64;
import java.util.Objects;
import org.springframework.util.Assert;
/**

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.vault.support;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -36,11 +34,15 @@ public class VaultSignRequest {
private final @Nullable String signatureAlgorithm;
private VaultSignRequest(Plaintext plaintext, @Nullable String hashAlgorithm, @Nullable String signatureAlgorithm) {
private final boolean prehashed;
private VaultSignRequest(Plaintext plaintext, @Nullable String hashAlgorithm, @Nullable String signatureAlgorithm,
boolean prehashed) {
this.plaintext = plaintext;
this.hashAlgorithm = hashAlgorithm;
this.signatureAlgorithm = signatureAlgorithm;
this.prehashed = prehashed;
}
/**
@@ -97,6 +99,13 @@ public class VaultSignRequest {
return getSignatureAlgorithm();
}
/**
* @return true if the input is already hashed.
*/
public boolean isPrehashed() {
return this.prehashed;
}
/**
* Builder to build a {@link VaultSignRequest}.
*/
@@ -108,6 +117,8 @@ public class VaultSignRequest {
private @Nullable String signatureAlgorithm;
private boolean prehashed;
/**
* Configure the input to be used to create the signature.
* @param input base input to create the signature, must not be {@literal null}.
@@ -166,16 +177,27 @@ public class VaultSignRequest {
return signatureAlgorithm(algorithm);
}
/**
* Set to true when the input is already hashed. If the key type is rsa-2048,
* rsa-3072 or rsa-4096, then the algorithm used to hash the input should be
* indicated by the hash_algorithm parameter.
* @param prehashed whether the input is already hashed
* @return {@code this} {@link VaultSignRequestBuilder}.
*/
public VaultSignRequestBuilder prehashed(boolean prehashed) {
this.prehashed = prehashed;
return this;
}
/**
* Build a new {@link VaultSignRequest} instance. Requires
* {@link #plaintext(Plaintext)} to be configured.
* @return a new {@link VaultSignRequest}.
*/
public VaultSignRequest build() {
Assert.notNull(this.plaintext, "Plaintext input must not be null");
return new VaultSignRequest(this.plaintext, this.hashAlgorithm, this.signatureAlgorithm);
return new VaultSignRequest(this.plaintext, this.hashAlgorithm, this.signatureAlgorithm, this.prehashed);
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.vault.support;
import org.checkerframework.checker.units.qual.A;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -39,14 +40,17 @@ public class VaultSignatureVerificationRequest {
private final @Nullable String signatureAlgorithm;
private final boolean prehashed;
private VaultSignatureVerificationRequest(Plaintext plaintext, @Nullable Signature signature, @Nullable Hmac hmac,
@Nullable String hashAlgorithm, @Nullable String signatureAlgorithm) {
@Nullable String hashAlgorithm, @Nullable String signatureAlgorithm, boolean prehashed) {
this.plaintext = plaintext;
this.signature = signature;
this.hmac = hmac;
this.hashAlgorithm = hashAlgorithm;
this.signatureAlgorithm = signatureAlgorithm;
this.prehashed = prehashed;
}
/**
@@ -136,6 +140,13 @@ public class VaultSignatureVerificationRequest {
return getSignatureAlgorithm();
}
/**
* @return true if the input is already hashed.
*/
public boolean isPrehashed() {
return this.prehashed;
}
/**
* Builder to build a {@link VaultSignatureVerificationRequest}.
*/
@@ -151,6 +162,8 @@ public class VaultSignatureVerificationRequest {
private @Nullable String signatureAlgorithm;
private boolean prehashed;
/**
* Configure the {@link Plaintext} input to be used to verify the signature.
* @param input base input, must not be {@literal null}.
@@ -230,6 +243,11 @@ public class VaultSignatureVerificationRequest {
return this;
}
public VaultSignatureVerificationRequestBuilder prehashed(boolean prehashed) {
this.prehashed = prehashed;
return this;
}
/**
* Configure the algorithm to be used for the operation.
* @param algorithm Specify the algorithm to be used for the operation. Supported
@@ -255,7 +273,7 @@ public class VaultSignatureVerificationRequest {
Assert.isTrue(this.hmac != null || this.signature != null, "Either Signature or Hmac must not be null");
return new VaultSignatureVerificationRequest(this.input, this.signature, this.hmac, this.hashAlgorithm,
this.signatureAlgorithm);
this.signatureAlgorithm, this.prehashed);
}
}

View File

@@ -15,12 +15,15 @@
*/
package org.springframework.vault.core;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.fail;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@@ -29,7 +32,6 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -807,6 +809,54 @@ class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport {
assertThat(signature.getSignature()).isNotEmpty();
}
@Test
@RequiresVaultVersion(SIGN_VERIFY_INTRODUCED_IN_VERSION)
void signAndVerifyWithPrehashedInput() {
String keyName = createEcdsaP256Key();
Plaintext plaintext = Plaintext.of("P8m2iUWdc4+MiKOkiqnjNUIBa3pAUuABqqU2/KdIE8s=");
VaultSignRequest signRequest = VaultSignRequest.builder()
.plaintext(plaintext)
.signatureAlgorithm("pkcs1v15")
.prehashed(true)
.build();
Signature signature = this.transitOperations.sign(keyName, signRequest);
assertThat(signature.getSignature()).isNotEmpty();
VaultSignatureVerificationRequest verifyRequest = VaultSignatureVerificationRequest.builder()
.prehashed(true)
.plaintext(plaintext)
.signature(signature)
.signatureAlgorithm("pkcs1v15")
.build();
SignatureValidation validation = this.transitOperations.verify(keyName, verifyRequest);
assertThat(validation.isValid()).isTrue();
}
@Test
@RequiresVaultVersion(SIGN_VERIFY_INTRODUCED_IN_VERSION)
void signWithPrehashedAndVerifyWithoutShouldFail() {
String keyName = createEcdsaP256Key();
Plaintext plaintext = Plaintext.of("P8m2iUWdc4+MiKOkiqnjNUIBa3pAUuABqqU2/KdIE8s=");
VaultSignRequest signRequest = VaultSignRequest.builder()
.plaintext(plaintext)
.signatureAlgorithm("pkcs1v15")
.prehashed(true)
.build();
Signature signature = this.transitOperations.sign(keyName, signRequest);
assertThat(signature.getSignature()).isNotEmpty();
VaultSignatureVerificationRequest verifyRequest = VaultSignatureVerificationRequest.builder()
.prehashed(false)
.plaintext(plaintext)
.signature(signature)
.signatureAlgorithm("pkcs1v15")
.build();
SignatureValidation validation = this.transitOperations.verify(keyName, verifyRequest);
assertThat(validation.isValid()).isFalse();
}
@Test
@RequiresVaultVersion(SIGN_VERIFY_INTRODUCED_IN_VERSION)
void shouldVerifyValidSignature() {