Skip to content

Commit

Permalink
refactor: consolidate Ethereum signature verification into crypto pac…
Browse files Browse the repository at this point in the history
…kage and remove legacy code
  • Loading branch information
Bewinxed committed Jan 18, 2025
1 parent fd8b16d commit 6e4c871
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 59 deletions.
3 changes: 1 addition & 2 deletions internal/api/provider/eip4361.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

"github.com/supabase/auth/internal/conf"
"github.com/supabase/auth/internal/crypto"
"github.com/supabase/auth/internal/utilities/web3/ethereum"
siws "github.com/supabase/auth/internal/utilities/web3/solana"
"golang.org/x/oauth2"
)
Expand Down Expand Up @@ -108,7 +107,7 @@ func (p *EIP4361Provider) VerifySignedMessage(msg *SignedMessage) (*UserProvided
}

func (p *EIP4361Provider) verifyEthereumSignature(msg *SignedMessage) error {
return ethereum.VerifySignature(msg.Message, msg.Signature, msg.Address)
return crypto.VerifyEthereumSignature(msg.Message, msg.Signature, msg.Address)
}

func (p *EIP4361Provider) verifySolanaSignature(msg *SignedMessage) error {
Expand Down
52 changes: 52 additions & 0 deletions internal/crypto/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ import (

"golang.org/x/crypto/hkdf"

"encoding/hex"

"github.com/btcsuite/btcutil/base58"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
siws "github.com/supabase/auth/internal/utilities/web3/solana"
)

Expand Down Expand Up @@ -213,3 +217,51 @@ func VerifySIWS(

return nil
}

func VerifyEthereumSignature(message string, signature string, address string) error {
// Remove 0x prefix if present
signature = removeHexPrefix(signature)
address = removeHexPrefix(address)

// Convert signature hex to bytes
sigBytes, err := hex.DecodeString(signature)
if err != nil {
return fmt.Errorf("invalid signature hex: %w", err)
}

// Adjust V value in signature (Ethereum specific)
if len(sigBytes) != 65 {
return fmt.Errorf("invalid signature length")
}
if sigBytes[64] < 27 {
sigBytes[64] += 27
}

// Hash the message according to EIP-191
prefixedMessage := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(message), message)
hash := crypto.Keccak256Hash([]byte(prefixedMessage))

// Recover public key from signature
pubKey, err := crypto.SigToPub(hash.Bytes(), sigBytes)
if err != nil {
return fmt.Errorf("error recovering public key: %w", err)
}

// Derive Ethereum address from public key
recoveredAddr := crypto.PubkeyToAddress(*pubKey)
checkAddr := common.HexToAddress(address)

// Compare addresses
if recoveredAddr != checkAddr {
return fmt.Errorf("signature not from expected address")
}

return nil
}

func removeHexPrefix(signature string) string {
if strings.HasPrefix(signature, "0x") {
return strings.TrimPrefix(signature, "0x")
}
return signature
}
57 changes: 0 additions & 57 deletions internal/utilities/web3/ethereum/verify.go
Original file line number Diff line number Diff line change
@@ -1,57 +0,0 @@
package ethereum

import (
"encoding/hex"
"fmt"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)

func VerifySignature(message string, signature string, address string) error {
// Remove 0x prefix if present
signature = removeHexPrefix(signature)
address = removeHexPrefix(address)

// Convert signature hex to bytes
sigBytes, err := hex.DecodeString(signature)
if err != nil {
return fmt.Errorf("invalid signature hex: %w", err)
}

// Adjust V value in signature (Ethereum specific)
if len(sigBytes) != 65 {
return fmt.Errorf("invalid signature length")
}
if sigBytes[64] < 27 {
sigBytes[64] += 27
}

// Hash the message according to EIP-191
prefixedMessage := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(message), message)
hash := crypto.Keccak256Hash([]byte(prefixedMessage))

// Recover public key from signature
pubKey, err := crypto.SigToPub(hash.Bytes(), sigBytes)
if err != nil {
return fmt.Errorf("error recovering public key: %w", err)
}

// Derive Ethereum address from public key
recoveredAddr := crypto.PubkeyToAddress(*pubKey)
checkAddr := common.HexToAddress(address)

// Compare addresses
if recoveredAddr != checkAddr {
return fmt.Errorf("signature not from expected address")
}

return nil
}

func removeHexPrefix(s string) string {
if len(s) > 2 && s[0:2] == "0x" {
return s[2:]
}
return s
}

0 comments on commit 6e4c871

Please sign in to comment.