С# требуется помощь для создания Facebook AppSecret_Proof HMACSHA256

Facebook требует, чтобы я создал appecret_proof: https://developers.facebook.com/docs/graph-api/securing-requests

И я сделал это, используя следующий код:

public string FaceBookSecret(string content, string key)
{
        var encoding = new System.Text.ASCIIEncoding();
        byte[] keyByte = encoding.GetBytes(key);
        byte[] messageBytes = encoding.GetBytes(content);
        using (var hmacsha256 = new HMACSHA256(keyByte))
        {
            byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
            return Convert.ToBase64String(hashmessage);
        }
}

Все выглядит хорошо для меня, однако в facebook говорится, что appsecret_proof недействителен. Я вошел в систему, я могу сделать все как обычно, когда я удаляю ключ. Поэтому, чтобы сэкономить время:

  • Да, я отправляю правильный URL
  • Да, я передаю действительный access_token
  • Да, я использую тот же access_token в доказательстве, что и я в запросе
  • Да, мои appsecret в порядке, и работает

Пример использования

dynamic results = client.Post("/" + model.PostAsId + "/feed", new { message = model.Message, appsecret_proof = FaceBookSecret(postAs.AuthToken, AppSecret) });

Я думаю, что он, вероятно, имеет какое-то отношение к кодировке или чему-то в этом отношении, но, честно говоря, я просто не знаю.

Я также использую SDK.net SDK, но это мало чем связано с документацией и, похоже, не влияет на автоматизацию, операции на стороне сервера и т.д.

Спасибо

Ответ 1

Секрет приложения - это строка base-16, поэтому вам нужно преобразовать ее в массив байтов. Взгляните на Как преобразовать шестнадцатеричную строку в массив байтов? для получения подробной информации о том, как это сделать. Access_token необходимо преобразовать в массив байтов, используя кодировку ASCII. После того, как вы создали HMAC, затем закодируйте это как строку base-16 для использования в качестве apps apps. Следующий код преобразует массив байтов в base16.

public static class Base16
{
    private static readonly char[] encoding;

    static Base16()
    {
        encoding = new char[16]
        {
            '0', '1', '2', '3', '4', '5', '6', '7',
            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
        };
    }

    public static string Encode(byte[] data)
    {
        char[] text = new char[data.Length * 2];

        for (int i = 0, j = 0; i < data.Length; i++)
        {
            text[j++] = encoding[data[i] >> 4];
            text[j++] = encoding[data[i] & 0xf];
        }

        return new string(text);
    }

Тогда код для создания appsecret_proof будет

private string GenerateAppSecretProof(string accessToken, string appSecret)
{
    byte[] key = Base16.Decode(appSecret);
    byte[] hash;
    using (HMAC hmacAlg = new HMACSHA1(key))
    {
        hash = hmacAlg.ComputeHash(Encoding.ASCII.GetBytes(accessToken));
    }
    return Base16.Encode(hash);
}

Facebook, похоже, принимает либо SHA256 HMAC, либо SHA1 HMAC.

Ответ 2

Я успешно использовал приложение ниже с Facebook

using System.Security.Cryptography;
using System.Text;

internal static string FaceBookSecret(string content, string key)
{
    byte[] keyBytes = Encoding.UTF8.GetBytes(key);
    byte[] messageBytes = Encoding.UTF8.GetBytes(content);
    byte[] hash;
    using (HMACSHA256 hmacsha256 = new HMACSHA256(keyBytes))
    {
        hash = hmacsha256.ComputeHash(messageBytes);
    }

    StringBuilder sbHash = new StringBuilder();
    for (int i = 0; i < hash.Length; i++)
    {
        sbHash.Append(hash[i].ToString("x2"));
    }
    return sbHash.ToString();
}