使用 ASP.NET MVC 为 Lemon Squeezy X-Signature 创建哈希

问题描述 投票:0回答:1

以下函数用于接收 Lemon Squeezy webhook 请求:

public ActionResult lsHook(LemonsqueezyWebhook lemonsqueezyWebhook)
{
...
}

就有效负载数据而言,它按预期工作。 Lemon Squeezy 使用 X-Signature 来帮助确认请求实际上来自 Lemon Squeezy,而不是网络钓鱼网站。以下是他们的代码示例:

$secret    = '[SIGNING_SECRET]'; // from your webhook settings
$payload   = file_get_contents('php://input');
$hash      = hash_hmac('sha256', $payload, $secret);
$signature = $_SERVER['HTTP_X_SIGNATURE'] ?? '';

if (!hash_equals($hash, $signature)) {
    throw new Exception('Invalid signature.');
}

这是我的 C# 代码,用于在

ActionResult lsHook(LemonsqueezyWebhook lemonsqueezyWebhook)
中执行相同操作:

StringBuilder sb = new StringBuilder("X-Signature")
if (Request.Headers.AllKeys.Contains("X-Signature"))
{
    foreach (string sValue in Request.Headers.GetValues("X-Signature"))
    {
        sb.Append(Environment.NewLine).Append(sValue);
    }
    Request.InputStream.Seek(0, SeekOrigin.Begin);
    string sPayload = new StreamReader(Request.InputStream).ReadToEnd();
    using (var sha256 = SHA256.Create())
    {
        byte[] payloadBytes = Encoding.UTF8.GetBytes(sPayload);
        byte[] secretBytes = Encoding.UTF8.GetBytes("mysecret");

        // Combine payload and secret
        byte[] data = payloadBytes.Concat(secretBytes).ToArray();

        // Hash the combined data
        byte[] hash = sha256.ComputeHash(data);
        
        sb.Append(Environment.NewLine + "hash: ").Append(BitConverter.ToString(hash).Replace("-", "").ToLower());
    }
}

这是我从一个对某人的请求中得到的信息:

      dab5a3c5f205f60aa09ab00098f67917e8fcc6b05e64d510b656d82f35bca97c
hash: 3ee77ac08f050e1338ca3a4a8c0162eb8ff9aa1fb7d89418881492a52da1cc37

它们不匹配。

sPayload
看起来正确。它是 json 对象。谁能提供有关可能原因的提示吗?

更新:

var sha256 = SHA256.Create()
替换为
var sha256 = HMACSHA256.Create()
后,我得到以下结果:

      10de6aa343a95017309a7e7d3b683fb35afa4be9f67c41c2d87ae1f9872e0914
hash: 9dceac34439623bff6549b2dd264672e0cc20910
c# hash asp.net-mvc-5 cryptography
1个回答
0
投票

发布的代码中的错误是C#代码仅计算SHA256值而不是HMAC/SHA56值。
修复此问题后,密钥未正确指定,并且应用了

Create()
方法,该方法需要指定摘要,但缺少摘要。


确定 HMAC/SHA256 可以在 .NET 上使用

HMASCSHA256
实现如下:

using System;
using System.Security.Cryptography;
using System.Text;
...
byte[] secret = Encoding.UTF8.GetBytes("some secret");
byte[] payload = Encoding.UTF8.GetBytes("some payload");
using (var hmacSha256 = new HMACSHA256(secret)) 
{
    byte[] hash = hmacSha256.ComputeHash(payload);
    Console.WriteLine(Convert.ToHexString(hash)); // 22A2E09F97E933DB48BA6EF24C6BE11A5A10024BD9A6A18E662E94BF3C35F257
}

密钥当然也可以稍后设置:

...
using (var hmacSha256 = new HMACSHA256()) 
{
    hmacSha256.Key = secret;
    byte[] hash = hmacSha256.ComputeHash(payload);
    Console.WriteLine(Convert.ToHexString(hash)); // 22A2E09F97E933DB48BA6EF24C6BE11A5A10024BD9A6A18E662E94BF3C35F257
}
...

请注意,

HMACSHA256.Create()
不适用于.NET 5+(System.PlatformNotSupportedException:此平台不允许自动选择算法)。
在 .NET Framework 上它可以工作,但默认返回 HMAC/SHA1 值:

...
using (var hmacSha256 = HMACSHA256.Create()) 
{
     hmacSha256.Key = secret;
     byte[] hash = hmacSha256.ComputeHash(payload);
     Console.WriteLine(ByteArrayToString(hash)); // FF81B9A37F9DA6EA0DE2CFF78216B697722E9A08
}
...

这可能是您环境中哈希值较短的原因。为了使用 HMAC/SHA256,必须明确指定:

...
using (var hmacSha256 = HMACSHA256.Create("HMACSHA256"))
{
    hmacSha256.Key = secret;
    byte[] hash = hmacSha256.ComputeHash(payload);
    Console.WriteLine(ByteArrayToString(hash)); // 22A2E09F97E933DB48BA6EF24C6BE11A5A10024BD9A6A18E662E94BF3C35F257
}
...

原因是

HMACSHA256.Create()
调用了
HMAC.Create()
,后者需要摘要的规范。
由于
new HMACSHA256()
适用于所有环境,因此使用它可能是最可靠的(根据文档中的 example)。

© www.soinside.com 2019 - 2024. All rights reserved.