Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BIP 322 Support #2077

Open
trevormil opened this issue Dec 22, 2023 · 13 comments · May be fixed by #2151 or #2152
Open

BIP 322 Support #2077

trevormil opened this issue Dec 22, 2023 · 13 comments · May be fixed by #2151 or #2152

Comments

@trevormil
Copy link

As BIP322 support becomes more popular with Bitcoin wallets (Phantom, etc), it would be nice to have a Go implementation for message signature verification. To my knowledge, I could not find one. The main one I could find is https://github.com/ACken2/bip322-js.

I particularly need it for my project that I am working on. Is this something that can be completed anytime soon? Or should I find an alternative solution in the meantime?

@Roasbeef
Copy link
Member

I particularly need it for my project that I am working on. Is this something that can be completed anytime soon? Or should I find an alternative solution in the meantime?

We'd accept a contribution implementing it. Seems relatively straight forward.

@mohamedawnallah
Copy link

I'd like to work on this issue, Thanks!

@trevormil
Copy link
Author

I'd like to work on this issue, Thanks!

Awesome. Could you keep me updated on any progress?

@mohamedawnallah
Copy link

Okay, I will do :)

@trevormil
Copy link
Author

Hey, any progress updates? My project will need a solution by the end of February. Do you think this will be done by then? Or, should I find an alternative?

No worries if not. Just need to know how to move forward.

@gamedevod
Copy link

@trevormil check my issue, i started implement it, but I warn you right away - my code does not produce correct results yet, and I cannot fix it https://github.com/btcsuite/btcd/issues/2117

@mohamedawnallah
Copy link

Sorry I seem missed this notification @trevormil I am busy now with other tasks Hope I get to it soon. That said please feel free to look for alternatives in the meantime. Thanks for your understanding 🙏

@trevormil
Copy link
Author

Sorry I seem missed this notification @trevormil I am busy now with other tasks Hope I get to it soon. That said please feel free to look for alternatives in the meantime. Thanks for your understanding 🙏

No worries. Thank you.

@AbhinavMir
Copy link

@trevormil hi! I had a look at how bitcoin core does this and a quick gist would be:

  • Adds script/proof.cpp and script/proof.h (for BIP 322 support).
  • Updates wallet interfaces to include a new signMessage method for all address types.
  • Modifies the dialog for signing/verifying messages to support BIP 322.
  • Modify verifymessage for verbosity of BIP 322 details.
  • Implement new logic in src/script/sign.cpp and src/script/sign.h for BIP 322 signature creation and verification.
  • Update utility functions and test cases for BIP 322 message signing and verification compatibility.

I just got started on this and would be using this as a rough roadmap. A rather trivial question would be: Where does the files for bip322 go? 😅 The repo is HUGE and I'm new here.

@yemmyharry
Copy link

yemmyharry commented Feb 28, 2024

@trevormil @Roasbeef pls, I'd like to contribute to this. can I pick it up?

@trevormil
Copy link
Author

@yemmyharry Yea, that would be great. I am not actively working on it. I kinda just settled with a workaround calling the JavaScript version from Go code. Could you keep me updated on progress?

@Roasbeef
Copy link
Member

Roasbeef commented Mar 1, 2024

I just got started on this and would be using this as a rough roadmap. A rather trivial question would be: Where does the files for bip322 go? 😅 The repo is HUGE and I'm new here.

@AbhinavMir I think we'd add the bip322 code to the txscript package (where all the other Script logic lives). IIUC, BIP 322 is just a way to make a "fake transaction" to show that if an output were created with a given pkScript, you can spend it with a valid witness. The txscript package has all the contents (along with the wire) package needed to do such a construction.

@yemmyharry sure, feel free to use this issue to get feedback on any WIP code you may have.

@trevormil
Copy link
Author

trevormil commented May 27, 2024

cc: @Roasbeef @AbhinavMir @yemmyharry @mohamedawnallah

Recently noticed that Unisat wallet a BIP322 Go package and was able to use it along with btcsuite for my use cases. I have provided the code below and is available via a Gist (https://gist.github.com/trevormil/7c8c3bec3cac94a2af3c1d4edf95ac2b). If you would like to use it or merge it into the library, feel free!

The goal of my code was to simply verify Phantom Wallet Bitcoin signatures in Go. Phantom uses P2WPKH BIP322 verification, so this code is only targeted to that specific algorithm (and not others like P2SH-P2WPKH and single-key-spend P2TR BIP-322 verification).

Behind the scenes, Phantom relies (or is at least compatible with) on the bip322-js npm package. This code is basically the equivalent of

Verifier.verifySignature(address, message, signature)

Code Snippet:

package main

import (
	"encoding/base64"
	"log"

	"github.com/btcsuite/btcd/btcutil"
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btcd/wire"

	bip322 "github.com/unisat-wallet/libbrc20-indexer/utils/bip322"
)

func convertAddressToScriptPubkey(address string) []byte {
	btcAddress, err := btcutil.DecodeAddress(address, &chaincfg.MainNetParams)
	if err != nil {
		panic(err)
	}

	outputScript, err := txscript.PayToAddrScript(btcAddress)
	if err != nil {
		panic(err)
	}

	return outputScript
}

func main() {
	//You can replace these with the actual values you want to verify
	//These are in the format used by bip322-js
	//This is for P2WPKH BIP322 verification
	message := "Hello World"
	signature := "AkcwRAIgZRfIY3p7/DoVTty6YZbWS71bc5Vct9p9Fia83eRmw2QCICK/ENGfwLtptFluMGs2KsqoNSk89pO7F29zJLUx9a/sASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI="
	signerAddress := "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l"

	//These will be in the following format:
	//[0x02 or 0x03] [LENGTH_BYTE, ...(LENGTH bytes that go into witness[0])] [0x21, ...(33 byte (len = 0x21) public key that was used to sign the message)]
	//- First byte is either a 0x02 or 0x03 (not sure exactly why but apparently it is - https://github.com/ACken2/bip322-js/blob/f0f9373b3a1da19e017c518b891522eaa4bcccdd/src/helpers/Address.ts#L85)
	//- Next part is the details that go into witness[0] (length of this part is determined by the second byte) - again, not exactly sure what this is
	//- Last part is the public key that was used to sign the message (33 bytes) - There is a length byte 0x21 before this part to denote the length of the public key (0x21 = 33)
	encodedSigBytes, err := base64.StdEncoding.DecodeString(signature)
	if err != nil {
		panic(err)
	}

	//Convert the address to a public key script (I believe this is the denotation for a pay-to-this-address script but not 100% sure)
	pkScript := convertAddressToScriptPubkey(signerAddress)

	//Decode the length of the witness[0] part
	encodedSigLenByte := encodedSigBytes[1]
	encodedSigLen := int(encodedSigLenByte)

	//Extract witness[0] and witness[1] from the encoded signature
	PUB_KEY_LEN := 33
	encodedSig := encodedSigBytes[len(encodedSigBytes)-PUB_KEY_LEN-1-encodedSigLen : len(encodedSigBytes)-PUB_KEY_LEN-1]
	pubKey := encodedSigBytes[len(encodedSigBytes)-33:]

	//Recreate the witness to pass into the VerifySignature function
	witness := wire.TxWitness{
		encodedSig,
		pubKey,
	}

	//This is the BIP322 verification function from the Unisat wallet
	verified := bip322.VerifySignature(witness, pkScript, message)
	log.Println("BIP 322 Verified:", verified)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants