I have to validate the signature of the petition everything happens fine until I run verify that it always returns false, someone could give me a hand
public AuthenticateMethodResponse verifyHttpSignatureRequest(ContainerRequestContext requestContext) {
MultivaluedMap<String, String> reqHeaders = requestContext.getHeaders();
String authorization = reqHeaders.getFirst("authorization");
logger.info("Verifying HTTP signature");
if (authorization == null || !authorization.toLowerCase().startsWith("signature")) {
return AuthenticateMethodResponse.builder()
.withRequiredMethodInfoFulfilled(false)
.withResponseCode(javax.ws.rs.core.Response.Status.UNAUTHORIZED)
.build();
}
Signature signature = Signature.fromString(authorization);
logger.info("Signature: " + signature);
if (signature.getAlgorithm() != Algorithm.RSA_SHA256) {
return AuthenticateMethodResponse.builder()
.withRequiredMethodInfoFulfilled(false)
.withErrorMessage("Only signature algorithm rsa-sha256 is supported.")
.withResponseCode(javax.ws.rs.core.Response.Status.UNAUTHORIZED)
.build();
}
Map<String, String> headers = new HashMap<>();
reqHeaders.entrySet().forEach((entry) -> {
headers.put(entry.getKey().toLowerCase(), String.join(", ", entry.getValue()));
});
Optional<AuthenticateMethodResponse> authenticateMethodResponse = checkRequiredSignedHeaders(signature, "(request-target)", "host", "date|original-date", "digest", "x-request-id");
if (authenticateMethodResponse.isPresent()) {
return authenticateMethodResponse.get();
}
/* if (headers.containsKey("host") && !headers.get("host").equals(requestContext.getUriInfo().getRequestUri().getHost())) {
return AuthenticateMethodResponse.builder()
.withErrorMessage("Host does not match")
.withResponseCode(javax.ws.rs.core.Response.Status.BAD_REQUEST)
.build();
}*/
if (headers.containsKey("x-request-id") &&
!headers.get("x-request-id").matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) {
return AuthenticateMethodResponse.builder()
.withErrorMessage("Authentication with non-canonical X-Request-ID")
.withResponseCode(javax.ws.rs.core.Response.Status.BAD_REQUEST)
.build();
}
if ((headers.containsKey("date") && !isDateWithinTimeThreshold(headers.get("date"))) ||
(headers.containsKey("original-date") && !isDateWithinTimeThreshold(headers.get("original-date")))) {
return AuthenticateMethodResponse.builder()
.withErrorMessage("The date cannot be parsed or the date does not match your server clock within a certain threshold of timeDate.")
.withResponseCode(javax.ws.rs.core.Response.Status.BAD_REQUEST)
.build();
}
try {
if (headers.containsKey("digest")) {
byte[] bodyBytes = getByteArray(requestContext);
final byte[] digest;
try {
digest = MessageDigest.getInstance("SHA-256").digest(bodyBytes);
} catch (NoSuchAlgorithmException e) {
logger.warn("No such algorithm", e);
return AuthenticateMethodResponse.builder()
.withErrorMessage("No such algorithm")
.withResponseCode(javax.ws.rs.core.Response.Status.BAD_REQUEST)
.build();
}
final String digestCalculated = "SHA-256=" + new String(Base64.encodeBase64(digest));
String requestDigest = null;
if (reqHeaders.containsKey("digest")) {
requestDigest = Arrays
.stream(reqHeaders.getFirst("digest").split(","))
.filter(d -> d.startsWith("SHA-256=")).findFirst().orElse(null);
}
if (!digestCalculated.equals(requestDigest)) {
return AuthenticateMethodResponse.builder()
.withErrorMessage("Digest mismatch! calculated (body length: " + bodyBytes.length + "): " + digestCalculated
+ ", header: " + reqHeaders.getFirst("digest"))
.withResponseCode(javax.ws.rs.core.Response.Status.BAD_REQUEST)
.build();
}
}
String fingerprint = signature.getKeyId();
RSAPublicKey publicKey = registryClient.findClientRsaPublicKey(fingerprint);
if (publicKey == null) {
return AuthenticateMethodResponse.builder()
.withErrorMessage("Key not found for fingerprint: " + fingerprint)
.withResponseCode(javax.ws.rs.core.Response.Status.FORBIDDEN)
.build();
}
final Verifier verifier = new Verifier(publicKey, signature);
logger.info("Verifying signature, fingerprint: {}", fingerprint);
String queryParams = requestContext.getUriInfo().getRequestUri().getQuery();
String requestString = requestContext.getUriInfo().getRequestUri().getRawPath() + (queryParams == null ? "" : "?" + queryParams);
boolean verifies = verifier.verify(requestContext.getMethod().toLowerCase(), requestString, headers);
logger.info("Verify with headers {}",headers);
if (!verifies) {
return AuthenticateMethodResponse.builder()
.withErrorMessage("Signature verification: " + verifies)
.withResponseCode(javax.ws.rs.core.Response.Status.UNAUTHORIZED)
.build();
}
requestContext.setProperty("EwpRequestRSAPublicKey", publicKey);
} catch (NoSuchAlgorithmException e) {
logger.warn("No such algorithm", e);
return AuthenticateMethodResponse.builder()
.withErrorMessage("No such algorithm")
.withResponseCode(javax.ws.rs.core.Response.Status.BAD_REQUEST)
.build();
} catch (IOException e) {
logger.warn("Error reading", e);
return AuthenticateMethodResponse.builder()
.withErrorMessage(e.getMessage())
.withResponseCode(javax.ws.rs.core.Response.Status.BAD_REQUEST)
.build();
} catch (SignatureException e) {
logger.warn("Signature error", e);
return AuthenticateMethodResponse.builder()
.withErrorMessage(e.getMessage())
.withResponseCode(javax.ws.rs.core.Response.Status.BAD_REQUEST)
.build();
} catch (MissingRequiredHeaderException e) {
logger.warn("Signature error, missing header", e);
return AuthenticateMethodResponse.builder()
.withErrorMessage(e.getMessage())
.withResponseCode(javax.ws.rs.core.Response.Status.BAD_REQUEST)
.build();
}
return AuthenticateMethodResponse.builder().build();
}