c# - 验证来自 Transnational webhook 的 webhook 帖子签名
问题描述
我试图验证来自跨国支付的 webhook 帖子签名。有这方面的文件;
Webhook post requests are sent with a header "Signature" that is HMAC SHA 256 signed and then base64 url encoded.
To verify webhook post signatures, retrieve "Signature" from header. Base64 url decode and use HMAC SHA 256 to check using your signature UUID located in the control panel under the webhook previously created
首先,当我尝试使用 Base64 Url 解码签名时,我得到一个错误。这是一个签名的例子。“RwtK6Kr4NOOFs9mjYPpEJWxSJQr23k6uXDktj4QEjGk”
这是他们用来测试签名比较的示例代码:,我认为它在 Go 中。
sig := r.Header.Get("Signature")
// Get the body
body, _ := ioutil.ReadAll(r.Body)
r.Body.Close()
// Verify Sig
mac := hmac.New(sha256.New, []byte("signature-to-check-here"))
mac.Write(body)
sigCheck, _ := base64.RawURLEncoding.DecodeString(sig)
doesitequal := hmac.Equal(sigCheck, mac.Sum(nil))
ctx.Log().Infof("%v", doesitequal)
他们还发送了用于对签名进行编码的代码。
// Set webhook data into buffer for http post
buf := &bytes.Buffer{}
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(true)
enc.Encode(w.Data)
// Encrypt the data for signature
mac := hmac.New(sha256.New, []byte(w.Signature))
mac.Write(buf.Bytes())
base64Enc := base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
// Create post request
client := &http.Client{
Timeout: time.Duration(5 * time.Second),
}
req, err := http.NewRequest("POST", w.URL, bytes.NewReader(buf.Bytes()))
if err != nil {
ctx.Log().AddField("Webhook data", w).Error(err.Error())
}
req.Header.Set("Content-type", "application/json")
req.Header.Set("Signature", base64Enc)
这是我尝试过的 1 个版本。我正在尝试从响应中创建签名并将其与标头中的签名相匹配。我找不到比赛。这不会尝试
Encoding ascii = Encoding.ASCII;
var client_secret = "[Secret]";
//request body
var body = "[Responce Body]";
// signature form header
var signature = "RwtK6Kr4NOOFs9mjYPpEJWxSJQr23k6uXDktj4QEjGk";
// uri escape the body
var calc_body = Uri.EscapeUriString(body);
//url encode te body
calc_body = WebUtility.UrlEncode(calc_body);
//create the signature HMACSHA256
var sig = GenerateSignature(calc_body, client_secret);
//Base64 Url encode the signture
var calc_sig = Base64UrlEncode(ascii.GetBytes(sig));
//Compare the signature form the header to the calculated cignature
if (signature == calc_sig)
{
Console.WriteLine("Matches");
}
else
{
Console.WriteLine("Does not match");
}
}
private static string GenerateSignature(string data, string signatureKey)
{
var keyByte = Encoding.ASCII.GetBytes(signatureKey);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
hmacsha256.ComputeHash(Encoding.ASCII.GetBytes(data));
return hmacsha256.Hash.Aggregate("", (current, t) => current + t.ToString("X2")).ToLower();
}
}
static string Base64UrlEncode(byte[] arg)
{
var s = Convert.ToBase64String(arg); // Regular base64 encoder
s = s.Split('=')[0]; // Remove any trailing '='s
s = s.Replace('+', '-'); // 62nd char of encoding
s = s.Replace('/', '_'); // 63rd char of encoding
return s;
}
我什至不确定我的步骤是否正确。
提前感谢您的帮助。
解决方案
推荐阅读
- jquery - 何时使用 toastr 在重定向中清除 Viewbag
- sql - ReactJs 与数据库
- opencart2.x - Opencart 定期订阅 购物车中的初始价格
- typescript - 如何将对象符号路径保存到要在模板中使用的变量中?
- python - 基于索引切割numpy数组
- javascript - 使用键盘向上/向下箭头导航表格
- openxml - OpenXML 表 gridSpan 属性
- google-apps-script - 如何为免费版 Google Add On 添加使用限制
- python - 带有自定义 Estimator 的 TensorFlow 指标
- python - 谷歌应用引擎部署烧瓶应用 - ImportError:libSM.so.6:无法打开共享对象文件:没有这样的文件或目录