bitcoin-sv / ts-sdk

Other
50 stars 12 forks source link

[ ALIGNMENT ] #119

Closed sirdeggen closed 1 month ago

sirdeggen commented 2 months ago

Summary

BSM implementation makes it awkward to match go-sdk and bsvjs Bsm implementations.

Motivation

It's deprecated so we didn't focus on making it good but now it's raised its head we should implement this under the hood.

Description

BSM.sign() should return the same base64 you'd expect from older libraries. We should be careful not to break ts-paymail in the process.

Additional References

Here's the solution

// bsv
import bsv from 'bsv'
import Message from 'bsv/message'
// @bsv/sdk
import { BSM, PrivateKey, Utils, Hash, BigNumber } from "@bsv/sdk"
const { toArray, Writer } = Utils

// sign with both libraries and compare signatures
const wif = "L211enC224G1kV8pyyq7bjVd9SxZebnRYEzzM3i7ZHCc1c5E7dQu"

const bsvSdkPk = PrivateKey.fromWif(wif)
const bsvPk = bsv.PrivateKey.fromWIF(wif)
const msgStr = "hello world"

const prefix = 'Bitcoin Signed Message:\n'
export const magicHash = (messageBuf: number[]): number[] => {
  const bw = new Writer()
  bw.writeVarIntNum(prefix.length)
  bw.write(toArray(prefix, 'utf8'))
  bw.writeVarIntNum(messageBuf.length)
  bw.write(messageBuf)
  const buf = bw.toArray()
  const hashBuf = Hash.hash256(buf)
  return hashBuf
}

const bsvSdkSig = BSM.sign(toArray(msgStr), bsvSdkPk)
const h = new BigNumber(magicHash(toArray(msgStr, 'utf8')))
const r = bsvSdkSig.CalculateRecoveryFactor(bsvSdkPk.toPublicKey(), h)
const sig = bsvSdkSig.toCompact(r, true, 'base64')
const bsvSig = new Message(msgStr).sign(bsvPk)

console.log("Sigs:", { sig, bsvSig })

// PRINTS
// 'Sigs:' {
//   sig: 'H4T8Asr0WkC6wYfBESR6pCAfECtdsPM4fwiSQ2qndFi8dVtv/mrOFaySx9xQE7j24ugoJ4iGnsRwAC8QwaoHOXk=',
//   bsvSig: 'H4T8Asr0WkC6wYfBESR6pCAfECtdsPM4fwiSQ2qndFi8dVtv/mrOFaySx9xQE7j24ugoJ4iGnsRwAC8QwaoHOXk='
// }
shruggr commented 2 months ago

In order to keep compatibility with all other libraries which have implemented BSM, can verify use an address rather than a pubKey? Here's the function signatures from go:

func SignMessage(privateKey *ec.PrivateKey, message []byte) ([]byte, error)
func VerifyMessage(address string, sig, data []byte) error
shruggr commented 2 months ago

moneybutton/bsv@1.5.6 Message.verify = function (message, address, signature)

@2.x static verify (messageBuf, sigstr, address)