Skip to content

feat(user_worker): SIWE core — EIP-4361 parser, EIP-191 ecrecover, EIP-55, RFC3339 (UNIT 1)#2

Merged
kingwingfly-claude merged 1 commit into
devfrom
feat/user-system-u1-siwe
Jul 5, 2026
Merged

feat(user_worker): SIWE core — EIP-4361 parser, EIP-191 ecrecover, EIP-55, RFC3339 (UNIT 1)#2
kingwingfly-claude merged 1 commit into
devfrom
feat/user-system-u1-siwe

Conversation

@kingwingfly

Copy link
Copy Markdown
Owner

Summary

UNIT 1 of the SIWE user system: replaces the `user_worker/src/siwe.rs` stub with a pure, host-testable implementation. No `worker` imports; public signatures unchanged from the frozen scaffold.

  • `parse_siwe` — strict line-oriented EIP-4361 parser: preamble/address/blank-line prologue, optional multi-line statement, ordered `URI`/`Version`/`Chain ID`/`Nonce`/`Issued At` fields, optional `Expiration Time`, tolerated trailing `Not Before`/`Request ID`/`Resources` (+ `- uri` lines); anything else rejected with `SiweError::Parse`.
  • `keccak256` — via `sha3::Keccak256`.
  • `recover_address` — EIP-191 personal_sign digest, 65-byte r||s||v hex signatures (v in {0,1,27,28}), low-s normalization with recovery-id parity flip, address from uncompressed pubkey keccak.
  • `to_checksum` — EIP-55; hash index bounded so over-long invalid input cannot panic.
  • `parse_rfc3339_epoch` — hand-rolled (no chrono): Z / ±HH:MM offsets, fractional seconds ignored, days-from-civil.

Test plan

  • `cargo check -p user_worker` ✅
  • `cargo test -p user_worker` ✅ (9 tests: ecrecover roundtrip incl. v=27 and negative cases, EIP-55 official vectors, parser accept/reject, RFC 3339 vectors incl. Z / +08:00 / -08:00 / fractional seconds)

🤖 Generated with Claude Code

…over, EIP-55, RFC3339)

UNIT 1: replace the siwe.rs stub with a pure, host-testable implementation:
- strict line-oriented EIP-4361 parser (ordered fields, optional statement /
  Expiration Time, tolerated Not Before / Request ID / Resources)
- keccak256 + EIP-191 personal_sign address recovery via k256 (low-s
  normalization with recovery-id parity flip, v in {0,1,27,28})
- EIP-55 checksum encoding
- hand-rolled RFC 3339 -> epoch seconds (Z / numeric offsets / fractional
  seconds, days-from-civil)

In-file unit tests: ecrecover roundtrip incl. v=27, EIP-55 official vectors,
parser accept/reject cases, RFC 3339 vectors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 4, 2026 15:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements UNIT 1 of the SIWE user system by replacing the prior siwe.rs stub with a pure, host-testable implementation covering EIP-4361 parsing, EIP-191 signature recovery (ecrecover), EIP-55 address checksumming, and RFC3339-to-epoch parsing, along with unit tests.

Changes:

  • Added a strict, line-oriented EIP-4361 (parse_siwe) parser with ordered required fields and tolerated trailing fields.
  • Implemented crypto helpers: keccak256, EIP-191 digest + recover_address, and to_checksum (EIP-55).
  • Added a hand-rolled parse_rfc3339_epoch and comprehensive unit tests for all components.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread user_worker/src/siwe.rs
Comment on lines +251 to +254
if !(1..=12).contains(&month) || !(1..=31).contains(&day) || hour > 23 || min > 59 || sec > 59
{
return None;
}
Comment thread user_worker/src/siwe.rs
Comment on lines +206 to +219
let hex_part = addr_lower.strip_prefix("0x").unwrap_or(addr_lower);
let hash = keccak256(hex_part.as_bytes());
let mut out = String::with_capacity(42);
out.push_str("0x");
// `.take(64)` bounds the hash index for over-long (invalid) inputs.
for (i, c) in hex_part.chars().enumerate().take(64) {
let nibble = if i % 2 == 0 { hash[i / 2] >> 4 } else { hash[i / 2] & 0xf };
if c.is_ascii_alphabetic() && nibble >= 8 {
out.push(c.to_ascii_uppercase());
} else {
out.push(c);
}
}
out
Comment thread user_worker/src/siwe.rs
Comment on lines +185 to +192
let digest = keccak256(
&[
b"\x19Ethereum Signed Message:\n",
message.len().to_string().as_bytes(),
message.as_bytes(),
]
.concat(),
);
@kingwingfly-claude kingwingfly-claude merged commit f64f63e into dev Jul 5, 2026
1 check passed
@kingwingfly-claude kingwingfly-claude deleted the feat/user-system-u1-siwe branch July 5, 2026 05:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants