
dev.shopstack.security.hmac.HmacGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of shopstack-security-hmac Show documentation
Show all versions of shopstack-security-hmac Show documentation
Authenticate Shopify requests using the provided HMAC.
The newest version!
package dev.shopstack.security.hmac;
import dev.shopstack.security.hmac.exception.HmacEncodingException;
import dev.shopstack.security.hmac.exception.HmacGeneratorInitializationException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.BinaryEncoder;
import org.apache.commons.codec.EncoderException;
import org.apache.commons.codec.binary.Base16;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.function.Function;
import static dev.shopstack.security.hmac.Encoding.BASE16;
import static dev.shopstack.security.hmac.Encoding.BASE64;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* Generates a SHA-256 based HMAC (hash-based message authentication code).
*/
@Slf4j
public final class HmacGenerator implements Function {
private static final String HMAC_SHA256 = "HmacSHA256";
private final Mac mac;
private final BinaryEncoder encoder;
public HmacGenerator(final String secret) {
this(secret, BASE64);
}
public HmacGenerator(final String secret, final Encoding encoding) {
this.mac = initMac(secret);
this.encoder = buildEncoder(encoding);
}
/**
* Initialize a new {@link Mac} instance.
*
* @throws HmacGeneratorInitializationException if the HMAC generator cannot be initialized.
*/
private Mac initMac(final String secret) {
try {
Mac mac = Mac.getInstance(HMAC_SHA256);
SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(UTF_8), HMAC_SHA256);
mac.init(keySpec);
return mac;
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
log.error("Unable to initialize the HMAC generator.", e);
throw new HmacGeneratorInitializationException("Unable to initialize the HMAC generator.", e);
}
}
/**
* Generate a new HMAC code for the provided content.
*/
@Override
public String apply(final String content) {
try {
byte[] macData = mac.doFinal(content.getBytes(UTF_8));
return new String(encoder.encode(macData), UTF_8);
} catch (EncoderException e) {
log.error("Unable to encode the HMAC.", e);
throw new HmacEncodingException("Unable to encode the HMAC.", e);
}
}
/**
* Create a suitable {@link BinaryEncoder} instance for the provided {@link Encoding}.
*/
private BinaryEncoder buildEncoder(Encoding encoding) {
if (encoding == BASE16) {
return new Base16(true);
}
return new Base64();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy