Unable to validate X-Hub-Signature-256 from webhook

I have set up a github webhook with content type as application/json and have provided a secret. My java code generates the different hash than what github provides. Any help will be highly appreciated. Thanks in advance.

Java code:

private static final String SIGNATURE_PREFIX = "sha256=";
private static final String HMAC_SHA_ALGORITHM = "HmacSHA256";

private boolean validateSignature(String signatureHeader, String payload, String encoding, String secretToken)
            throws UnsupportedEncodingException {

        if (secretToken == null || secretToken.equals("")) {
            LOG.error("webhookSecret not configured. Skip signature validation");
            return false;
        }

        if (!signatureHeader.startsWith(SIGNATURE_PREFIX)) {
            LOG.errorf("Unsupported webhook signature type: {}", signatureHeader);
            return false;
        }
        byte[] signatureHeaderBytes;
        try {
            signatureHeaderBytes = decodeHex(signatureHeader.substring(SIGNATURE_PREFIX.length()).toCharArray());
        } catch (DecoderException e) {
            LOG.errorf("Invalid signature: {}", signatureHeader);
            return false;
        }
        byte[] expectedSignature = getExpectedSignature(payload.getBytes(encoding == null ? "UTF-8" : encoding), secretToken);
        LOG.info("generated signature: "+ bytesToHex(expectedSignature));
        return MessageDigest.isEqual(signatureHeaderBytes, expectedSignature);
    }

    
    private byte[] getExpectedSignature(byte[] payload, String secretToken) {

        SecretKeySpec key = new SecretKeySpec(secretToken.getBytes(), HMAC_SHA_ALGORITHM);
        Mac hmac;
        try {
            hmac = Mac.getInstance(HMAC_SHA_ALGORITHM);
            hmac.init(key);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("Hmac SHA must be supported", e);
        } catch (InvalidKeyException e) {
            throw new IllegalStateException("Hmac SHA must be compatible to Hmac SHA Secret Key", e);
        }
        return hmac.doFinal(payload);
    }

    private static String bytesToHex(byte[] hash) {
        StringBuilder hexString = new StringBuilder(2 * hash.length);
        for (int i = 0; i < hash.length; i++) {
            String hex = Integer.toHexString(0xff & hash[i]);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

    
    public static byte[] decodeHex(final char[] data) throws DecoderException {
        final byte[] out = new byte[data.length >> 1];
        final int outOffset = 0;
        final int len = data.length;

        if ((len & 0x01) != 0) {
            throw new DecoderException("Odd number of characters.");
        }

        final int outLen = len >> 1;
        if (out.length - outOffset < outLen) {
            throw new DecoderException("Output array is not large enough to accommodate decoded data.");
        }

        // two characters form the hex value.
        for (int i = outOffset, j = 0; j < len; i++) {
            int f = toDigit(data[j], j) << 4;
            j++;
            f = f | toDigit(data[j], j);
            j++;
            out[i] = (byte) (f & 0xFF);
        }

        return out;
    }

   
    protected static int toDigit(final char ch, final int index) throws DecoderException {
        final int digit = Character.digit(ch, 16);
        if (digit == -1) {
            throw new DecoderException("Illegal hexadecimal character " + ch + " at index " + index);
        }
        return digit;
    }
1 Like

This is resolved. when I was copying payload it was adding some formatting chars (\n, \t) due to which payload was getting modified. It worked after stripping those.

2 Likes

even after removing formatting chars i couldnt generate correct signature
plz help

@madhumithra Can you share more details such as how you have configured webhooks and code you are using to verify those?

1 Like