开发者

Facebook Real-time Update: Validating X-Hub-Signature SHA1 signature in C#

开发者 https://www.devze.com 2023-01-29 18:39 出处:网络
When Facebook sends real-time updates, they include a X-Hub-Signature in the HTTP header. According to their documentation (http://developers.facebook.com/docs/api/realtime), they\'re using SHA1 and t

When Facebook sends real-time updates, they include a X-Hub-Signature in the HTTP header. According to their documentation (http://developers.facebook.com/docs/api/realtime), they're using SHA1 and the application secret as the key. I tried to verify the signature like this:

public void MyAction() {
  string signature = request.Headers["X-Hub-Signature"];
  request.InputStream.Position = 0;
  StreamReader reader = new StreamReader(request.InputStream);
  string json = reader.ReadToEnd();

  var hmac = SignWithHmac(UTF8Encoding.UTF8.GetBytes(json), UTF8Encoding.UTF8.GetBytes("MySecret"));
  var hmacBase64 = ToUrlBase64String(hmac);

  bool isValid = signature.Split('=')开发者_如何学Python[1] == hmacBase64;

}


    private static byte[] SignWithHmac(byte[] dataToSign, byte[] keyBody) {
        using (var hmacAlgorithm = new System.Security.Cryptography.HMACSHA1(keyBody)) {
            hmacAlgorithm.ComputeHash(dataToSign);
            return hmacAlgorithm.Hash;
        }
    }

    private static string ToUrlBase64String(byte[] Input) {
        return Convert.ToBase64String(Input).Replace("=", String.Empty)
                                            .Replace('+', '-')
                                            .Replace('/', '_');
    }

But I can't seem to get this to ever validate. Any thoughts on what I'm doing wrong?

Thanks in advance.


In case someone will need this information:

What Kelvin offered might work, but it seems very cumbersome. All you need is instead of using the ToUrlBase64String function just use the ConvertToHexadecimal function.

See fully updated code below:

public void MyAction() {
    string signature = request.Headers["X-Hub-Signature"];
    request.InputStream.Position = 0;
    StreamReader reader = new StreamReader(request.InputStream);
    string json = reader.ReadToEnd();

    var hmac = SignWithHmac(UTF8Encoding.UTF8.GetBytes(json), UTF8Encoding.UTF8.GetBytes("MySecret"));
    var hmacHex = ConvertToHexadecimal(hmac);

    bool isValid = signature.Split('=')[1] == hmacHex ;

}


private static byte[] SignWithHmac(byte[] dataToSign, byte[] keyBody) {
    using (var hmacAlgorithm = new System.Security.Cryptography.HMACSHA1(keyBody)) {
        return hmacAlgorithm.ComputeHash(dataToSign);
    }
}

private static string ConvertToHexadecimal(IEnumerable<byte> bytes)
{
    var builder = new StringBuilder();
    foreach (var b in bytes)
    {
        builder.Append(b.ToString("x2"));
    }

    return builder.ToString();
 }


The code below will resolve the problem for you:

     public String hmacSha1(String keyString, byte[] in) throws GeneralSecurityException {
        Mac hmac = Mac.getInstance("HmacSHA1");
        int keySize = keyString.length();
        byte[] keyBytes = new byte[keySize];

        for (int i = 0; i < keyString.length(); i++) {
          keyBytes[i] = (byte) keyString.charAt(i);
        }

        Key key = new SecretKeySpec(keyBytes, "HmacSHA1");
        hmac.init(key);
        hmac.update(in);
        byte[] bb = hmac.doFinal();

        StringBuilder v = new StringBuilder();
        for (int i = 0; i < bb.length; i++) {
          int ch = bb[i];
          int d1 = (ch >> 4) & 0xf;
          int d2 = (ch) & 0xf;

          if (d1 < 10) {
            v.append((char) ('0' + d1));
          } else {
            v.append((char) ('a' + d1 - 10));
          }

          if (d2 < 10) {
            v.append((char) ('0' + d2));
          } else {
            v.append((char) ('a' + d2 - 10));
          }
        }
        return v.toString();
      }

  public String callback(HttpServletRequest request) throws IOException {
    InputStream in = request.getInputStream();
    StringBuilder builder = new StringBuilder();
    byte[] buffer = new byte[1024];
    while (in.read(buffer) > 0) {
      builder.append(new String(buffer));
    }
    String signature = request.getHeader("X-Hub-Signature");
    try {
      String signed = subscriptionService.hmacSha1("YOUR_SECRET", builder.toString().getBytes());
      if (signature.startsWith("sha1=") && signature.substring(4).equals(signed)) {
        // process the update
        ....
      }
    } catch (GeneralSecurityException ex) {
      log.warn(ex.getMessage());
    }

    return null;
  }
0

精彩评论

暂无评论...
验证码 换一张
取 消