Skip to content

Commit

Permalink
Simplify the fallback to ERC1271
Browse files Browse the repository at this point in the history
  • Loading branch information
0xdev22 committed Jan 19, 2024
1 parent 82ad3fa commit aef4087
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 32 deletions.
69 changes: 38 additions & 31 deletions connector/web3/web3.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
package web3

import (
"bytes"
"errors"
"fmt"
"github.com/dexidp/dex/connector"
Expand All @@ -13,21 +12,25 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"os"
)

type Config struct {
InfuraID string `json:"infuraId"`
RPCURL string `json:"rpcUrl"`
}

func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) {
w := &web3Connector{infuraID: c.InfuraID, logger: logger}

ethClient, err := createEthClient()
if err != nil {
return nil, err
if c.RPCURL != "" {
ethClient, err := createEthClient(c.RPCURL)
if err != nil {
return nil, err
}
w.ethClient = ethClient
} else {
logger.Warnf("No RPC URL specified, contract signature validation will not be available.")
}
w.ethClient = ethClient

return w, nil
}

Expand All @@ -41,39 +44,54 @@ func (c *web3Connector) InfuraID() string {
return c.infuraID
}

var erc1271magicValue = [4]byte{0x16, 0x26, 0xba, 0x7e}

// https://gist.github.com/dcb9/385631846097e1f59e3cba3b1d42f3ed#file-eth_sign_verify-go
func (c *web3Connector) Verify(address, msg, signedMsg string) (identity connector.Identity, err error) {
func (c *web3Connector) Verify(address, msg, signedMsg string) (connector.Identity, error) {
addrb := common.HexToAddress(address)

msgHash := signHash([]byte(msg))

identity, err := c.VerifyEOASignature(addrb, msgHash, signedMsg)
if err != nil {
return c.VerifyERC1271Signature(addrb, msgHash, signedMsg)
}

return identity, nil
}

func (c *web3Connector) VerifyEOASignature(addr common.Address, msgHash []byte, signedMsg string) (identity connector.Identity, err error) {
signb, err := hexutil.Decode(signedMsg)
if err != nil {
return identity, fmt.Errorf("could not decode hex string of signed nonce: %v", err)
}

msgHash := signHash([]byte(msg))
if len(signb) != 65 {
return identity, fmt.Errorf("signature has length %d != 65", len(signb))
}

// This is the v parameter in the signature. Per the yellow paper, 27 means even and 28
// means odd.
if signb[64] == 27 || signb[64] == 28 {
signb[64] -= 27
} else if signb[64] != 0 && signb[64] != 1 {
// We allow 0 or 1 because some non-conformant devices like Ledger use it.
return c.VerifyERC1271Signature(addrb, msgHash, signedMsg)
return identity, fmt.Errorf("v byte %d, not one of 0, 1, 27, or 28", signb[64])
}

pubKey, err := crypto.SigToPub(msgHash, signb)
if err != nil {
return c.VerifyERC1271Signature(addrb, msgHash, signedMsg)
return c.VerifyERC1271Signature(addr, msgHash, signedMsg)
}

recoveredAddr := crypto.PubkeyToAddress(*pubKey)
// These are byte arrays, so this is okay to do.
if recoveredAddr != addrb {
return c.VerifyERC1271Signature(addrb, msgHash, signedMsg)
if recoveredAddr != addr {
return identity, fmt.Errorf("hash was not signed by %s and not %s", recoveredAddr, addr)
}

identity.UserID = address
identity.Username = address
identity.UserID = addr.Hex()
identity.Username = addr.Hex()
return identity, nil
}

Expand All @@ -85,7 +103,7 @@ func (c *web3Connector) VerifyERC1271Signature(contractAddress common.Address, h

if c.ethClient == nil {
c.logger.Errorf("Eth client was not initialized successfully %v", err)
return identity, fmt.Errorf("error occurred completing authentication, please try again %w", err)
return identity, errors.New("can't attempt to validate signature, no Ethereum client available")
}
var msgHash [32]byte
copy(msgHash[:], hash)
Expand All @@ -99,14 +117,12 @@ func (c *web3Connector) VerifyERC1271Signature(contractAddress common.Address, h
return identity, fmt.Errorf("error occurred completing login %w", err)
}

isValid, err := ct.IsValidSignature(&bind.CallOpts{}, msgHash, signature)
result, err := ct.IsValidSignature(nil, msgHash, signature)
if err != nil {
return identity, fmt.Errorf("error occurred completing login %w", err)
}
resultVal := common.BytesToAddress(isValid[:])
truthyVal := common.HexToAddress("0x1626ba7e")

if !bytes.Equal(truthyVal.Bytes(), resultVal.Bytes()) {
if result != erc1271magicValue {
return identity, fmt.Errorf("given address and address recovered from signed message do not match")
}

Expand All @@ -120,15 +136,6 @@ func signHash(data []byte) []byte {
return accounts.TextHash(data)
}

func createEthClient() (bind.ContractBackend, error) {
rpcUrl := os.Getenv("ETH_RPC_CLIENT")
if rpcUrl != "" {
client, err := ethclient.Dial(rpcUrl)
if err != nil {
return nil, err
}
return client, nil
}

return nil, errors.New("could not initialize eth client with url")
func createEthClient(rpcUrl string) (bind.ContractBackend, error) {
return ethclient.Dial(rpcUrl)
}
2 changes: 1 addition & 1 deletion connector/web3/web3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ func TestBlockchainBackend(t *testing.T) {
msgHash: emptyByte,
signedMessage: hexutil.Encode(emptyByte),
shouldErr: true,
err: errors.New("error occurred completing authentication, please try again"),
err: errors.New("no Ethereum client available"),
}
},
}
Expand Down

0 comments on commit aef4087

Please sign in to comment.