Skip to content

Instantly share code, notes, and snippets.

@esabook
Last active January 19, 2020 09:14
Show Gist options
  • Save esabook/840d7c92a1db56e665d8ed7cf21a0e75 to your computer and use it in GitHub Desktop.
Save esabook/840d7c92a1db56e665d8ed7cf21a0e75 to your computer and use it in GitHub Desktop.
HMAC signer for http req
/*Request
1. Date Format RFC1123 (Sun, 06 Nov 1994 08:49:37 UTC)
2. Request Line (POST /v1/account/check HTTP/1.1)
Signature
signing_string = ‘date: Sun, 06 Nov 1994 08:49:37 UTC\nPOST /v1/account/check HTTP/1.1’
digest=HMAC-SHA256(signing_string)
signature=BASE64(digest)
Body
{
“bank_id”: ”45”,
“account_number”: “234398045983”
}
value=SHA-256(body)
Digest=BASE64(value)
Final Header
Date: Sun, 06 Nov 1994 08:49:37 UTC
Authorization: "hmac username=\"myun\", algorithm=\"hmac-sha256\", headers=\"date request-line\", signature=\"%s\"", signature
Digest: SHA-256=Digest
*/
/**
* example usage:
* try {
* HttpSignatureUtils httpSignatureUtils = new HttpSignatureUtils();
* request = httpSignatureUtils.mergeToRequest(request, requestObject.toString());
*
* }catch (Exception e){
* e.printStackTrace();
* }
*/
public class HttpSignatureUtils {
final static String SECRET_HMAC = BuildConfig.SECRET_HMAC;
final static String DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z";
final static String AUTH_FORMAT = "\"hmac username=\"myun\", algorithm=\"hmac-sha256\", headers=\"date request-line\", signature=\"%s\"\"";
final static String DIGEST_FORMAT = "SHA-256=%s";
Date mDate = new Date();
public Request mergeToRequest(Request request, String json) throws Exception {
String auth = String.format(AUTH_FORMAT, getSignatureEncodedBase64(request));
String date = getFormattedDateFormat();
String digest = String.format(DIGEST_FORMAT, getEncodedBase64(json));
return request.newBuilder()
.addHeader("Date", date)
.addHeader("Digest", digest)
.addHeader("Authorization", auth).build();
}
/**
* expected format: Sun, 06 Nov 1994 08:49:37 UTC
*
* @return
*/
public String getFormattedDateFormat() {
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
return dateFormat.format(mDate.getTime());
}
/**
* Base64(HMAC-sha256)
* // expected: ‘date: Sun, 06 Nov 1994 08:49:37 UTC\nPOST /v1/account/check HTTP/1.1’
*
* @return
*/
public String getSignature(@NonNull String httpMethod, @NonNull String httpUrl) {
String signatureFormated = String.format("date: %s\n%s %s HTTP/1.1",
getFormattedDateFormat(),
httpMethod.toUpperCase(),
httpUrl);
return signatureFormated;
}
public String getSignatureEncodedBase64(Request httpRequest) throws Exception {
return getSignatureEncodedBase64(httpRequest.method(), httpRequest.url().encodedPath());
}
public String getSignatureEncodedBase64(@NonNull String httpMethod, @NonNull String httpUrl)
throws Exception {
String hash = Base64.encodeToString(
getHMAC_SHA256Digest(SECRET_HMAC, getSignature(httpMethod, httpUrl)), Base64.NO_WRAP);
return hash;
}
public byte[] getHMAC_SHA256Digest(String secret, String data)
throws Exception {
String algoritm = "HmacSHA256";
Mac sha256_HMAC = Mac.getInstance(algoritm);
SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(), algoritm);
sha256_HMAC.init(secretKeySpec);
return sha256_HMAC.doFinal(data.getBytes());
}
public String getEncodedBase64(String data) {
byte[] sha256 = DigestUtils.getSha256Digest().digest(data.getBytes());
String hash = Base64.encodeToString(sha256, Base64.NO_WRAP);
return hash;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment