在 .NET Framework 的 WCF Web 服务中验证 HMAC 签名

Verify HMAC signature in WCF web service in .NET Framework

提问人:Pavel 提问时间:9/20/2023 最后编辑:Pavel 更新时间:9/20/2023 访问量:83

问:

我正在尝试在 WCF Web 服务中实现 HMAC 安全性,但很难验证 HMAC 签名。我正在使用 .NET Framework 4.8。

我在这里关注 DocuSign API 文档:
https://developers.docusign.com/platform/webhooks/connect/validate/

他们的文档提供了代码示例,特别是在“步骤 2:验证 HMAC 签名”中:

using System;
using System.Text;
using System.Security.Cryptography;

public static class HMACValidation
{
    public static string ComputeHash(string secret, string payload)
    {
        byte[] bytes = Encoding.UTF8.GetBytes(secret);
        HMAC hmac = new HMACSHA256(bytes);
        bytes = Encoding.UTF8.GetBytes(payload);

        return Convert.ToBase64String(hmac.ComputeHash(bytes));
    }

    public static bool HashIsValid(string secret, string payload, string verify)
    {
       ReadOnlySpan<byte> hashBytes = Convert.FromBase64String(ComputeHash(secret, payload));
       ReadOnlySpan<byte> verifyBytes = Convert.FromBase64String(verify);

       return CryptographicOperations.FixedTimeEquals(hashBytes, verifyBytes);
    }
}

每个 Microsoft,仅适用于:.NET Core 2.1、2.2、3.0、3.1、.NET 5、.NET 6、.NET 7CryptographicOperations.FixedTimeEquals

因此,我无法在 .NET Framework 4.8 中使用此代码示例。

问题 1:在 .NET Framework 4.8 中,是否有其他方法可以验证 HMAC 签名?

我无法找到替代方案,因此我尝试了与下面的 Microsoft 文章类似的方法。

使用 WCF 3.5 设计和构建 RESTful Web 服务的指南

因此,我在我的 WCF 服务中实现了以下内容,希望能够解决:CryptographicOperations.FixedTimeEquals

public string DocuSign(DocuSignWebhookRequest jsonRequest)
{
    var payload = JsonConvert.SerializeObject(jsonRequest);
    var secretKey = ConfigurationManager.AppSettings["HMAC_Key"];
    var verifyKey = HttpContext.Current.Request.Headers["x-docusign-signature-1"];

    var computedHashString = ComputeHash(secretKey, payload);
    var valid = computedHashString.Equals(verifyKey); // false
}

private string ComputeHash(string secret, string payload)
{
    byte[] bytes = Encoding.UTF8.GetBytes(secret);
    HMAC Mac = new HMACSHA256(bytes);
    bytes = Encoding.UTF8.GetBytes(payload);
    return Convert.ToBase64String(Mac.ComputeHash(bytes));
}

问题 2:为什么我的代码无法验证 HMAC 签名?与 DocuSign 发送的验证密钥相比,它始终返回 false。

asp.net WCF HMAC docusignconnect

评论

0赞 Topaco 9/20/2023
两种代码的区别仅在于比较数据,第一个代码将字节数组与 进行比较,第二个代码将 Base64 编码数据与 进行比较。如果第一个代码验证成功,则第二个代码也验证成功(如果您传递相同的数据),则在此处 如果情况并非如此,请发布可以重现问题的非生产性数据。否则,问题更有可能出在您的数据上,而数据可能不一致。FixedTimeEquals()String.Equals()
0赞 Topaco 9/20/2023
如果要在 .NET Framework 下使用非常量时间比较来修复漏洞,请自行实现。在网络上,您可以找到实现(例如这里)。FixedTimeEquals()
0赞 Pavel 9/21/2023
@Topaco谢谢。我按照您推荐的链接复制了 .NET Core 实现,并且正在使用它。似乎正在工作。

答:

-1赞 Jiayao 9/20/2023 #1

下面是一个官方文档,展示了如何使用 HMACSHA256 对象对文件进行签名,然后如何验证文件:HMACSHA256 Class

关于第二个问题,您发布的代码已替换为实际值。我不确定这是否会导致问题。

评论

0赞 NotARobot 9/20/2023
这并不是对这个问题的真正回答,更像是评论。如果链接最终停止工作,这个答案实际上毫无价值。