Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: util/src/main/java/edu/sjsu/moth/util/http signature.java #129

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions util/src/main/java/edu/sjsu/moth/util/HttpSignature.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package edu.sjsu.moth.util;

import lombok.extern.apachecommons.CommonsLog;
import org.springframework.http.HttpHeaders;
import org.springframework.web.reactive.function.client.WebClient;

import java.net.URI;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
Expand All @@ -23,6 +19,11 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.springframework.http.HttpHeaders;
import org.springframework.web.reactive.function.client.WebClient;

import lombok.extern.apachecommons.CommonsLog;

/*
* routines to support HTTP Signatures
*
Expand All @@ -34,8 +35,12 @@

@CommonsLog
public class HttpSignature {
private HttpSignature() {
throw new IllegalStateException("This is a utility class. You shouldn't instantiate it.");
}

public static final String REQUEST_TARGET = "(request-target)";
static public final Pattern HTTP_HEADER_FIELDS_PATTERN = Pattern.compile(
public static final Pattern HTTP_HEADER_FIELDS_PATTERN = Pattern.compile(
"(?<key>\\p{Alnum}+)=\"(?<value>([^\"])*)\"");

public static Signature newSigner() {
Expand All @@ -59,11 +64,11 @@ public static MessageDigest newSHA256Digest() {
}

public static WebClient.Builder signHeaders(WebClient.Builder clientBuilder, List<String> headers,
PrivateKey signingKey, String keyUri) {
PrivateKey signingKey, String keyUri) {
clientBuilder.filter((request, next) -> {
try {
String sigLine = generateSignatureHeader(request.method().name(), request.url(), request.headers(),
headers, signingKey, keyUri);
headers, signingKey, keyUri);
request.headers().add("Signature", sigLine);
} catch (InvalidKeyException | SignatureException e) {
log.error("couldn't sign request", e);
Expand All @@ -75,7 +80,7 @@ public static WebClient.Builder signHeaders(WebClient.Builder clientBuilder, Lis
}

static String generateSignatureHeader(String requestMethod, URI requestURI, HttpHeaders requestHeaders,
List<String> headers, PrivateKey signingKey, String keyUri) throws SignatureException, InvalidKeyException {
List<String> headers, PrivateKey signingKey, String keyUri) throws SignatureException, InvalidKeyException {
var toSign = generateHeadersToSign(requestMethod, requestURI, requestHeaders, headers);
var signer = newSigner();
signer.initSign(signingKey);
Expand All @@ -85,7 +90,7 @@ static String generateSignatureHeader(String requestMethod, URI requestURI, Http
}

private static byte[] generateHeadersToSign(String requestMethod, URI requestURI, HttpHeaders requestHeaders,
List<String> headers) {
List<String> headers) {
var toSign = headers.stream().map(h -> {
if (h.equalsIgnoreCase(REQUEST_TARGET)) {
var uri = requestURI;
Expand All @@ -102,15 +107,13 @@ private static byte[] generateHeadersToSign(String requestMethod, URI requestURI
}

public static boolean validateSignatureHeader(String method, URI uri, HttpHeaders headers, String signedHeaders,
PublicKey publicKey, String signature) throws InvalidKeyException,
PublicKey publicKey, String signature) throws InvalidKeyException,
SignatureException {
var toValidate = generateHeadersToSign(method, uri, headers, List.of(signedHeaders.split(" ")));
var signer = newSigner();
String sigLine = null;
signer.initVerify(publicKey);
signer.update(toValidate);
return signer.verify(Base64.getMimeDecoder().decode(signature));

}

public static PublicKey pemToPublicKey(String publicKeyPEM) {
Expand Down Expand Up @@ -147,6 +150,6 @@ public static Map<String, String> extractFields(String sig) {
public static void addDigest(HttpHeaders headers, byte[] body) {
// https://docs.joinmastodon.org/spec/security/ says we should use SHA-256
headers.add("Digest",
"sha-256=%s".formatted(Base64.getMimeEncoder().encodeToString(newSHA256Digest().digest(body))));
"sha-256=%s".formatted(Base64.getMimeEncoder().encodeToString(newSHA256Digest().digest(body))));
}
}
Loading