Facebook 实时更新:在 C# 中验证 X-Hub-Signature SHA1 签名

发布于 2024-10-06 20:29:05 字数 1187 浏览 0 评论 0原文

当 Facebook 发送实时更新时,它们会在 HTTP 标头中包含 X-Hub-Signature。根据他们的文档 (http://developers.facebook.com/docs/api/realtime),他们使用 SHA1 和应用程序机密作为密钥。我尝试像这样验证签名:

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('=')[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('/', '_');
    }

但我似乎无法验证此签名。对我做错了什么有什么想法吗?

提前致谢。

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('=')[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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

美男兮 2024-10-13 20:29:05

如果有人需要这些信息:

开尔文提供的可能有用,但看起来很麻烦。
您所需要的只是使用 ConvertToHexadecimal 函数,而不是使用 ToUrlBase64String 函数。

请参阅下面完全更新的代码:

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();
 }

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();
 }
§普罗旺斯的薰衣草 2024-10-13 20:29:05

下面的代码将为您解决问题:

     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;
  }

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;
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文