Search code examples
c#youtube-apiyoutube-data-apisha1hmac

Youtube Pubsub Validate signature


I am creating an open Source Project which uses the youtube pubsub api to get notifications on video uploads. I want to verify that the request does come from youtube and not from a 3rd Party by checking the HMAC SHA1 Signature as described.

So, every time 1 Run my Program, I will generate a Secret later, to debug the problem, i use "test" as my secret string.

I use the following method to check if the provided signature is valid

    public static bool Check(string body, string signature)
    {
        using (var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(Secret)))
        {
            var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(body));
            var hash = Encoding.UTF8.GetString(hashBytes);
            Console.WriteLine("Computed Hash " + hash);
            return signature.Equals(hash);
        }
    }

Where body is the request body and signature is a value provided in the request header. According to https://pubsubhubbub.github.io/PubSubHubbub/pubsubhubbub-core-0.4.html#rfc.section.7

If the subscriber supplied a value for hub.secret in their subscription request, the hub MUST generate an HMAC signature of the payload and include that signature in the request headers of the content distribution request. The X-Hub-Signature header's value MUST be in the form sha1=signature where signature is a 40-byte, hexadecimal representation of a SHA1 signature [RFC3174]. The signature MUST be computed using the HMAC algorithm [RFC2104] with the request body as the data and the hub.secret as the key.

I supply my Secret as hub.secret in my subscription request. So if I understand it correctly, the hub SHOULD use that secret to generate a HMACSHA1 of the payload -> the body. I want to regenerate the HMAC and should get the same value, right? It does not work. Also the computed hash value logged by console.WriteLine is something completely different, not alphabetic characters at all, so I guess it might be a problem with the encoding, but I can't figure it out. Thanks for all the help!


Solution

  • The documentation says "where signature is a 40-byte, hexadecimal representation" so instead of converting hashBytes to an UTF8 string you should convert it to a hexadecimal string.

    public static bool Check(string body, string signature)
    {
        using (var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(Secret)))
        {
            var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(body));
            var hash = Convert.ToHexString(hashBytes).ToLowerInvariant();
            Console.WriteLine("Computed Hash " + hash);
            return signature.Equals(hash);
        }
    }