如何用OpenAPI规范认证Bitstamp HTTP API v2?遇403无效签名错误
问题:Bitstamp API客户端认证失败(403 Invalid signature)
使用Bitstamp的OpenAPI规范通过NSWAG生成客户端后,始终无法完成认证,持续收到403错误:
响应的HTTP状态码不符合预期(403)。
状态码:403
响应内容:
{"status": "error", "reason": "Invalid signature", "code": "API0005"}
自定义的BitstampClient代码如下:
public partial class BitstampClient { private readonly string key; private readonly string secret; private readonly bool isPublicApi; public BitstampClient(string key, string secret, IHttpClientFactory httpFactory) : this(httpFactory.CreateClient($"BitstampClient-{key}")) { this.key = key; this.secret = secret; this.isPublicApi = false; } public BitstampClient(IHttpClientFactory httpFactory) : this(httpFactory.CreateClient($"BitstampClient-Public")) { this.isPublicApi = true; } public BitstampClient(string key, string secret) : this(new HttpClient()) { this.key = key; this.secret = secret; } partial void PrepareRequest(HttpClient client, HttpRequestMessage request, StringBuilder urlBuilder) { if (!this.isPublicApi) { var xauth = $"{"BITSTAMP"} {this.key}"; var nonce = Guid.NewGuid().ToString(); //DateTime.Now.Ticks; var time = DateTime.UtcNow.Ticks / TimeSpan.TicksPerMillisecond; var version = "v2"; var contentType = "application/x-www-form-urlencoded"; var signature = GetXAuthSignature(nonce, this.key, this.secret, "QWERTY"); request.Headers.Add("X-Auth", xauth); request.Headers.Add("X-Auth-Signature", signature); request.Headers.Add("X-Auth-Nonce", nonce.ToString()); request.Headers.Add("X-Auth-Timestamp", time.ToString()); request.Headers.Add("X-Auth-Version", version); request.Content.Headers.ContentType = null; } } private string GetXAuthSignature(string nonce, string key, string secret, string clientId) { var msg = $"{nonce}{clientId}{key}"; return ByteArrayToString(SignHMACSHA256(secret, StringToByteArray(msg))).ToUpper(); } private static byte[] SignHMACSHA256(string key, byte[] data) { var hashMaker = new HMACSHA256(Encoding.ASCII.GetBytes(key)); return hashMaker.ComputeHash(data); } private static byte[] StringToByteArray(string str) { return Encoding.ASCII.GetBytes(str); } private static string ByteArrayToString(byte[] hash) { return BitConverter.ToString(hash).Replace("-", "").ToLower(); } }
问题分析与修复
核心问题1:Nonce格式不符合要求
Bitstamp要求X-Auth-Nonce必须是严格递增的数字值(通常用自增整数或毫秒级时间戳),你当前用Guid.NewGuid().ToString()生成的字符串完全不符合规则,直接导致签名验证失败。
核心问题2:ClientId硬编码错误
GetXAuthSignature里的clientId被硬编码为"QWERTY",但这个值必须是Bitstamp账户API密钥对应的数字用户ID,可在账户的API设置页面查询到。
核心问题3:签名转换逻辑冗余
你先将签名转为小写再转大写,虽然不影响结果,但增加了不必要的转换步骤,可能引入潜在错误。
修复后的代码调整
- 替换Nonce生成逻辑,用静态自增计数器确保每次请求的Nonce严格递增
- 替换硬编码的ClientId为实际的数字用户ID
- 简化签名转换流程
- 修正请求Content-Type的设置逻辑
修复后的关键代码片段:
// 维护静态自增计数器,确保Nonce严格递增 private static long _nonceCounter = DateTime.UtcNow.Ticks / TimeSpan.TicksPerMillisecond; partial void PrepareRequest(HttpClient client, HttpRequestMessage request, StringBuilder urlBuilder) { if (!this.isPublicApi) { var apiKey = this.key; var apiSecret = this.secret; var clientId = "你的Bitstamp数字用户ID"; // 替换为实际值 var nonce = Interlocked.Increment(ref _nonceCounter).ToString(); var timestamp = DateTime.UtcNow.Ticks / TimeSpan.TicksPerMillisecond; var version = "v2"; var signature = GetXAuthSignature(nonce, apiKey, apiSecret, clientId); request.Headers.Add("X-Auth", $"BITSTAMP {apiKey}"); request.Headers.Add("X-Auth-Signature", signature); request.Headers.Add("X-Auth-Nonce", nonce); request.Headers.Add("X-Auth-Timestamp", timestamp.ToString()); request.Headers.Add("X-Auth-Version", version); // 确保请求内容的Content-Type正确 if (request.Content != null) { request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); } } } private string GetXAuthSignature(string nonce, string key, string secret, string clientId) { var msg = $"{nonce}{clientId}{key}"; var secretBytes = Encoding.ASCII.GetBytes(secret); var msgBytes = Encoding.ASCII.GetBytes(msg); using var hmac = new HMACSHA256(secretBytes); var hashBytes = hmac.ComputeHash(msgBytes); // 直接生成大写十六进制签名 return BitConverter.ToString(hashBytes).Replace("-", "").ToUpper(); }
额外注意事项
- 确保API密钥已开启对应操作的权限(如查询余额、交易等)
- 本地系统时间需与UTC时间同步,偏差过大将导致
X-Auth-Timestamp验证失败 - 禁止重复使用Nonce,必须保证每次请求的Nonce值严格大于上一次
内容的提问来源于stack exchange,提问作者R4nc1d
相关产品推荐
相关产品推荐

