0

Our user recieve emails with a prepared hyperlink.

This hyperlink has a parameter.

When the user clicks the hyperlink I need to make sure that the user did not tamper with the parameter.

The parameter is a simple integer.

  • I would like to create a hash from the integer.
  • I would like to sign the hash.

What are the current .NET classes I should use for this task?

Pascal
  • 12,265
  • 25
  • 103
  • 195

2 Answers2

2

The easiest way to do this is use a HMAC ("keyed-hash message authentication code").

public static string CreateHMAC(int data, byte[] key)
{
    using(var hmac = new HMACSHA1(key))
    {
        var dataArray = BitConverter.GetBytes(data);
        var resultArray = hmac.ComputeHash(dataArray);
        return Convert.ToBase64String(resultArray);
    }
}

You keep key secret on your server, and pass data and the result of CreateHMAC to the user in the URL. When the user clicks the link you verify that the data was not modified.

public static bool VerifyHMAC(int data, byte[] key, string verification)
{
    using(var hmac = new HMACSHA1(key))
    {
        var dataArray = BitConverter.GetBytes(data);
        var computedHash = hmac.ComputeHash(dataArray);
        var verificationHash = Convert.FromBase64String(verification);

        for (int i = 0; i < verificationHash.Length; i++)
        {
            if (computedHash[i] != verificationHash[i])
            {
                return false;
            }
        }
        return true;
    }
}
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
  • Now that I have some code before me, I googled again for HMACSHA1 and found this what I did not find before: https://msdn.microsoft.com/de-de/library/system.security.cryptography.hmacsha1(v=vs.110).aspx Thanks Scott! The BitConverter was what I searched for! – Pascal Jan 06 '16 at 22:32
  • 1
    Even though SHA1 is considered dangerous in many contexts, it is safe to use it in HMAC. However if some security auditor complains (not all security auditors know much about crypto), then just use [HMAC-SHA256](https://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha256%28v=vs.110%29.aspx) instead. – TheGreatContini Jan 06 '16 at 23:28
  • In what form (data type) would you save the key on the server? Just do sth like pseudocode: Convert.ToBase64String-Methode (var key = new Byte[32]). Save the byte array as base64 string? – Pascal Jan 07 '16 at 21:17
  • Well, it depends on how you want to do it. If you are storing it in a SQL server I would just leave it as a `byte[]` in C# and a `varbinary` in SQL. If you are just using one global key that never changes it could just be hardcoded as a `byte[]` right in the program as `new byte[] { 0x01, 0x5d, ...` – Scott Chamberlain Jan 07 '16 at 21:31
  • When I put on the server I would prefer a string. You have the storedHash in your code but its declared nowwhere. Is that a type from the MS sample? Do you mean maybe verificationHash.Length instead of storedHash.Length? – Pascal Jan 07 '16 at 21:33
  • Yes, it was copied and pasted from the MS sample, it should have been `verificationHash.Length`. For storing the key as a string just do `byte[] key = Convert.FromBase64String(YourKeyStringHere)`. – Scott Chamberlain Jan 07 '16 at 21:34
  • I guess you mean string keyToStore = Convert.ToBase64String(keyArray) ;-) – Pascal Jan 07 '16 at 21:36
  • I was talking about reading it after you have saved it, but yes, that is how you would make the string in the first place. – Scott Chamberlain Jan 07 '16 at 21:38
  • ok thanks Scott again. I wrote some unit tests and they are all green ;-) – Pascal Jan 07 '16 at 21:45
  • Is it bad/weak from a security standpoint that I generate my key like this new byte[64] because each byte is a zero! Is there a better way I can generate a byte sequence? I could do => _RNGCryptoServiceProvider.GetBytes(key); Would you advise me to do that? – Pascal Jan 07 '16 at 22:21
  • Yes, `RNGCryptoServiceProvider.GetBytes(key)` is a very good way to generate a random key. – Scott Chamberlain Jan 07 '16 at 22:24
0

You can see here how to calculate the hash.

Since HASH functions accepts only ARRAYS, I advice you to create an array of ONE single item, with your integer there.

You may "sign" the input calculating the HASH of the calculated HASH above PLUS a constant of your application (or date and hour, for instance)

David BS
  • 1,822
  • 1
  • 19
  • 35