C#PHP SHA-256哈希返回不同的值,但SHA-1和base64不会

时间:2020-08-16 19:42:08

标签: c# php hash sha256

我正在为我的游戏(服务器和客户端)制作后端系统。我使用以下代码生成签名的第一部分(此部分已损坏):

    #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);
    }

这是加密类:

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);
    }
}

服务器通过使用相同的散列和相同的数据来验证数据,并最终检查生成的签名是否等于输入的签名。这是CreateFirstHash()函数的服务器实现:

    #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);
    }

所有来自输入的数据都是相同的(手动检查)。这是调试(逐步操作)中相同的列表:

  • 组合字符串:相同
  • 组合字符串的SHA-1哈希:相同
  • 编码网址:相同
  • 纯文本:相同
  • 最终SHA-256哈希:无效

谁能知道哪里出了问题,我该如何使之有效?

编辑1 添加了示例输入数据。

1 个答案:

答案 0 :(得分:0)

感谢添加一些示例数据,但由于某些功能缺少,您的C#代码未直接运行。

我运行您的PHP代码,并可以将输入提取到SHA256函数中:

plainString: d4a1466c15dc46dd6f7533b172313660eab1aba5:aHR0cHM6Ly9leGFtcGxlLmNvbS9hcGkvdGVzdC9leGFtcGxlLnBocA==:ACBANE8AX98FT7JY6YVWKAMTMJHMYH3E2C582FCYJBTQLU4UZVSJ2E67CPB7BG75NDASGS3BAMR34UVUZN2SSPCV35A8VJPKPPCGGVEH5U9JM47GLUKRZSH3T65MBVZ2RY78C69ZGMC7JG998HRBY6U9TLQH6JDCVRE5YAR8D3TUJ3H2LBE2C598M7VNDSME5WM2YX2449Q8Z923QWGPFLCXXXCC4CETTKUJ28RYSHN372WP2KCXH6V7ZNZNJRAE

使用此输入,PHP-SHA256为:

hash: dced08719b7da56f69f70204122a498f5eda5090ad6b5a90691eb73731cc4c15

使用在线工具(https://emn178.github.io/online-tools/sha256.html)测试plainString值会得到相同的结果:

dced08719b7da56f69f70204122a498f5eda5090ad6b5a90691eb73731cc4c15

最后但并非最不重要的一点是,我在修复缺失的问题后测试了SHA256的C#实现

byte[] inputBytes = **enc.GetBytes**(input);

得到结果:

dced08719b7da56f69f70204122a498f5eda5090ad6b5a90691eb73731cc4c15

所以最后-C#和PHP之间的SHA256结果没有没有差异

相关问题