passing test

This commit is contained in:
shwoop 2025-07-02 15:33:48 +02:00
parent 5c54198a68
commit 35e187b8f7
No known key found for this signature in database
GPG key ID: 95A35B68C1E5F95A
4 changed files with 75 additions and 23 deletions

View file

@ -256,3 +256,23 @@ func PeerInfoFromContext(ctx context.Context) PeerInfo {
info, _ := ctx.Value(peerInfoContextKey{}).(PeerInfo)
return info
}
// ContextWithMockPeerInfo is a helper function to create a context with a mock peer info.
// It is used in tests to simulate a peer info.
func ContextWithMockPeerInfo(ctx context.Context, transport, source, account string) context.Context {
peerInfo := PeerInfo{
Transport: transport,
HTTP: struct {
Version string
UserAgent string
Origin string
Host string
}{
Version: "1.1",
UserAgent: "test",
Origin: source,
Host: "test",
},
}
return context.WithValue(ctx, peerInfoContextKey{}, peerInfo)
}

View file

@ -17,6 +17,7 @@
package core_test
import (
"cmp"
"bytes"
"context"
"encoding/json"
@ -32,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/signer/core"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
"github.com/stretchr/testify/require"
@ -1068,14 +1070,23 @@ func TestSignInWithEtheriumValid(t *testing.T) {
testFiles, err := os.ReadDir(filepath.Join("testdata", "siwe"))
require.NoError(t, err)
var messages map[string]string
type TestData struct {
Msg string `json:"msg"`
Account string `json:"account"`
RequestContext struct {
Transport string `json:"transport"`
Source string `json:"source"`
Account string `json:"account"`
} `json:"request_context"`
}
var messages map[string]TestData
var expectingWarning bool
for _, fInfo := range testFiles {
if !strings.HasSuffix(fInfo.Name(), "json") {
continue
}
if fInfo.Name() != "warning_uris.json" {
if fInfo.Name() != "valid_eip1271.json" {
continue
}
expectingWarning = strings.HasPrefix(fInfo.Name(), "warning")
@ -1086,7 +1097,7 @@ func TestSignInWithEtheriumValid(t *testing.T) {
err = json.Unmarshal(jsonFile, &messages)
require.NoError(t, err)
for testName, message := range messages {
for testName, testData := range messages {
t.Run(testName, func(t *testing.T) {
t.Parallel()
@ -1098,9 +1109,13 @@ func TestSignInWithEtheriumValid(t *testing.T) {
require.NoError(t, err)
a := common.NewMixedcaseAddress(list[0])
ctx := rpc.ContextWithMockPeerInfo(context.Background(), testData.RequestContext.Transport, testData.RequestContext.Source, testData.Account)
account := cmp.Or(testData.Account, a.Address().Hex())
message := strings.ReplaceAll(testData.Msg, "{{Account}}", account)
control.approveCh <- "Y"
control.inputCh <- "a_long_password"
signature, err := api.SignData(context.Background(), apitypes.TextPlain.Mime, a, hexutil.Encode([]byte(message)))
signature, err := api.SignData(ctx, apitypes.TextPlain.Mime, a, hexutil.Encode([]byte(message)))
if expectingWarning {
// todo: check UI for warning message

View file

@ -25,24 +25,27 @@ import (
"github.com/ethereum/go-ethereum/common"
)
// Message size
var messageSize = `(?:\d+)`
// Regular expression to match SIWE messages
// Scheme (optional)
var scheme = `(?:[a-zA-Z][a-zA-Z0-9+\-.]*://)?`
var scheme = `([a-zA-Z][a-zA-Z0-9+\-.]*://)?`
// Domain
var domain = `(?:[^ ]+)`
var domain = `([^ ]+)`
// Static message
var wantsMsg = ` wants you to sign in with your Ethereum account:\n`
// Ethereum address (with basic 0x prefix + 40 hex digits)
var address = `(?:0x[a-fA-F0-9]{40})\n`
var address = `(0x[a-fA-F0-9]{40})\n`
// Optional statement (any line not containing "\n\n")
var statement = `(?:[^\n]+\n)?`
// URI
var uri = `URI: (.+)\n`
var uri = `URI: (?:.+)\n`
// Version
var version = `Version: 1\n`
@ -51,25 +54,25 @@ var version = `Version: 1\n`
var chainID = `Chain ID: (\d+)\n`
// Nonce (min 8 alphanumeric characters)
var nonce = `Nonce: [a-zA-Z0-9]{8,}\n`
var nonce = `Nonce: (?:[a-zA-Z0-9]{8,})\n`
// Issued At (RFC 3339 date-time)
var issuedAt = `Issued At: ([0-9T:\-+.Z]+)`
var issuedAt = `Issued At: (?:[0-9T:\-+.Z]+)`
// Optional Expiration Time
var expiration = `(?:\nExpiration Time: ([0-9T:\-+.Z]+))?`
var expiration = `(?:\nExpiration Time: (?:[0-9T:\-+.Z]+))?`
// Optional Not Before
var notBefore = `(?:\nNot Before: ([0-9T:\-+.Z]+))?`
var notBefore = `(?:\nNot Before: (?:[0-9T:\-+.Z]+))?`
// Optional Request ID
var requestID = `(?:\nRequest ID: ([^\n]+))?`
var requestID = `(?:\nRequest ID: (?:[^\n]+))?`
// Optional Resources
var resources = `(?:\nResources:(?:\n- .+)+)?`
// SIWE Message Regex
var siweMessageRegex = regexp.MustCompile(`(?m)^` + scheme + domain + wantsMsg +
var siweMessageRegex = regexp.MustCompile(`(?m)^` + messageSize + scheme + domain + wantsMsg +
address + `\n` + statement + `\n` +
uri + version + chainID + nonce + issuedAt +
expiration + notBefore + requestID + resources + `$`)
@ -85,18 +88,19 @@ func validateSIWE(req *SignDataRequest) error {
if !strings.Contains(s, "wants you to sign in with your Ethereum account") {
continue
}
patterns := siweMessageRegex.FindStringSubmatch(s)
if len(patterns) != 15 {
if patterns == nil {
return ErrMalformedSIWEMEssage
}
scheme := "https"
if patterns[0] != "" {
scheme = patterns[0]
if patterns[1] != "" {
scheme = patterns[1]
}
if err := validateDomain(req, scheme, patterns[1]); err != nil {
if err := validateDomain(req, scheme, patterns[2]); err != nil {
return err
}
if err := validateAddress(req, patterns[2]); err != nil {
if err := validateAddress(req, patterns[3]); err != nil {
return err
}
}
@ -105,8 +109,9 @@ func validateSIWE(req *SignDataRequest) error {
func validateDomain(request *SignDataRequest, scheme, domain string) error {
siweOrigin := fmt.Sprintf("%s://%s", scheme, domain)
if siweOrigin != request.Meta.Origin {
return fmt.Errorf("sign in request domain (%s) does not match source: %s", siweOrigin, request.Meta.Origin)
requestOrigin := fmt.Sprintf("%s://%s", request.Meta.Scheme, request.Meta.Origin)
if siweOrigin != requestOrigin {
return fmt.Errorf("sign in request domain (%s) does not match source: %s", siweOrigin, requestOrigin)
}
return nil
}

View file

@ -1,4 +1,16 @@
{
"argent": "localhost:4361 wants you to sign in with your Ethereum account:\n0xa5b3A53800cD49669F34DE80f2C569c6D4Ca3009\n\nSIWE Notepad Example\n\nURI: http://localhost:4361\nVersion: 1\nChain ID: 1\nNonce: FbYd6TNB4m0IUHDG7\nIssued At: 2022-04-19T18:55:04.444Z",
"loopring": "localhost:4361 wants you to sign in with your Ethereum account:\n0x0e565A6dFc43DE21455a67bbF196f7F7b15447A7\n\nSIWE Notepad Example\n\nURI: http://localhost:4361\nVersion: 1\nChain ID: 1\nNonce: b19JyMHnM0Jdm20as\nIssued At: 2022-04-19T18:57:09.490Z"
"argent": {
"msg": "localhost:4361 wants you to sign in with your Ethereum account:\n{{Account}}\n\nSIWE Notepad Example\n\nURI: http://localhost:4361\nVersion: 1\nChain ID: 1\nNonce: FbYd6TNB4m0IUHDG7\nIssued At: 2022-04-19T18:55:04.444Z",
"request_context": {
"transport": "https",
"source": "localhost:4361"
}
},
"loopring": {
"msg": "localhost:4361 wants you to sign in with your Ethereum account:\n{{Account}}\n\nSIWE Notepad Example\n\nURI: http://localhost:4361\nVersion: 1\nChain ID: 1\nNonce: b19JyMHnM0Jdm20as\nIssued At: 2022-04-19T18:57:09.490Z",
"request_context": {
"transport": "https",
"source": "localhost:4361"
}
}
}