feat: sign JSON Web Token with HmacSHA algorithms
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2024-2025 OnixByte.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.onixbyte.jwt;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public interface TokenCreator {
|
||||
|
||||
String sign(TokenPayload payload);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2024-2025 OnixByte.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.onixbyte.jwt;
|
||||
|
||||
import com.onixbyte.jwt.data.RawTokenComponent;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public interface TokenResolver {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param token
|
||||
*/
|
||||
void verify(String token);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
Map<String, String> getHeader(String token);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param payload
|
||||
* @return
|
||||
*/
|
||||
Map<String, Object> getPayload(String payload);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
RawTokenComponent splitToken(String token);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2024-2025 OnixByte.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.onixbyte.jwt.constant;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public enum Algorithm {
|
||||
HS256(1, 256, "HmacSHA256"),
|
||||
HS384(1, 384, "HmacSHA384"),
|
||||
HS512(1, 512, "HmacSHA512"),
|
||||
RS256(2, 256, "SHA256withRSA"),
|
||||
RS384(2, 384, "SHA384withRSA"),
|
||||
RS512(2, 512, "SHA512withRSA"),
|
||||
ES256(3, 256, "SHA256withECDSA"),
|
||||
ES384(3, 384, "SHA384withECDSA"),
|
||||
ES512(3, 512, "SHA512withECDSA");
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final int HS_FLAG = 1; // 001
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final int RS_FLAG = 2; // 010
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final int ES_FLAG = 3; // 011
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final int typeFlag;
|
||||
private final int shaLength;
|
||||
private final String algorithm;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param typeFlag
|
||||
* @param shaLength
|
||||
* @param algorithm
|
||||
*/
|
||||
Algorithm(int typeFlag, int shaLength, String algorithm) {
|
||||
this.typeFlag = typeFlag;
|
||||
this.shaLength = shaLength;
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isHmac() {
|
||||
return (this.typeFlag & HS_FLAG) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isRsa() {
|
||||
return (this.typeFlag & RS_FLAG) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isEcdsa() {
|
||||
return (this.typeFlag & ES_FLAG) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getShaLength() {
|
||||
return shaLength;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getTypeFlag() {
|
||||
return typeFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2024-2025 OnixByte.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.onixbyte.jwt.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.onixbyte.jwt.TokenCreator;
|
||||
import com.onixbyte.jwt.TokenPayload;
|
||||
import com.onixbyte.jwt.constant.Algorithm;
|
||||
import com.onixbyte.jwt.constant.HeaderClaims;
|
||||
import com.onixbyte.jwt.holder.ObjectMapperHolder;
|
||||
import com.onixbyte.jwt.util.CryptoUtil;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Implementation of {@link TokenCreator} that generates HMAC-signed JSON Web Tokens (JWTs).
|
||||
* <p>
|
||||
* This class uses a specified HMAC algorithm to create signed tokens, incorporating a header,
|
||||
* payload, and signature. It ensures the secret key meets the minimum length requirement for
|
||||
* the chosen algorithm and handles JSON serialisation of the token components.
|
||||
*
|
||||
* @author zihluwang
|
||||
*/
|
||||
public class HmacTokenCreator implements TokenCreator {
|
||||
|
||||
private final Algorithm algorithm;
|
||||
private final String issuer;
|
||||
private final byte[] secret;
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* Constructs an HMAC token creator with the specified algorithm, issuer, and secret key.
|
||||
* <p>
|
||||
* Validates that the secret key length meets the minimum requirement for the chosen algorithm.
|
||||
*
|
||||
* @param algorithm the HMAC algorithm to use for signing (e.g., HS256, HS384, HS512)
|
||||
* @param issuer the issuer identifier to include in the token payload if not already present
|
||||
* @param secret the secret key as a string, used to generate the HMAC signature
|
||||
* @throws IllegalArgumentException if the secret key is shorter than the minimum required
|
||||
* length for the specified algorithm
|
||||
*/
|
||||
public HmacTokenCreator(Algorithm algorithm, String issuer, String secret) {
|
||||
var _minSecretLength = algorithm.getShaLength() >> 3;
|
||||
var secretBytesLength = secret.getBytes(StandardCharsets.UTF_8).length;
|
||||
if (secretBytesLength < _minSecretLength) {
|
||||
throw new IllegalArgumentException("Secret key too short for HS%d: minimum %d bytes required, got %d."
|
||||
.formatted(algorithm.getShaLength(), _minSecretLength, secretBytesLength)
|
||||
);
|
||||
}
|
||||
|
||||
this.algorithm = algorithm;
|
||||
this.issuer = issuer;
|
||||
this.secret = secret.getBytes(StandardCharsets.UTF_8);
|
||||
this.objectMapper = ObjectMapperHolder.getInstance().getObjectMapper();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and signs a JWT using the HMAC algorithm.
|
||||
* <p>
|
||||
* Generates a token by encoding the header and payload as Base64 URL-safe strings,
|
||||
* creating an HMAC signature, and concatenating them with dots. If the payload does not
|
||||
* include an issuer, the configured issuer is added.
|
||||
*
|
||||
* @param payload the {@link TokenPayload} containing claims to include in the token
|
||||
* @return the signed JWT as a string in the format "header.payload.signature"
|
||||
* @throws IllegalArgumentException if the payload cannot be serialised to JSON due to
|
||||
* invalid data or structure
|
||||
* @throws RuntimeException if an unexpected error occurs during JSON processing
|
||||
*/
|
||||
@Override
|
||||
public String sign(TokenPayload payload) {
|
||||
var header = new HashMap<String, String>();
|
||||
|
||||
header.put(HeaderClaims.ALGORITHM, algorithm.name());
|
||||
if (!header.containsKey(HeaderClaims.TYPE)) {
|
||||
header.put(HeaderClaims.TYPE, "JWT");
|
||||
}
|
||||
|
||||
if (!payload.hasIssuer()) {
|
||||
payload.withIssuer(issuer);
|
||||
}
|
||||
|
||||
try {
|
||||
var encodedHeader = Base64.getUrlEncoder().withoutPadding()
|
||||
.encodeToString(objectMapper.writeValueAsBytes(header));
|
||||
var encodedPayload = Base64.getUrlEncoder().withoutPadding()
|
||||
.encodeToString(objectMapper.writeValueAsBytes(payload.getPayload()));
|
||||
|
||||
var signatureBytes = CryptoUtil.createSignatureFor(algorithm,
|
||||
secret,
|
||||
encodedHeader.getBytes(StandardCharsets.UTF_8),
|
||||
encodedPayload.getBytes(StandardCharsets.UTF_8));
|
||||
var signature = Base64.getUrlEncoder()
|
||||
.withoutPadding()
|
||||
.encodeToString((signatureBytes));
|
||||
|
||||
return "%s.%s.%s".formatted(encodedHeader, encodedPayload, signature);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new IllegalArgumentException("Failed to serialise token header or payload to JSON.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (C) 2024-2025 OnixByte.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.onixbyte.jwt.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.onixbyte.jwt.TokenResolver;
|
||||
import com.onixbyte.jwt.constant.Algorithm;
|
||||
import com.onixbyte.jwt.constant.RegisteredClaims;
|
||||
import com.onixbyte.jwt.data.RawTokenComponent;
|
||||
import com.onixbyte.jwt.holder.ObjectMapperHolder;
|
||||
import com.onixbyte.jwt.util.CryptoUtil;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Implementation of {@link TokenResolver} that resolves and verifies HMAC-signed JSON Web
|
||||
* Tokens (JWTs).
|
||||
* <p>
|
||||
* This class splits a JWT into its components, verifies its signature using an HMAC algorithm, and
|
||||
* deserialises the header and payload into usable data structures. It ensures the secret key meets
|
||||
* the minimum length requirement for the specified algorithm.
|
||||
*
|
||||
* @author zihluwang
|
||||
*/
|
||||
public class HmacTokenResolver implements TokenResolver {
|
||||
|
||||
private final Algorithm algorithm;
|
||||
private final byte[] secret;
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* Constructs an HMAC token resolver with the specified algorithm and secret key.
|
||||
* <p>
|
||||
* Validates that the secret key length meets the minimum requirement for the chosen algorithm.
|
||||
*
|
||||
* @param algorithm the HMAC algorithm used for signature verification (e.g., HS256,
|
||||
* HS384, HS512)
|
||||
* @param secret the secret key as a string, used to verify the HMAC signature
|
||||
* @throws IllegalArgumentException if the secret key is shorter than the minimum required
|
||||
* length for the specified algorithm
|
||||
*/
|
||||
public HmacTokenResolver(Algorithm algorithm, String secret) {
|
||||
var _minSecretLength = algorithm.getShaLength() >> 3;
|
||||
var secretBytesLength = secret.getBytes(StandardCharsets.UTF_8).length;
|
||||
if (secretBytesLength < _minSecretLength) {
|
||||
throw new IllegalArgumentException("Secret key too short for HS%d: minimum %d bytes required, got %d"
|
||||
.formatted(algorithm.getShaLength(), _minSecretLength, secretBytesLength)
|
||||
);
|
||||
}
|
||||
|
||||
this.algorithm = algorithm;
|
||||
this.secret = secret.getBytes(StandardCharsets.UTF_8);
|
||||
this.objectMapper = ObjectMapperHolder.getInstance().getObjectMapper();
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits a JWT into its raw components: header, payload, and signature.
|
||||
*
|
||||
* @param token the JWT string to split
|
||||
* @return a {@link RawTokenComponent} containing the header, payload, and signature as strings
|
||||
* @throws IllegalArgumentException if the token does not consist of exactly three parts
|
||||
* separated by dots
|
||||
*/
|
||||
@Override
|
||||
public RawTokenComponent splitToken(String token) {
|
||||
var tokenTuple = token.split("\\.");
|
||||
|
||||
if (tokenTuple.length != 3) {
|
||||
throw new IllegalArgumentException(
|
||||
"The provided JWT is invalid: it must consist of exactly three parts separated by dots.");
|
||||
}
|
||||
|
||||
return new RawTokenComponent(tokenTuple[0], tokenTuple[1], tokenTuple[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the HMAC signature of the provided JWT.
|
||||
* <p>
|
||||
* Splits the token into its components and uses the configured algorithm and secret to check
|
||||
* the signature's validity. If the signature does not match, an exception is thrown by the
|
||||
* underlying cryptographic utility.
|
||||
*
|
||||
* @param token the JWT string to verify
|
||||
* @throws IllegalArgumentException if the token is malformed or the signature verification
|
||||
* fails due to an invalid algorithm, key, or
|
||||
* mismatched signature
|
||||
*/
|
||||
@Override
|
||||
public void verify(String token) {
|
||||
var _token = splitToken(token);
|
||||
|
||||
var isValid = CryptoUtil.verifySignatureFor(algorithm,
|
||||
secret,
|
||||
_token.header(),
|
||||
_token.payload(),
|
||||
_token.signature().getBytes(StandardCharsets.UTF_8)
|
||||
);
|
||||
if (!isValid) throw new IllegalArgumentException(
|
||||
"JWT signature verification failed: the token may be tampered with or invalid.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the header claims from the provided JWT.
|
||||
* <p>
|
||||
* Decodes the Base64-encoded header and deserialises it into a map of strings.
|
||||
*
|
||||
* @param token the JWT string from which to extract the header
|
||||
* @return a map containing the header claims as key-value pairs
|
||||
* @throws IllegalArgumentException if the token is malformed or the header cannot be
|
||||
* deserialised due to invalid JSON format
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> getHeader(String token) {
|
||||
var _token = splitToken(token);
|
||||
|
||||
var headerBytes = Base64.getDecoder().decode(_token.header());
|
||||
var headerJson = new String(headerBytes);
|
||||
|
||||
try {
|
||||
return objectMapper.readValue(headerJson, new TypeReference<>() {
|
||||
});
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Failed to deserialise JWT header: the header JSON is invalid or malformed.", e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the payload claims from the provided JWT, excluding registered claims.
|
||||
* <p>
|
||||
* Decodes the Base64-encoded payload, deserialises it into a map, and removes any registered
|
||||
* claims as defined in {@link RegisteredClaims}.
|
||||
*
|
||||
* @param token the JWT string from which to extract the payload
|
||||
* @return a map containing the custom payload claims as key-value pairs
|
||||
* @throws IllegalArgumentException if the token is malformed or the payload cannot be
|
||||
* deserialised due to invalid JSON format
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> getPayload(String token) {
|
||||
var _token = splitToken(token);
|
||||
|
||||
var payloadBytes = Base64.getDecoder().decode(_token.payload());
|
||||
var payloadJson = new String(payloadBytes);
|
||||
|
||||
try {
|
||||
var payloadMap = objectMapper.readValue(payloadJson, new TypeReference<Map<String, Object>>() {
|
||||
});
|
||||
|
||||
payloadMap.keySet().removeIf(RegisteredClaims.VALUES::contains);
|
||||
return payloadMap;
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Failed to deserialise JWT payload: the payload JSON is invalid or malformed.", e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2024-2025 OnixByte.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.onixbyte.jwt.util;
|
||||
|
||||
import com.onixbyte.jwt.constant.Algorithm;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* Utility class for cryptographic operations related to JWT processing.
|
||||
* <p>
|
||||
* Provides methods for creating and verifying signatures using specified algorithms, primarily for
|
||||
* JSON Web Token (JWT) authentication purposes.
|
||||
*
|
||||
* @author zihluwang
|
||||
*/
|
||||
public final class CryptoUtil {
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation of this utility class.
|
||||
*/
|
||||
private CryptoUtil() {
|
||||
}
|
||||
|
||||
private static final byte JWT_PART_SEPARATOR = (byte) 46;
|
||||
|
||||
/**
|
||||
* Creates a signature for the given header and payload using the specified algorithm
|
||||
* and secret.
|
||||
*
|
||||
* @param algorithm the cryptographic algorithm to use (e.g., HMAC-SHA256)
|
||||
* @param secret the secret key bytes used for signing
|
||||
* @param header the header bytes to include in the signature
|
||||
* @param payload the payload bytes to include in the signature
|
||||
* @return the generated signature bytes
|
||||
* @throws IllegalArgumentException if the algorithm is not supported or the key is invalid
|
||||
*/
|
||||
public static byte[] createSignatureFor(
|
||||
Algorithm algorithm,
|
||||
byte[] secret,
|
||||
byte[] header,
|
||||
byte[] payload) {
|
||||
try {
|
||||
final var mac = Mac.getInstance(algorithm.getAlgorithm());
|
||||
mac.init(new SecretKeySpec(secret, algorithm.getAlgorithm()));
|
||||
mac.update(header);
|
||||
mac.update(JWT_PART_SEPARATOR);
|
||||
return mac.doFinal(payload);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new IllegalArgumentException("The provided secret key is invalid for the algorithm '%s'."
|
||||
.formatted(algorithm.getAlgorithm()), e);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalArgumentException("The specified algorithm '%s' is not supported."
|
||||
.formatted(algorithm.getAlgorithm()), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the signature for the given header and payload using the specified algorithm
|
||||
* and secret.
|
||||
* <p>
|
||||
* This method converts the header and payload strings to UTF-8 bytes before verification.
|
||||
*
|
||||
* @param algorithm the cryptographic algorithm used for signing
|
||||
* @param secretBytes the secret key bytes used for signing
|
||||
* @param header the header string to verify
|
||||
* @param payload the payload string to verify
|
||||
* @param signatureBytes the signature bytes to check against
|
||||
* @return {@code true} if the signature is valid, {@code false} otherwise
|
||||
* @throws IllegalArgumentException if the algorithm is not supported or the key is invalid
|
||||
*/
|
||||
public static boolean verifySignatureFor(
|
||||
Algorithm algorithm,
|
||||
byte[] secretBytes,
|
||||
String header,
|
||||
String payload,
|
||||
byte[] signatureBytes) {
|
||||
return verifySignatureFor(
|
||||
algorithm,
|
||||
secretBytes,
|
||||
header.getBytes(StandardCharsets.UTF_8),
|
||||
payload.getBytes(StandardCharsets.UTF_8),
|
||||
signatureBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the signature for the given header and payload bytes using the specified algorithm
|
||||
* and secret.
|
||||
*
|
||||
* @param algorithm the cryptographic algorithm used for signing
|
||||
* @param secretBytes the secret key bytes used for signing
|
||||
* @param headerBytes the header bytes to verify
|
||||
* @param payloadBytes the payload bytes to verify
|
||||
* @param signatureBytes the signature bytes to check against
|
||||
* @return {@code true} if the signature matches, {@code false} otherwise
|
||||
* @throws IllegalArgumentException if the algorithm is not supported or the key is invalid
|
||||
*/
|
||||
public static boolean verifySignatureFor(
|
||||
Algorithm algorithm,
|
||||
byte[] secretBytes,
|
||||
byte[] headerBytes,
|
||||
byte[] payloadBytes,
|
||||
byte[] signatureBytes) {
|
||||
return MessageDigest.isEqual(
|
||||
createSignatureFor(
|
||||
algorithm,
|
||||
secretBytes,
|
||||
headerBytes,
|
||||
payloadBytes),
|
||||
signatureBytes);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user