0

I am attempting to use this process to hash data in custom policy: https://learn.microsoft.com/en-us/azure/active-directory-b2c/general-transformations#hash

I need to hash data the same way in c# that will be sent as claims to the policy, and then will use custom policy to hash the same data, and then will compare in custom policy that the hashes match. However, when I hash the data using c# using the following code snipet and then try to hash the data in the policy, the hashes are not matching. Im looking for the method I can use in C# that the custom policy is using to hash the data?

       var saltedClaim = string.Concat(text, salt);
     byte[] saltedClaimAsBytes = Encoding.UTF8.GetBytes(saltedClaim);
     byte[] keyAsBytes = Encoding.UTF8.GetBytes(key);
     using (HMACSHA256 hmac = new HMACSHA256(keyAsBytes))
     {
                 // Compute the hash 
         byte[] hashValue = hmac.ComputeHash(saltedClaimAsBytes);
        return Convert.ToBase64String(hashValue);
     }
heather
  • 21
  • 3
  • The padding mode is wrong(see : https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.hmacsha256.-ctor?view=net-5.0). Says : The key can be any length. However, the recommended size is 64 bytes. If the secret key is more than 64 bytes long, it will be hashed (using SHA-256) to derive a 64-byte key. If it is less than 64 bytes long, it will be padded to 64 bytes. – jdweng Apr 26 '21 at 13:39
  • Hi @jdweng ,The key is 16 characters long. I would think that would be plenty long enough – heather Apr 26 '21 at 14:37
  • To get same hash, the hash calculation (including key size) in the policy has to be the same as in c#. – jdweng Apr 26 '21 at 14:49
  • its using the same key and the same salt. It must be hashing differently though in the policy, and that is what I was hoping to find out. :) – heather Apr 26 '21 at 15:22

3 Answers3

2

Microsoft documentation lacks some essential information for this claim transformation. Doing a SHA456 of the concatenation of "Secret key", "plain text" and "salt" in that order before converting to a base64 worked for me. Here is a working C# example:

using System.Security.Cryptography;

string textToBeHashed = "myText";
string salt = "mySalt";
string secretKey = "mySecret";

string assembledClaim = string.Concat(secretKey, textToBeHashed, salt); 

using (SHA256 sha256Hash = SHA256.Create())
{
    byte[] bytes = sha256Hash.ComputeHash(System.Text.Encoding.UTF8.GetBytes(assembledClaim));
    string hashResult = System.Convert.ToBase64String(bytes);
}
Gali12345
  • 21
  • 3
0

Please use SHA256 instead of HMACSHA256 and it will solve your issue.

Reference: https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.sha256?view=net-5.0

Algorithms are different in SHA256 Vs HMACSHA256.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Jit_MSFT
  • 134
  • 4
0

Ran into the same issue and answer doesn't quite give you all the answers:

$saltedClaim = "<AzureSecret/key><plaintext><salt>"
$saltedClaimAsBytes = [System.Text.Encoding]::UTF8.GetBytes($saltedClaim);
$hasher = [System.Security.Cryptography.HashAlgorithm]::Create('sha256')
$hashValue = $hasher.ComputeHash($saltedClaimAsBytes);
[Convert]::ToBase64String($hashValue);
Nic
  • 71
  • 7