Skip to content

Instantly share code, notes, and snippets.

@nickreffitt
Created December 4, 2017 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nickreffitt/0ceb1f1a6f663e9ef3c1ea5aaa43c3d5 to your computer and use it in GitHub Desktop.
Save nickreffitt/0ceb1f1a6f663e9ef3c1ea5aaa43c3d5 to your computer and use it in GitHub Desktop.
A utility class to verify signatures on a publisher's backend when using Tapdaq's Server-Side Rewarded Callbacks
import com.google.common.base.Strings;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class CryptoUtil {
private static final String CHAR_ENCODING = "UTF-8";
private static final String HMAC_ALGORITHM = "HmacSHA256";
public static String calculateBase64EncodedMd5(String contentToEncode) throws NoSuchAlgorithmException, IOException {
MessageDigest digest = MessageDigest.getInstance("MD5");
// Get the MD5 hash:
digest.update(contentToEncode.getBytes(CHAR_ENCODING));
// Base-64 encode the result:
return new String(Base64.encodeBase64(digest.digest()));
}
public static String calculateHmac(String key, String data) throws Exception {
if (Strings.isNullOrEmpty(data)) {
throw new IllegalArgumentException("Data should not be null or empty");
}
Mac sha256_HMAC = Mac.getInstance(HMAC_ALGORITHM);
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(CHAR_ENCODING), HMAC_ALGORITHM);
sha256_HMAC.init(secret_key);
return Hex.encodeHexString(sha256_HMAC.doFinal(data.getBytes(CHAR_ENCODING)));
}
/**
* Re-creates the signature and generates a SHA-256 hash, returning true if the hmac value passed in
* from the request matches, otherwise false.
*
* @param eventId retrieve value from the request params
* @param rewardValue retrieve value from the request params
* @param idfa retrieve value from the request params
* @param httpMethod either POST or GET
* @param date taken from the 'Date' Header value
* @param url the callback URL entered on the dashboard
* @param privateKey the private key used for encryption, entered in the dashboard
* @param receivedHmac the value included in the 'hmac' Header, after the colon 'tapdaq:[this_value]'
* @return
* @throws Exception
*/
public static boolean verifySignature(String eventId, String rewardValue, String idfa,
String httpMethod, String date, String url,
String privateKey, String receivedHmac) throws Exception {
String concatenatedDashboardRequiredFields = eventId + rewardValue + idfa;
String base64EncodedMd5 = calculateBase64EncodedMd5(concatenatedDashboardRequiredFields);
String capitalisedHttpMethod = httpMethod.toUpperCase();
String signature = base64EncodedMd5 + capitalisedHttpMethod + date + url;
String hmac = calculateHmac(privateKey, signature);
return hmac.equals(receivedHmac);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment