I am making backend system for mine game (server & client). I use following code to generate first part of signature (this one is corrupted one):
#example data
string Url = "https://example.com/api/test/example.php";
Dictionary<string, string> RequestBody = new Dictionary<string, string>() { { "example_value", "test" } };
string CreateFirstHash()
{
string Combined = "";
foreach(KeyValuePair<string, string> BodyPart in RequestBody)
{
Combined += BodyPart.Key + "-" + BodyPart.Value + ".";
}
string HashedCombined = Encryption.SHA1(Combined);
string EncodedUrl = Encryption.Base64Encode(this.Url);
string PlainText = HashedCombined + ":" + EncodedUrl + ":" + 'ACBANE8AX98FT7JY6YVWKAMTMJHMYH3E2C582FCYJBTQLU4UZVSJ2E67CPB7BG75NDASGS3BAMR34UVUZN2SSPCV35A8VJPKPPCGGVEH5U9JM47GLUKRZSH3T65MBVZ2RY78C69ZGMC7JG998HRBY6U9TLQH6JDCVRE5YAR8D3TUJ3H2LBE2C598M7VNDSME5WM2YX2449Q8Z923QWGPFLCXXXCC4CETTKUJ28RYSHN372WP2KCXH6V7ZNZNJRAE';
return Encryption.SHA256(PlainText);
}
Here is Encryption class:
using System;
using System.Security.Cryptography;
using System.Text;
public class Encryption
{
private static readonly Encoding enc = Encoding.UTF8;
public static string MD5(string input)
{
byte[] inputBytes = enc.GetBytes(input);
using(System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
byte[] hashBytes = md5.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
foreach(byte hashByte in hashBytes)
{
sb.Append(hashByte.ToString("x2"));
}
return sb.ToString();
}
}
public static string SHA1(string input)
{
byte[] inputBytes = enc.GetBytes(input);
using(SHA1Managed sha = new SHA1Managed())
{
byte[] hashBytes = sha.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
foreach(byte hashByte in hashBytes)
{
sb.Append(hashByte.ToString("x2"));
}
return sb.ToString();
}
}
public static string SHA256(string input)
{
byte[] inputBytes = enc.GetBytes(input);
using (SHA256Managed sha = new SHA256Managed())
{
byte[] hashBytes = sha.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
foreach (byte hashByte in hashBytes)
{
sb.Append(hashByte.ToString("x2"));
}
return sb.ToString();
}
}
public static string SHA512(string input)
{
byte[] inputBytes = enc.GetBytes(input);
using (SHA512Managed sha = new SHA512Managed())
{
byte[] hashBytes = sha.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
foreach (byte hashByte in hashBytes)
{
sb.Append(hashByte.ToString("x2"));
}
return sb.ToString();
}
}
public static string HMAC512(string input, string secret)
{
byte[] inputBytes = enc.GetBytes(input);
byte[] secretBytes = enc.GetBytes(secret);
using(HMACSHA512 hmac = new HMACSHA512(secretBytes))
{
byte[] hashBytes = hmac.ComputeHash(inputBytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
public static string Base64Encode(string input)
{
byte[] inputBytes = Encoding.ASCII.GetBytes(input);
return Convert.ToBase64String(inputBytes);
}
}
Server validates data by making same hash, with the same data and finally checks if generated signature is equal to input one. This is server implementation for CreateFirstHash() function:
#example data
public $requestBody = array('example_value' => 'test');
public $url = 'https://example.com/api/test/example.php';
public $scope = 'game'; #this is not important, you can disregard it
private static function generateFirstHash($requestBody, $url, $scope)
{
$combined = "";
foreach ($requestBody as $key => $value)
{
$combined .= $key . '-' . $value . ".";
}
$combined = sha1($combined);
$encodedUrl = base64_encode($url);
$plainString = $combined . ':' . $encodedUrl . ':' . 'ACBANE8AX98FT7JY6YVWKAMTMJHMYH3E2C582FCYJBTQLU4UZVSJ2E67CPB7BG75NDASGS3BAMR34UVUZN2SSPCV35A8VJPKPPCGGVEH5U9JM47GLUKRZSH3T65MBVZ2RY78C69ZGMC7JG998HRBY6U9TLQH6JDCVRE5YAR8D3TUJ3H2LBE2C598M7VNDSME5WM2YX2449Q8Z923QWGPFLCXXXCC4CETTKUJ28RYSHN372WP2KCXH6V7ZNZNJRAE';
return hash('sha256', $plainString);
}
All data from input were the same (checked manually). This is list what was the same in debug (step by step):
- Combined string: same
- SHA-1 hash of combined string: same
- Encoded URL: same
- Plain text: same
- Final SHA-256 hash: invalid
Can anyone knows what is wrong and how can I make this valid?
Edit 1 Added example input data.