diff --git a/README.md b/README.md index 3a1629f464..9ccfe933aa 100644 --- a/README.md +++ b/README.md @@ -29,12 +29,6 @@ or, to build the full suite of utilities: make all ``` -If make `geth fails` due to a missing `build/ci.go` file or related error, you can instead build Geth directly using: - -```shell -go build -o geth ./cmd/geth -``` - ## Executables The go-ethereum project comes with several wrappers/executables found in the `cmd` diff --git a/cmd/clef/siwe-validator/README.md b/cmd/clef/siwe-validator/README.md new file mode 100644 index 0000000000..8b967fce19 --- /dev/null +++ b/cmd/clef/siwe-validator/README.md @@ -0,0 +1,75 @@ +# SIWE Validator for Clef + +This directory implements a minimal Sign-In with Ethereum (SIWE) message validator for Clef, +designed to verify incoming EIP-4361 formatted messages before approving signing requests. + +The validator checks critical fields including: + +- **Domain**: Ensures the requested domain matches an expected domain (e.g., `localhost:3000`). +- **Ethereum Address**: Verifies that a valid `0x` prefixed address is provided. +- **URI**: Confirms the target URI matches the expected resource. +- **Version**: Verifies that the SIWE version is `1`. +- **ChainID**: Ensures the chain ID matches the intended network (e.g., `1` for Ethereum Mainnet). +- **Nonce**: Checks that a unique nonce is included to prevent replay attacks. +- **Issued At**: Ensures the issued timestamp follows the ISO 8601/RFC3339 format. + +Unlike previous implementations relying on external libraries such as `spruceid/siwe-go`, +this version introduces a **lightweight internal parser** that directly processes SIWE messages, +eliminating external dependencies and improving maintainability. + +--- + +## How It Works + +Upon receiving a signing request, Clef will invoke the `siwe-validator` binary, +passing the SIWE message via standard input (stdin). + +The validator parses the message line-by-line and verifies mandatory fields according to EIP-4361 specifications. + +If validation passes, Clef proceeds with the signing flow. Otherwise, signing is rejected. + +### Manually Testing the Validator + +You can manually simulate a Clef signing request by piping a SIWE message into `siwe-validator`. +For example: + +```bash +echo "localhost:3000 wants you to sign in with your Ethereum account: +0x32e0556aeC41a34C3002a264f4694193EBCf44F7 + +URI: https://localhost:3000 +Version: 1 +ChainID: 1 +Nonce: 32891756 +Issued At: 2025-04-26T12:00:00Z" | ./siwe-validator +``` + +If the message is valid, `siwe-validator` will exit silently with code `0`. +If the message is invalid, an error message will be printed to `stderr`. + +--- + +## Test Data + +The `testdata/genmsg_test.go` file provides a minimal static SIWE message generator for manual testing purposes. + +It outputs a standardized EIP-4361 formatted message, allowing developers to easily validate the `siwe-validator` behavior. + +This file is intended for manual verification only and is not part of the production codebase or automated tests. + +To manually generate and test a SIWE message: + +```bash +cd cmd/clef/siwevalidator +go run testdata/genmsg_test.go | ./siwe-validator +``` + +--- + +## Notes + +- The validator currently supports basic field validation only. +- Future improvements may include supporting optional fields like `Resources`, `Expiration Time`, and `Request ID`. +- This implementation follows the EIP-4361. + +--- diff --git a/cmd/clef/siwe-validator/main.go b/cmd/clef/siwe-validator/main.go new file mode 100644 index 0000000000..a7cf771c5f --- /dev/null +++ b/cmd/clef/siwe-validator/main.go @@ -0,0 +1,69 @@ +package main + +import ( + "fmt" + "io" + "os" + "strings" +) + +func main() { + raw, err := io.ReadAll(os.Stdin) + if err != nil { + fmt.Fprintln(os.Stderr, "failed to read stdin:", err) + os.Exit(1) + } + + lines := strings.Split(string(raw), "\n") + + if len(lines) < 8 { + fmt.Fprintln(os.Stderr, "invalid message: not enough lines") + os.Exit(1) + } + + domainLine := lines[0] + addressLine := lines[1] + uriLine := lines[3] + versionLine := lines[4] + chainIDLine := lines[5] + nonceLine := lines[6] + issuedAtLine := lines[7] + + if !strings.Contains(domainLine, "localhost:3000") { + fmt.Fprintf(os.Stderr, "domain mismatch: %s\n", domainLine) + os.Exit(1) + } + + if !strings.HasPrefix(addressLine, "0x") { + fmt.Fprintf(os.Stderr, "invalid address: %s\n", addressLine) + os.Exit(1) + } + + if !strings.HasPrefix(uriLine, "URI: https://localhost:3000") { + fmt.Fprintf(os.Stderr, "uri mismatch: %s\n", uriLine) + os.Exit(1) + } + + if !strings.Contains(versionLine, "Version: 1") { + fmt.Fprintf(os.Stderr, "version mismatch: %s\n", versionLine) + os.Exit(1) + } + + if !strings.Contains(chainIDLine, "ChainID: 1") { + fmt.Fprintf(os.Stderr, "chainID mismatch: %s\n", chainIDLine) + os.Exit(1) + } + + if !strings.Contains(nonceLine, "Nonce:") { + fmt.Fprintf(os.Stderr, "nonce missing: %s\n", nonceLine) + os.Exit(1) + } + + if !strings.Contains(issuedAtLine, "Issued At:") { + fmt.Fprintf(os.Stderr, "issued at missing: %s\n", issuedAtLine) + os.Exit(1) + } + + // 全部檢查通過 + os.Exit(0) +} diff --git a/cmd/clef/siwe-validator/testdata/genmsg_test.go b/cmd/clef/siwe-validator/testdata/genmsg_test.go new file mode 100644 index 0000000000..ea25be6348 --- /dev/null +++ b/cmd/clef/siwe-validator/testdata/genmsg_test.go @@ -0,0 +1,17 @@ +package main + +import ( + "fmt" +) + +func main() { + fmt.Print(`localhost:3000 wants you to sign in with your Ethereum account: +0x32e0556aeC41a34C3002a264f4694193EBCf44F7 + +URI: https://localhost:3000 +Version: 1 +ChainID: 1 +Nonce: 32891756 +Issued At: 2025-04-26T12:00:00Z +`) +}