You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求PHP转C#的HMAC-SHA256验证函数getVerifiedPayload实现帮助

从PHP转换C#的HMAC验证函数实现

我们需要在服务器与客户端间安全传输数据包,已用PHP实现相关逻辑,现需转为C#代码。刚接触C#,已完成createHashedPayload函数的转换,附上PHP原代码及已实现的C#加密函数,请求帮助转换getVerifiedPayload验证函数。

PHP原代码

function createHashedPayload(string $packet, string $secret, string $hash = 'sha256'): string
{
    return base64_encode(hash_hmac('sha256', $packet, $secret, true) . $packet);
}

function getVerifiedPayload(string $payload, string $secret, string $hash = 'sha256'): ?string
{
    $decoded = base64_decode($payload);
    $hashlen = strlen(hash($hash, "test", true)); // Quick method to get hash length
    

    $hmac = substr($decoded, 0, $hashlen); // Get HMAC from start of string
    $content = substr($decoded, $hashlen); // Rest of the string is content

    // Verify HMAC
    $calcmac = hash_hmac($hash, $content, $secret, true);
    if (hash_equals($hmac, $calcmac)) {
        return $content;
    }

    return null;
}

已实现的C#加密函数

static string createHashedPayload(string text, string key)
{
    key = key ?? "";

    using (var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(key)))
    {
        var hash = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(text));
        return Convert.ToBase64String(hash);
    }
}

修正后的C#完整实现

1. 先修正createHashedPayload函数

注意:当前C#版的createHashedPayload和PHP逻辑不一致——PHP是将HMAC字节流与原始数据包字节拼接后再做Base64编码,而当前C#版仅返回了HMAC的Base64,这会导致后续验证失败,先做修正:

static string CreateHashedPayload(string text, string key)
{
    key = key ?? string.Empty;
    byte[] textBytes = Encoding.UTF8.GetBytes(text);
    
    using (var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(key)))
    {
        byte[] hashBytes = hmacsha256.ComputeHash(textBytes);
        // 拼接HMAC字节和原始文本字节
        byte[] combinedBytes = new byte[hashBytes.Length + textBytes.Length];
        Buffer.BlockCopy(hashBytes, 0, combinedBytes, 0, hashBytes.Length);
        Buffer.BlockCopy(textBytes, 0, combinedBytes, hashBytes.Length, textBytes.Length);
        
        return Convert.ToBase64String(combinedBytes);
    }
}

2. 实现GetVerifiedPayload验证函数

对应PHP的getVerifiedPayload逻辑,完成C#版本:

static string? GetVerifiedPayload(string payload, string key)
{
    key = key ?? string.Empty;
    
    try
    {
        // 解码Base64字符串
        byte[] decodedBytes = Convert.FromBase64String(payload);
        // SHA256的HMAC固定长度为32字节,直接使用固定值替代PHP的动态获取方式
        int hashLength = 32;
        
        // 校验数据长度是否合法
        if (decodedBytes.Length < hashLength)
        {
            return null;
        }
        
        // 拆分出接收到的HMAC和原始内容字节
        byte[] receivedHmac = new byte[hashLength];
        byte[] contentBytes = new byte[decodedBytes.Length - hashLength];
        Buffer.BlockCopy(decodedBytes, 0, receivedHmac, 0, hashLength);
        Buffer.BlockCopy(decodedBytes, hashLength, contentBytes, 0, contentBytes.Length);
        
        // 计算内容的HMAC
        using (var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(key)))
        {
            byte[] calculatedHmac = hmacsha256.ComputeHash(contentBytes);
            
            // 用固定时间比较防范时序攻击,等价于PHP的hash_equals
            if (CryptographicOperations.FixedTimeEquals(receivedHmac, calculatedHmac))
            {
                return Encoding.UTF8.GetString(contentBytes);
            }
        }
    }
    catch (FormatException)
    {
        // Base64解码失败直接返回null
        return null;
    }
    
    return null;
}

补充说明

  • 使用CryptographicOperations.FixedTimeEquals做字节数组比较,避免时序攻击,保证验证安全性;
  • SHA256的HMAC长度固定为32字节,无需像PHP那样动态计算,直接用固定值更高效;
  • 加入异常捕获处理Base64解码失败的情况,避免程序崩溃。

内容的提问来源于stack exchange,提问作者jagadeeshaleti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 05:45:34