mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 13:16:42 +00:00
passing test
This commit is contained in:
parent
5c54198a68
commit
35e187b8f7
4 changed files with 75 additions and 23 deletions
|
|
@ -256,3 +256,23 @@ func PeerInfoFromContext(ctx context.Context) PeerInfo {
|
||||||
info, _ := ctx.Value(peerInfoContextKey{}).(PeerInfo)
|
info, _ := ctx.Value(peerInfoContextKey{}).(PeerInfo)
|
||||||
return info
|
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)
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package core_test
|
package core_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cmp"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
@ -32,6 +33,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"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"
|
||||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
@ -1068,14 +1070,23 @@ func TestSignInWithEtheriumValid(t *testing.T) {
|
||||||
testFiles, err := os.ReadDir(filepath.Join("testdata", "siwe"))
|
testFiles, err := os.ReadDir(filepath.Join("testdata", "siwe"))
|
||||||
require.NoError(t, err)
|
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
|
var expectingWarning bool
|
||||||
|
|
||||||
for _, fInfo := range testFiles {
|
for _, fInfo := range testFiles {
|
||||||
if !strings.HasSuffix(fInfo.Name(), "json") {
|
if !strings.HasSuffix(fInfo.Name(), "json") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if fInfo.Name() != "warning_uris.json" {
|
if fInfo.Name() != "valid_eip1271.json" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
expectingWarning = strings.HasPrefix(fInfo.Name(), "warning")
|
expectingWarning = strings.HasPrefix(fInfo.Name(), "warning")
|
||||||
|
|
@ -1086,7 +1097,7 @@ func TestSignInWithEtheriumValid(t *testing.T) {
|
||||||
err = json.Unmarshal(jsonFile, &messages)
|
err = json.Unmarshal(jsonFile, &messages)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
for testName, message := range messages {
|
for testName, testData := range messages {
|
||||||
t.Run(testName, func(t *testing.T) {
|
t.Run(testName, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
@ -1098,9 +1109,13 @@ func TestSignInWithEtheriumValid(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
a := common.NewMixedcaseAddress(list[0])
|
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.approveCh <- "Y"
|
||||||
control.inputCh <- "a_long_password"
|
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 {
|
if expectingWarning {
|
||||||
// todo: check UI for warning message
|
// todo: check UI for warning message
|
||||||
|
|
|
||||||
|
|
@ -25,24 +25,27 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Message size
|
||||||
|
var messageSize = `(?:\d+)`
|
||||||
|
|
||||||
// Regular expression to match SIWE messages
|
// Regular expression to match SIWE messages
|
||||||
// Scheme (optional)
|
// Scheme (optional)
|
||||||
var scheme = `(?:[a-zA-Z][a-zA-Z0-9+\-.]*://)?`
|
var scheme = `([a-zA-Z][a-zA-Z0-9+\-.]*://)?`
|
||||||
|
|
||||||
// Domain
|
// Domain
|
||||||
var domain = `(?:[^ ]+)`
|
var domain = `([^ ]+)`
|
||||||
|
|
||||||
// Static message
|
// Static message
|
||||||
var wantsMsg = ` wants you to sign in with your Ethereum account:\n`
|
var wantsMsg = ` wants you to sign in with your Ethereum account:\n`
|
||||||
|
|
||||||
// Ethereum address (with basic 0x prefix + 40 hex digits)
|
// 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")
|
// Optional statement (any line not containing "\n\n")
|
||||||
var statement = `(?:[^\n]+\n)?`
|
var statement = `(?:[^\n]+\n)?`
|
||||||
|
|
||||||
// URI
|
// URI
|
||||||
var uri = `URI: (.+)\n`
|
var uri = `URI: (?:.+)\n`
|
||||||
|
|
||||||
// Version
|
// Version
|
||||||
var version = `Version: 1\n`
|
var version = `Version: 1\n`
|
||||||
|
|
@ -51,25 +54,25 @@ var version = `Version: 1\n`
|
||||||
var chainID = `Chain ID: (\d+)\n`
|
var chainID = `Chain ID: (\d+)\n`
|
||||||
|
|
||||||
// Nonce (min 8 alphanumeric characters)
|
// 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)
|
// Issued At (RFC 3339 date-time)
|
||||||
var issuedAt = `Issued At: ([0-9T:\-+.Z]+)`
|
var issuedAt = `Issued At: (?:[0-9T:\-+.Z]+)`
|
||||||
|
|
||||||
// Optional Expiration Time
|
// Optional Expiration Time
|
||||||
var expiration = `(?:\nExpiration Time: ([0-9T:\-+.Z]+))?`
|
var expiration = `(?:\nExpiration Time: (?:[0-9T:\-+.Z]+))?`
|
||||||
|
|
||||||
// Optional Not Before
|
// Optional Not Before
|
||||||
var notBefore = `(?:\nNot Before: ([0-9T:\-+.Z]+))?`
|
var notBefore = `(?:\nNot Before: (?:[0-9T:\-+.Z]+))?`
|
||||||
|
|
||||||
// Optional Request ID
|
// Optional Request ID
|
||||||
var requestID = `(?:\nRequest ID: ([^\n]+))?`
|
var requestID = `(?:\nRequest ID: (?:[^\n]+))?`
|
||||||
|
|
||||||
// Optional Resources
|
// Optional Resources
|
||||||
var resources = `(?:\nResources:(?:\n- .+)+)?`
|
var resources = `(?:\nResources:(?:\n- .+)+)?`
|
||||||
|
|
||||||
// SIWE Message Regex
|
// SIWE Message Regex
|
||||||
var siweMessageRegex = regexp.MustCompile(`(?m)^` + scheme + domain + wantsMsg +
|
var siweMessageRegex = regexp.MustCompile(`(?m)^` + messageSize + scheme + domain + wantsMsg +
|
||||||
address + `\n` + statement + `\n` +
|
address + `\n` + statement + `\n` +
|
||||||
uri + version + chainID + nonce + issuedAt +
|
uri + version + chainID + nonce + issuedAt +
|
||||||
expiration + notBefore + requestID + resources + `$`)
|
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") {
|
if !strings.Contains(s, "wants you to sign in with your Ethereum account") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
patterns := siweMessageRegex.FindStringSubmatch(s)
|
patterns := siweMessageRegex.FindStringSubmatch(s)
|
||||||
if len(patterns) != 15 {
|
if patterns == nil {
|
||||||
return ErrMalformedSIWEMEssage
|
return ErrMalformedSIWEMEssage
|
||||||
}
|
}
|
||||||
scheme := "https"
|
scheme := "https"
|
||||||
if patterns[0] != "" {
|
if patterns[1] != "" {
|
||||||
scheme = patterns[0]
|
scheme = patterns[1]
|
||||||
}
|
}
|
||||||
if err := validateDomain(req, scheme, patterns[1]); err != nil {
|
if err := validateDomain(req, scheme, patterns[2]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := validateAddress(req, patterns[2]); err != nil {
|
if err := validateAddress(req, patterns[3]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -105,8 +109,9 @@ func validateSIWE(req *SignDataRequest) error {
|
||||||
|
|
||||||
func validateDomain(request *SignDataRequest, scheme, domain string) error {
|
func validateDomain(request *SignDataRequest, scheme, domain string) error {
|
||||||
siweOrigin := fmt.Sprintf("%s://%s", scheme, domain)
|
siweOrigin := fmt.Sprintf("%s://%s", scheme, domain)
|
||||||
if siweOrigin != request.Meta.Origin {
|
requestOrigin := fmt.Sprintf("%s://%s", request.Meta.Scheme, request.Meta.Origin)
|
||||||
return fmt.Errorf("sign in request domain (%s) does not match source: %s", siweOrigin, request.Meta.Origin)
|
if siweOrigin != requestOrigin {
|
||||||
|
return fmt.Errorf("sign in request domain (%s) does not match source: %s", siweOrigin, requestOrigin)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
signer/core/testdata/siwe/valid_eip1271.json
vendored
16
signer/core/testdata/siwe/valid_eip1271.json
vendored
|
|
@ -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",
|
"argent": {
|
||||||
"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"
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue