在 Node 中签署比特币交易
Signing a Bitcoin transaction in Node
我一直在 NodeJS 环境中实现事务,并且一直在使用 https://learnmeabitcoin.com/technical/ecdsa#sign 等指南来理解其背后的代码。
我已经编写了一个对交易进行签名的函数,但是代码的某些部分存在缺陷,因为验证以下函数生成的签名不断返回 false
。我编写的 verify
函数应该可以正常工作,因为它 returns true
用于 a thirty party library.
生成的签名
bufferToBigInt
、pointMultiply
、pointAdd
、modulo
等导入函数已经过测试,应该可以正常工作。
我在下面添加了类型注释,以便更容易理解变量的类型。
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
);
我一直在 NodeJS 环境中实现事务,并且一直在使用 https://learnmeabitcoin.com/technical/ecdsa#sign 等指南来理解其背后的代码。
我已经编写了一个对交易进行签名的函数,但是代码的某些部分存在缺陷,因为验证以下函数生成的签名不断返回 false
。我编写的 verify
函数应该可以正常工作,因为它 returns true
用于 a thirty party library.
bufferToBigInt
、pointMultiply
、pointAdd
、modulo
等导入函数已经过测试,应该可以正常工作。
我在下面添加了类型注释,以便更容易理解变量的类型。
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
);