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

使用RSA私钥生成Walmart Affiliate SHA256签名遇401认证失败

问题:RSA私钥生成SHA256签名时Walmart API返回401验证失败

尝试用RSA私钥生成SHA256签名调用Walmart联盟API时,收到401错误:

Could not authenticate in-request, auth signature : Signature verification failed: affil-product, version: 2.0.0, env: prod

怀疑问题出在.pem私钥文件的处理上。已按Walmart指南创建无密码密钥对并上传公钥,配置了appsettings.json:

{"Settings": {"consumerID": "e2ca6a2f-56f2-4465-88b3-273573b1e0c9","keyVer": "4"}}

现有代码流程

读取配置(Program.cs)

IConfiguration config = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .AddEnvironmentVariables()
    .Build();

// 从配置中获取参数
Settings settings = config.GetRequiredSection("Settings").Get<Settings>();

实例化API对象

WalMartAfilAPI wallMartAfilAPI = new WalMartAfilAPI();

导入私钥并导出参数

RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider();
var rsaPem = File.ReadAllText("D:\\Users\\Adam\\source\\repos\\DealsBot\\DealsBot\\DealsBot\\wallmartAfill\\WM_IO_private_key.pem");
var rsa = RSA.Create();
rsa.ImportFromPem(rsaPem);
// 导出私钥参数用于签名
RSAParameters Key = rsa.ExportParameters(true);

生成时间戳并调用签名方法

// 生成Unix毫秒级时间戳
var time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
Console.WriteLine(time);

byte[] conicData = wallMartAfilAPI.Canonicalize(settings.KeyVer, settings.ConsumerID, time);
byte[] signedData = wallMartAfilAPI.HashAndSignBytes(conicData, Key);

if (wallMartAfilAPI.VerifySignedHash(conicData, signedData, Key))
{
    Console.WriteLine("The data was verified");
    Console.WriteLine(Convert.ToBase64String(signedData));
}
else
{
    // 此处代码未完整展示
}

WalMartAfilAPI类代码

namespace DealsBot.wallmartAfill
{
    public class WalMartAfilAPI
    {
        public byte[] Canonicalize(string version, string consumerId, string timestamp)
        {
            ASCIIEncoding ByteConverter = new ASCIIEncoding();
            StringBuilder keyBuilder = new StringBuilder();
            StringBuilder valueBuilder = new StringBuilder();
            SortedDictionary<string, string> dictionary = new SortedDictionary<string, string>() 
            { 
                { "WM_CONSUMER.ID", consumerId }, 
                { "WM_CONSUMER.INTIMESTAMP", timestamp }, 
                { "WM_SEC.KEY_VERSION", version } 
            };

            foreach (string key in dictionary.Keys)
            {
                keyBuilder.Append($"{key.Trim()};");
                valueBuilder.AppendLine($"{dictionary[key].Trim()}");
            }
            string[] conHeader =  { keyBuilder.ToString(), valueBuilder.ToString() };
            byte[] originalData = ByteConverter.GetBytes(conHeader[1]);

            return originalData;
        }

        public byte[] HashAndSignBytes(byte[] DataToSign, RSAParameters Key)
        {
            try
            {
                RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider();
                RSAalg.ImportParameters(Key);
                return RSAalg.SignData(DataToSign, SHA256.Create());
            }
            catch (CryptographicException e)
            {
                Console.WriteLine(e.Message);
                return null;
            }
        }

        public bool VerifySignedHash(byte[] DataToVerify, byte[] SignedData, RSAParameters Key)
        {
            try
            {
                RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider();
                RSAalg.ImportParameters(Key);
                return RSAalg.VerifyData(DataToVerify, SHA256.Create(), SignedData);
            }
            catch (CryptographicException e)
            {
                Console.WriteLine(e.Message);
                return false;
            }
        }
    }
}

问题排查与修复方案

1. 规范化(Canonicalize)逻辑错误

Walmart签名规范要求同时包含排序后的键和值拼接内容,当前代码仅使用了值部分,忽略了键部分,导致签名原始数据不匹配。

修改Canonicalize方法:

public byte[] Canonicalize(string version, string consumerId, string timestamp)
{
    ASCIIEncoding byteConverter = new ASCIIEncoding();
    SortedDictionary<string, string> dictionary = new SortedDictionary<string, string>() 
    { 
        { "WM_CONSUMER.ID", consumerId }, 
        { "WM_CONSUMER.INTIMESTAMP", timestamp }, 
        { "WM_SEC.KEY_VERSION", version } 
    };

    StringBuilder canonicalBuilder = new StringBuilder();
    // 先拼接排序后的键,用分号分隔
    foreach (var key in dictionary.Keys)
    {
        canonicalBuilder.Append($"{key.Trim()};");
    }
    canonicalBuilder.AppendLine();
    // 再拼接对应的值,每个值单独一行
    foreach (var key in dictionary.Keys)
    {
        canonicalBuilder.AppendLine(dictionary[key].Trim());
    }

    // 移除末尾多余换行,确保格式严格匹配
    string canonicalString = canonicalBuilder.ToString().TrimEnd();
    return byteConverter.GetBytes(canonicalString);
}

2. RSA签名算法未明确指定

Walmart要求使用SHA256withRSA(PKCS#1 v1.5)签名,当前代码未明确指定签名填充方式,可能导致签名格式不兼容。

修改签名和验证方法:

public byte[] HashAndSignBytes(byte[] DataToSign, RSAParameters Key)
{
    try
    {
        using (RSA rsa = RSA.Create())
        {
            rsa.ImportParameters(Key);
            return rsa.SignData(DataToSign, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
        }
    }
    catch (CryptographicException e)
    {
        Console.WriteLine(e.Message);
        return null;
    }
}

public bool VerifySignedHash(byte[] DataToVerify, byte[] SignedData, RSAParameters Key)
{
    try
    {
        using (RSA rsa = RSA.Create())
        {
            rsa.ImportParameters(Key);
            return rsa.VerifyData(DataToVerify, SignedData, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
        }
    }
    catch (CryptographicException e)
    {
        Console.WriteLine(e.Message);
        return false;
    }
}

3. 私钥处理冗余优化

移除冗余的RSACryptoServiceProvider实例,简化私钥导入逻辑:

var rsaPem = File.ReadAllText("D:\\Users\\Adam\\source\\repos\\DealsBot\\DealsBot\\DealsBot\\wallmartAfill\\WM_IO_private_key.pem");
using (var rsa = RSA.Create())
{
    rsa.ImportFromPem(rsaPem);
    RSAParameters Key = rsa.ExportParameters(true);
    // 后续签名逻辑放在using块内,避免资源泄漏
}

4. 时间戳一致性检查

确保生成签名的时间戳与请求API时携带的时间戳完全一致,且时间戳在Walmart服务器允许的5分钟误差范围内,建议签名生成后立即发起请求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 12:30:42