Request Signature Verification

michael.roth's Avatar

michael.roth

20 Jun, 2013 03:12 PM

Hello,

I'm setting up a webhook to check to make sure a transaction has gone through and I'm writing the code to do the verification with my secret key and I just have some questions on the logic. I'm writing my code in C# and I'm not sure what the raw request body is. I've been trying to research it and havent' had much luck. Do you have any C# code examples of how to do the request signature verification or can give me more details on how to retrieve the raw request body.

Thanks
We Are Mammoth

  1. Support Staff 1 Posted by Marc Guyer on 20 Jun, 2013 03:50 PM

    Marc Guyer's Avatar

    Hi Michael -- The raw body is just the content of the HTTP POST request. HTTP POST starts with the headers followed by two newline characters followed by the body content. Normally, this is parsed by the HTTP client automatically when the content type is application/x-www-form-urlencoded. Whatever library/framework you're using should still have access to the POST body in it's raw form. I'm not intimately familiar with c# but I'd like to try to help further. Are you using a framework of some sort?

  2. Support Staff 2 Posted by Marc Guyer on 20 Jun, 2013 03:54 PM

    Marc Guyer's Avatar
  3. 3 Posted by michael.roth on 20 Jun, 2013 03:56 PM

    michael.roth's Avatar

    Thanks, I'll give that a try.

  4. Support Staff 4 Posted by Marc Guyer on 20 Jun, 2013 04:05 PM

    Marc Guyer's Avatar

    Ok, once we have a solution, I hope you can provide a simple example we can use in our docs so others can benefit by our efforts. Please let me know if I can help further.

  5. 5 Posted by michael.roth on 21 Jun, 2013 03:38 PM

    michael.roth's Avatar

    Hey Marc,

    So this is what I have, and it seems like they are not matching up. Am I supposed to do the MD5 hash on the entire request body which is around 4,565 characters long. So here is the code I have and the steps that go along

    Grab The Authorization Header
    var authorizationHeader = request.Headers["X-CG-SIGNATURE"];

    Set The Input Stream The Beginning
    request.InputStream.Seek(0, SeekOrigin.Begin);
    using (var reader = new StreamReader(request.InputStream))
                        {
    Read The Entire Body In
                            var httpBody = reader.ReadToEnd();
    Get The Byte Array of My Secret Key
                            var secretKeyArray = Encoding.ASCII.GetBytes(_secretKey);
    Get MD5 Hash of the Entire Body
                            var md5Array = CalculateMd5Hash(httpBody);
    Build A SHA256 Hash Creator Using My Secret Key as the key
                            var hash = new HMACSHA256(secretKeyArray);
    Get The Hash of The MD5 Hash
                            var secretKeyHash = hash.ComputeHash(md5Array);
    Check Against The Authorization Header
                            if (BitConverter.ToString(secretKeyHash).Replace("-", "").ToLower() != authorizationHeader.ToLower())
                            {
                                throw new Domain.Exceptions.Exception();
                            }
                        }

    public byte[] CalculateMd5Hash(string input)
                {
                    var md5 = MD5.Create();
                    var inputBytes = Encoding.ASCII.GetBytes(input);
                    var hash = md5.ComputeHash(inputBytes);

                    return hash;
                }

  6. Support Staff 6 Posted by Marc Guyer on 21 Jun, 2013 09:43 PM

    Marc Guyer's Avatar

    Hi Michael --

    Am I supposed to do the MD5 hash on the entire request body which is around 4,565 characters long

    Yes. To be clear, it's the request body not including the headers.

    If you're still having trouble getting it match the X-CG-SIGNATURE, I might be able to help further if you post the raw output of each step (i.e., the values of httpBody, md5Array, secretKeyArray, hash, and the value of the X-CG-SIGNATURE of the request you're trying to verify)

  7. 7 Posted by michael.roth on 25 Jun, 2013 03:10 PM

    michael.roth's Avatar

    Hey Marc,

    Here is some of the values I'm getting. The header to check against, the request body, and the final code I'm getting after doing all the hashes and everything. Let me know if this help or if you have any questions.

    Thanks
    Michael

    From: Marc Guyer <[email blocked]<mailto:[email blocked]>>
    Date: Fri, 21 Jun 2013 17:43:49 -0400
    To: Michael Roth <[email blocked]<mailto:[email blocked]>>
    Subject: Re: Request Signature Verification [Questions #6669]

  8. Support Staff 8 Posted by Marc Guyer on 25 Jun, 2013 03:16 PM

    Marc Guyer's Avatar

    What is the result you get from the MD5 hash? It should be a 32-character hexadecimal number.

  9. Support Staff 9 Posted by Marc Guyer on 25 Jun, 2013 03:21 PM

    Marc Guyer's Avatar

    This returns a byte array:

    var hash = md5.ComputeHash(inputBytes);
    

    You then need to convert that to the hex number:

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < hash.Length; i++)
    {
        sb.Append(hash[i].ToString("X2"));
    }
    return sb.ToString();
    
  10. Support Staff 10 Posted by Marc Guyer on 25 Jun, 2013 04:40 PM

    Marc Guyer's Avatar

    I created a quick gist of this based on your work:

    https://gist.github.com/marcguyer/5860026

    I have no way of testing this so please modify the gist or comment here with changes.

  11. Support Staff 11 Posted by Marc Guyer on 27 Jun, 2013 03:33 PM

    Marc Guyer's Avatar

    Hi Michael -- Sorry for the delay. Github Gist comments do not notify anyone, oddly. So, let's keep the discussion here.

    Also, fyi, you can fork the gist into your account and then edit it directly. That's makes it quite easy to see the diff of all the revisions.

    I suppose I forgot a line of code there. It would be easier if I had an environment to test this in but I don't. This is a little like flying blind for me.

    I updated the gist with the meat of your change (I think). Here's a nice diff:

    https://gist.github.com/marcguyer/5860026/revisions

    Thanks for the output text file earlier. That helps a bit but there's a big gap of information between the raw post body and the "Final" output. What's the value of md5String? Which secret key are you using (which product)? So, to be clear, I can better help out if you'll post:

    1. X-CG-Signature Header
    2. HTTP POST raw body
    3. The value of md5String
    4. The product account. Is it Kin (Test)?
    5. The secret key you're using
      • The first few characters is fine if you want to keep it secret.

    Also, would it be cleaner to use this to convert to string instead of that StringBuilder loop?

    return Encoding.ASCII.GetString(hash, 0, hash.Length);
    
  12. 12 Posted by michael.roth on 28 Jun, 2013 01:53 PM

    michael.roth's Avatar

    This comment was split into a new discussion: Reactivation After Expired Trial Auto-Cancel

    Hey Marc,

    I have a question I was wondering if I could get your help on. We're trying to work through a scenario and wanted to get your take on it. So the scenario is that a user signs up for our product on July 1st and gets an invoice built in CG for a billing date of July 14th when his 14 day trial period ends. The user doesn't end up using the product and never inserts his billing information, so on July 14th CG cancels the customer and doesn't run the invoice. Then a month passes by and the user decides that he wants the product now. He re-signs in to our product and inserts his billing information which gets sent to CG. So the previous CG invoice gets run and CG creates the recurring next invoice for a bill date of the next year. Our question is when that previous invoice gets runs does the next invoice get a billing date of a July 14th 2014, which is a year from the bill date of the first invoice, or is it a year from the day that the invoice got ran, which was August 1st. For our situation we would want the next invoice bill date to be a year from when the invoice ran, so August 1st 2014, not July 1st 2014. If you could give us some guidance on what the dates will be set to and what we might do to update the dates that would be great.

    Thanks again for the help,
    Michael

  13. Jess Pendley closed this discussion on 21 Nov, 2013 07:44 PM.

Discussions are closed to public comments.
If you need help with Cheddar please start a new discussion.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac

Recent Discussions

28 Mar, 2024 10:45 PM
24 Jan, 2024 08:33 AM
11 Jan, 2024 07:13 AM
30 Nov, 2023 02:07 AM
22 Nov, 2023 08:41 AM