
本文旨在解决在Webhook签名验证过程中,Python与TypeScript实现之间出现的差异问题。通过详细分析两种语言在JSON序列化时的不同行为,提供了一套可靠的TypeScript解决方案,确保签名验证的一致性和准确性。该方案通过规范化JSON字符串格式,消除了因空格差异导致的验证失败问题,从而保证了Webhook通信的安全性和可靠性。
在开发涉及Webhook的应用时,确保接收到的数据确实来自可信来源至关重要。Webhook签名验证是一种常见的安全措施,它通过使用共享密钥对请求内容进行签名,并在接收端验证签名,从而防止恶意篡改。然而,在跨语言环境中实现签名验证时,可能会遇到一些意想不到的问题,例如Python和TypeScript在处理JSON序列化时的差异。
问题根源:JSON序列化格式的差异
Python的json.dumps()方法在默认情况下会生成紧凑的JSON字符串,不包含额外的空格。而TypeScript中使用JSON.stringify()在没有指定参数的情况下也会生成紧凑的JSON字符串。但是,如果格式化JSON(例如为了方便调试),可能会引入空格,导致生成的签名与预期不符。即使没有格式化,不同的JSON序列化库也可能在空格处理上存在细微差异。
解决方案:规范化JSON字符串格式
为了解决这个问题,我们需要在TypeScript中规范化JSON字符串的格式,使其与Python生成的格式保持一致。一种有效的方法是使用一系列的字符串替换操作,移除或调整JSON字符串中的空格。
立即学习“Python免费学习笔记(深入)”;
以下代码展示了如何使用Ramda库中的pipe和replace函数,创建一个名为toJSONWithSpaces的函数,该函数可以规范化JSON字符串的格式:
import { pipe, replace } from 'ramda';export const toJSONWithSpaces = pipe( (object: unknown) => JSON.stringify(object, null, 1), // stringify with line-breaks and indents replace(/n +/gm, ' '), // replace line breaks and following spaces with a single space replace(/:s/g, ': '), // ensure a space after colon replace(/{s/g, '{'), // remove space after opening brace replace(/s}/g, '}'), // remove space before closing brace replace(/[s/g, '['), // remove space after opening bracket replace(/s]/g, ']'), // remove space before closing bracket replace(/,s/g, ', '), // ensure a space after comma);
这个函数首先使用JSON.stringify(object, null, 1)将对象转换为带有换行符和缩进的JSON字符串。然后,它使用一系列的正则表达式替换操作来移除或调整空格,以确保JSON字符串的格式与Python生成的格式一致。
集成到签名验证函数中
接下来,我们需要将toJSONWithSpaces函数集成到签名验证函数中。以下是一个修改后的verifyCloseSignature函数,它使用toJSONWithSpaces函数来规范化payload:
import { toJSONWithSpaces } from './json-formatter'; // 假设 toJSONWithSpaces 函数在 json-formatter.ts 文件中import * as crypto from 'crypto';export function verifyCloseSignature( request: Request, key: string, payload: any,) { const headers = request.headers; const timestamp = headers.get('close-sig-timestamp'); const providedSignature = headers.get('close-sig-hash'); if (!timestamp) { throw new Error('[verifyCloseSignature] Required timestamp header missing'); } if (!providedSignature) { throw new Error('[verifyCloseSignature] Required signature header missing'); } const hmac = crypto.createHmac('sha256', Buffer.from(key, 'hex')); const cleanedPayload = toJSONWithSpaces(payload); hmac.update(timestamp + cleanedPayload); const calculatedSignature = hmac.digest('hex'); return crypto.timingSafeEqual( Buffer.from(providedSignature, 'hex'), Buffer.from(calculatedSignature, 'hex'), );}
在这个修改后的函数中,我们首先使用toJSONWithSpaces(payload)来规范化payload,然后再将其用于HMAC计算。
注意事项
依赖管理: 确保安装了ramda库,可以通过运行npm install ramda或yarn add ramda来安装。密钥格式: 确认密钥是以十六进制字符串的形式提供的,并且在TypeScript中使用Buffer.from(key, ‘hex’)正确地将其转换为Buffer。时间戳: 确保时间戳的格式在Python和TypeScript中一致。通常,时间戳应该是一个整数或字符串,表示自Epoch以来的秒数。Content-Type: 确保请求头的 Content-Type 设置为 application/json。
总结
通过规范化JSON字符串的格式,我们可以解决在Webhook签名验证过程中Python和TypeScript实现之间的差异问题。这种方法可以确保签名验证的一致性和准确性,从而提高Webhook通信的安全性和可靠性。在实际应用中,建议编写单元测试来验证签名验证函数的正确性,并定期审查和更新代码,以应对潜在的安全风险。
以上就是解决Webhook签名验证中Python与TypeScript差异的实用指南的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1539092.html
微信扫一扫
支付宝扫一扫