使用javaScript中使用sblecrypto进行HMAC验证的错误结果错误

发布于 2025-01-30 13:58:05 字数 1235 浏览 2 评论 0原文

我正在尝试使用kittlecrypto API验证HMAC签名。整个过程应该在Cloudflare工人中运行,我正在使用其Wrangler工具在本地进行测试。

到目前为止,这是我的代码,但是它会生成错误的签名。

const message = "(query params from an url)";
const given_signature = "(extracted from the query params)";
const SECRET = "...";

const algorithm = { name: 'HMAC', hash: 'SHA-256' };
const encoder = new TextEncoder();

const key = await crypto.subtle.importKey(
    'raw',
    encoder.encode(SECRET),
    algorithm,
    false,
    ['sign', 'verify']
);

const signature = await crypto.subtle.sign(
    algorithm.name,
    key,
    encoder.encode(message)
);

const digest = btoa(String.fromCharCode(...new Uint8Array(signature)));
// The digest does not match the signature extracted from the query params

// If I, for example, want to verify the signature directly, the result is still false.
const verify = await crypto.subtle.verify(
    algorithm.name,
    key,
    encoder.encode(given_signature),
    encoder.encode(message)
);

如果我在在线HMAC测试工具中使用相同的秘密和消息,我会得到正确的结果,因此我确定我的代码中必须有一个错误。

我发现有趣的是我的代码生成的签名比给定的一个(例如3FN0MHREBHTJMHTOYVRP5NZIHOGX/M1OKQ5GOJNIZTM = vs 533 )。

有人知道我出了什么问题吗?

I am trying to verify a HMAC signature using the SubtleCrypto API. The whole thing is supposed to run in Cloudflare Workers and I am testing it locally using their wrangler tool.

This is my code so far, but it generates the wrong signature.

const message = "(query params from an url)";
const given_signature = "(extracted from the query params)";
const SECRET = "...";

const algorithm = { name: 'HMAC', hash: 'SHA-256' };
const encoder = new TextEncoder();

const key = await crypto.subtle.importKey(
    'raw',
    encoder.encode(SECRET),
    algorithm,
    false,
    ['sign', 'verify']
);

const signature = await crypto.subtle.sign(
    algorithm.name,
    key,
    encoder.encode(message)
);

const digest = btoa(String.fromCharCode(...new Uint8Array(signature)));
// The digest does not match the signature extracted from the query params

// If I, for example, want to verify the signature directly, the result is still false.
const verify = await crypto.subtle.verify(
    algorithm.name,
    key,
    encoder.encode(given_signature),
    encoder.encode(message)
);

If I am using the same secret and message in online HMAC testing tools, I am getting the correct results, so I am certain that there must be a bug in my code.

What I find interesting, is that the signature generated by my code is much shorter than the given one (e.g. 3fn0mhrebHTJMhtOyvRP5nZIhogX/M1OKQ5GojniZTM= vs ddf9f49a1ade6c74c9321b4ecaf44fe67648868817fccd4e290e46a239e26533).

Does anyone have an idea where I am going wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

℉絮湮 2025-02-06 13:58:05

感谢有用的评论!简而言之,问题在于,所提供的签名被编码为十六进制字符串,而生成的签名是基本64编码的字符串。

为了保持清洁,这是一个使用crypto.subtle.verify函数的工作版本:

const message = "(query params from an url w/o the hmac signature)";
const given_signature = "(the given hmac signature extracted from the query params)";
const SECRET = "(my secret key)";

const hexToBuffer = (hex: string) => {
  const matches = hex.match(/[\da-f]{2}/gi) ?? [];
  const typedArray = new Uint8Array(
    matches.map(function (h) {
      return parseInt(h, 16);
    })
  );
  return typedArray.buffer;
};

const algorithm = { name: "HMAC", hash: "SHA-256" };
const encoder = new TextEncoder();

const key = await crypto.subtle.importKey(
  "raw",
  encoder.encode(SECRET),
  algorithm,
  false,
  ["sign", "verify"]
);

const result: boolean = await crypto.subtle.verify(
  algorithm.name,
  key,
  hexToBuffer(given_signature),
  encoder.encode(message)
);

Thanks to the helpful comments! The problem in a nutshell was that the provided signature was encoded as a HEX string, while the generated signature was a base64-encoded string.

To keep things clean, here is a working version that uses the crypto.subtle.verify function:

const message = "(query params from an url w/o the hmac signature)";
const given_signature = "(the given hmac signature extracted from the query params)";
const SECRET = "(my secret key)";

const hexToBuffer = (hex: string) => {
  const matches = hex.match(/[\da-f]{2}/gi) ?? [];
  const typedArray = new Uint8Array(
    matches.map(function (h) {
      return parseInt(h, 16);
    })
  );
  return typedArray.buffer;
};

const algorithm = { name: "HMAC", hash: "SHA-256" };
const encoder = new TextEncoder();

const key = await crypto.subtle.importKey(
  "raw",
  encoder.encode(SECRET),
  algorithm,
  false,
  ["sign", "verify"]
);

const result: boolean = await crypto.subtle.verify(
  algorithm.name,
  key,
  hexToBuffer(given_signature),
  encoder.encode(message)
);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文