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

Add validation to sample remote signer #100

Merged
merged 3 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/remote-signing-server/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/btcsuite/btcd v0.24.0 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/btcsuite/btcd/btcutil v1.1.5 // indirect
github.com/btcsuite/btcd/btcutil/psbt v1.1.9 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect
github.com/bytedance/sonic v1.9.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions examples/remote-signing-server/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9Ur
github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE=
github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8=
github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00=
github.com/btcsuite/btcd/btcutil/psbt v1.1.9 h1:UmfOIiWMZcVMOLaN+lxbbLSuoINGS1WmK1TZNI0b4yk=
github.com/btcsuite/btcd/btcutil/psbt v1.1.9/go.mod h1:ehBEvU91lxSlXtA+zZz3iFYx7Yq9eqnKx4/kSrnsvMY=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ=
Expand Down
4 changes: 2 additions & 2 deletions examples/remote-signing-server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func main() {
case objects.WebhookEventTypeRemoteSigning:
if config.RespondDirectly {
resp, err := remotesigning.GraphQLResponseForRemoteSigningWebhook(
remotesigning.PositiveValidator{}, *event, config.MasterSeed)
remotesigning.HashValidator{}, *event, config.MasterSeed)
if err != nil {
log.Printf("ERROR: Unable to handle remote signing webhook: %s", err)
c.AbortWithStatus(http.StatusInternalServerError)
Expand All @@ -80,7 +80,7 @@ func main() {
}
} else {
resp, err := remotesigning.HandleRemoteSigningWebhook(
lsClient, remotesigning.PositiveValidator{}, *event, config.MasterSeed)
lsClient, remotesigning.HashValidator{}, *event, config.MasterSeed)
if err != nil {
log.Printf("ERROR: Unable to handle remote signing webhook: %s", err)
c.AbortWithStatus(http.StatusInternalServerError)
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/btcsuite/btcd/btcutil v1.1.5 // indirect
github.com/btcsuite/btcd/btcutil v1.1.5
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
Expand All @@ -27,6 +27,7 @@ require (

require (
github.com/btcsuite/btcd v0.24.0
github.com/btcsuite/btcd/btcutil/psbt v1.1.9
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9Ur
github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE=
github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8=
github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00=
github.com/btcsuite/btcd/btcutil/psbt v1.1.9 h1:UmfOIiWMZcVMOLaN+lxbbLSuoINGS1WmK1TZNI0b4yk=
github.com/btcsuite/btcd/btcutil/psbt v1.1.9/go.mod h1:ehBEvU91lxSlXtA+zZz3iFYx7Yq9eqnKx4/kSrnsvMY=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ=
Expand Down
62 changes: 61 additions & 1 deletion remotesigning/validation.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package remotesigning

import (
"bytes"
"encoding/hex"
"errors"
"regexp"

"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/btcutil/psbt"
"github.com/btcsuite/btcd/txscript"
)

Expand All @@ -26,6 +29,63 @@ func GetPaymentHashFromScript(scriptHex string) (*string, error) {
if len(match) > 0 {
return &match[1], nil
} else {
return nil, errors.New("No match found")
return nil, errors.New("no match found")
}
}

func CalculateWitnessHash(amount int64, script string, transaction string) (*string, error) {
decodedTx, err := hex.DecodeString(transaction)
if err != nil {
return nil, err
}

tx, err := btcutil.NewTxFromBytes(decodedTx)
if err != nil {
return nil ,err
}

decodedScript, err := hex.DecodeString(script)
if err != nil {
return nil ,err
}

prevOutFetcher := txscript.NewCannedPrevOutputFetcher(
decodedScript, amount,
)

txhash := txscript.NewTxSigHashes(tx.MsgTx(), prevOutFetcher)
hash, err := txscript.CalcWitnessSigHash(decodedScript, txhash, txscript.SigHashAll, tx.MsgTx(), 0, amount)
if err != nil {
return nil, err
}

result := hex.EncodeToString(hash)

return &result, nil
}

func CalculateWitnessHashPSBT(transaction string) (*string, error) {
transactionBytes, err := hex.DecodeString(transaction)
if err != nil {
return nil, err
}
// Reader for the PSBT.
psbtBytes := []byte(transactionBytes)
r := bytes.NewReader(psbtBytes)

// Create instance of a PSBT.
p, err := psbt.NewFromRawBytes(r, false)
if err != nil {
return nil, err
}
prevOutFetcher := txscript.NewCannedPrevOutputFetcher(
p.Inputs[0].WitnessUtxo.PkScript, int64(p.Inputs[0].WitnessUtxo.Value),
)
sigHashes := txscript.NewTxSigHashes(p.UnsignedTx, prevOutFetcher)
hash, err := txscript.CalcWitnessSigHash(p.Inputs[0].WitnessScript, sigHashes, txscript.SigHashAll, p.UnsignedTx, 0, int64(p.Inputs[0].WitnessUtxo.Value))
if err != nil {
return nil, err
}
result := hex.EncodeToString(hash)
return &result, nil
}
38 changes: 37 additions & 1 deletion remotesigning/validator.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
// Copyright ©, 2023-present, Lightspark Group, Inc. - All Rights Reserved
package remotesigning

import "github.com/lightsparkdev/go-sdk/webhooks"
import (
"strings"

"github.com/lightsparkdev/go-sdk/webhooks"
)

// Validator an interface which decides whether to sign or reject a remote signing webhook event.
type Validator interface {
Expand All @@ -13,3 +17,35 @@ type PositiveValidator struct{}
func (v PositiveValidator) ShouldSign(webhooks.WebhookEvent) bool {
return true
}

type HashValidator struct {}

func (v HashValidator) ShouldSign(webhookEvent webhooks.WebhookEvent) bool {
request, err := ParseDeriveAndSignRequest(webhookEvent)
if err != nil {
// Only validate DeriveAndSignRequest events
return true
}

for _, signing := range request.SigningJobs {
if strings.HasSuffix(signing.DerivationPath, "/2") {
msg, err := CalculateWitnessHashPSBT(*signing.Transaction)
if err != nil {
return false
}
if strings.Compare(*msg, signing.Message) != 0 {
return false
}
} else {
msg, err := CalculateWitnessHash(*signing.Amount, *signing.Script, *signing.Transaction)
if err != nil {
return false
}
if strings.Compare(*msg, signing.Message) != 0 {
return false
}
}
}

return true
}
Loading