Search code examples
javafacebook-oauth

Verify hash signature against secret java


I'm trying to convert the php code below to java. I'm having difficulties comparing the hash. Could someone offer some help. Thanks

Example comes from here https://developers.facebook.com/docs/facebook-login/using-login-with-games/#parsingsr

$secret = "appsecret"; // Use your app secret here

// decode the data
$sig = base64_url_decode($encoded_sig);
$data = json_decode(base64_url_decode($payload), true);

// confirm the signature
$expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
if ($sig !== $expected_sig) {

What I've got thus far.

String secret = "somesecret";
String signedRequest = "some.signedrequest";

String[] encoded = signedRequest.split("\\.");

System.out.println(encoded[0]);
System.out.println(encoded[1]);

String signature = base64UrlDecode(encoded[0]);
String payload = base64UrlDecode(encoded[1]);


public static String base64UrlDecode(String input) {
    String result = null;
    Base64 decoder = new Base64(true);
    byte[] decodedBytes = decoder.decode(input);
    result = new String(decodedBytes);
    return result;
}

From here I'm at a loss.

I do not know how to set-up the hash to be compared against my signature.


Solution

  • Get some idea from this, this worked for me.

    import org.apache.commons.codec.binary.Base64;
    import javax.crypto.Mac;
    import javax.crypto.spec.SecretKeySpec;
    
    private JSONObject parseFBSignedRequest(String signedRequest, String secret) throws UnsupportedEncodingException, Exception {
    
    
        //split request into signature and data
        String[] signedRequests = signedRequest.split("\\.", 2);
        //parse signature
        String sig = signedRequests[0];
    
        //parse data and convert to json object
        String data = signedRequests[1];
    
        //I assumed it is UTF8
        JSONObject jsonData = new JSONObject(new String(Base64.decodeBase64(data), "UTF-8"));
        //check signature algorithm
        if(!jsonData.getString("algorithm").equals("HMAC-SHA256")) {
            //unknown algorithm is used
            return null;
        }
    
        //check if data is signed correctly
        if(!hmacSHA256(signedRequests[1], secret).equals(sig)) {
            //signature is not correct, possibly the data was tampered with
            return null;
        }
        return jsonData;
    
    }
    
    //HmacSHA256 implementation 
    private String hmacSHA256(String data, String key) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(secretKey);
        byte[] hmacData = mac.doFinal(data.getBytes("UTF-8"));
        return new String(Base64.encodeBase64URLSafe(hmacData), "UTF-8");
    }