在 Node 中签署比特币交易

Signing a Bitcoin transaction in Node

我一直在 NodeJS 环境中实现事务,并且一直在使用 https://learnmeabitcoin.com/technical/ecdsa#sign 等指南来理解其背后的代码。

我已经编写了一个对交易进行签名的函数,但是代码的某些部分存在缺陷,因为验证以下函数生成的签名不断返回 false。我编写的 verify 函数应该可以正常工作,因为它 returns true 用于 a thirty party library.

生成的签名

bufferToBigIntpointMultiplypointAddmodulo 等导入函数已经过测试,应该可以正常工作。

我在下面添加了类型注释,以便更容易理解变量的类型。

export const sign = (hashOfMessage: Buffer, privateKey: Buffer) => {
  const randomNumber: bigint = bufferToBigInt(generatePrivateKey());
  const randomPoint: Buffer = pointMultiply(GENERATOR_POINT, randomNumber);
  const randomPointX: bigint = extractX(randomPoint);
  const privateKeyAsNumber: bigint = bufferToBigInt(privateKey);
  const r: bigint = modulo(randomPointX, ORDER);
  const s: bigint = modulo(
    modInv(randomNumber, ORDER) *
      (bufferToBigInt(hashOfMessage) + randomNumber * privateKeyAsNumber),
    ORDER
  );
  const sLow: bigint = s > ORDER / 2n ? ORDER - s : s;
  return Buffer.concat([
    Buffer.from(r.toString(16).padStart(64, "0"), "hex"),
    Buffer.from(sLow.toString(16).padStart(64, "0"), "hex"),
  ]);
};

export const verify = (
  hashOfMessage: Buffer,
  publicKey: Buffer,
  signature: Buffer
) => {
  const r: bigint = bufferToBigInt(signature, 0, 32);
  const s: bigint = bufferToBigInt(signature, 32);
  const sModInverse: bigint = modInv(s, ORDER);
  const pointOne: Buffer = pointMultiply(
    GENERATOR_POINT,
    bufferToBigInt(hashOfMessage) * sModInverse
  );
  const pointTwo: Buffer = pointMultiply(publicKey, r * sModInverse);
  const pointResult: Buffer = pointAdd(pointOne, pointTwo);
  return extractX(pointResult) === r;
};

我发现了我的错误。

我计算错了 s 因为我使用 randomNumber 而不是 r

s 的计算应该如下:

const s: bigint = modulo(
    modInv(randomNumber, ORDER) *
      (bufferToBigInt(hashOfMessage) + r * privateKeyAsNumber),
    ORDER
  );