Skip to content

Commit 7a15fb7

Browse files
Merge pull request #628 from JeneaVranceanu/fix/eip4361-captured-fields
fix: EIP4361 - improved validation by adding ability to extract invalid values for all fields
2 parents 6982038 + 55877e9 commit 7a15fb7

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

Sources/web3swift/Utils/EIP/EIP4361.swift

+30-1
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,37 @@ public final class EIP4361 {
7777
"^\(domain)\(address)\(statementParagraph)\(uri)\(version)\(chainId)\(nonce)\(issuedAt)\(expirationTime)\(notBefore)\(requestId)\(resourcesParagraph)$"
7878
}
7979

80+
private static var _eip4361OptionalPattern: String!
8081
private static var eip4361OptionalPattern: String {
81-
"^\(domain)(\(address))?\(statementParagraph)(\(uri))?(\(version))?(\(chainId))?(\(nonce))?(\(issuedAt))?\(expirationTime)\(notBefore)\(requestId)\(resourcesParagraph)$"
82+
guard _eip4361OptionalPattern == nil else { return _eip4361OptionalPattern! }
83+
84+
let domain = "(?<\(EIP4361Field.domain.rawValue)>(.*)) wants you to sign in with your Ethereum account:"
85+
let address = "\\n(?<\(EIP4361Field.address.rawValue)>.*)\\n\\n"
86+
let uri = "\\nURI: (?<\(EIP4361Field.uri.rawValue)>(.*)?)"
87+
let version = "\\nVersion: (?<\(EIP4361Field.version.rawValue)>.*)"
88+
let chainId = "\\nChain ID: (?<\(EIP4361Field.chainId.rawValue)>.*)"
89+
let nonce = "\\nNonce: (?<\(EIP4361Field.nonce.rawValue)>.*)"
90+
let issuedAt = "\\nIssued At: (?<\(EIP4361Field.issuedAt.rawValue)>(.*))"
91+
let expirationTime = "(\\nExpiration Time: (?<\(EIP4361Field.expirationTime.rawValue)>(.*)))?"
92+
let notBefore = "(\\nNot Before: (?<\(EIP4361Field.notBefore.rawValue)>(.*)))?"
93+
let requestId = "(\\nRequest ID: (?<\(EIP4361Field.requestId.rawValue)>.*))?"
94+
let resourcesParagraph = "(\\nResources:(?<\(EIP4361Field.resources.rawValue)>(.|\n)*))?"
95+
96+
let patternParts: [String] = ["^\(domain)",
97+
"(\(address))?",
98+
"\(statementParagraph)",
99+
"(\(uri))?",
100+
"(\(version))?",
101+
"(\(chainId))?",
102+
"(\(nonce))?",
103+
"(\(issuedAt))?",
104+
"\(expirationTime)",
105+
"\(notBefore)",
106+
"\(requestId)",
107+
"\(resourcesParagraph)$"]
108+
109+
_eip4361OptionalPattern = patternParts.joined()
110+
return _eip4361OptionalPattern!
82111
}
83112

84113
public static func validate(_ message: String) -> EIP4361ValidationResponse {

Tests/web3swiftTests/localTests/EIP4361Test.swift

+23
Original file line numberDiff line numberDiff line change
@@ -167,4 +167,27 @@ class EIP4361Test: XCTestCase {
167167

168168
XCTAssertEqual(validationResponse.capturedFields[.version], "123")
169169
}
170+
171+
func test_validEIP4361_allRequiredFieldsContainWrongData() {
172+
let rawSiweMessage = "service.invalid wants you to sign in with your Ethereum account:\nnot-a-hex-1234567890qwertyuiop1234567890qwertyuiop\n\nTHESTATEMENT123102938102938: aURIisSupposedToBeHEre\n\nURI: ANOTHER_URIisSupposedToBeHEre\nVersion: dsfjlsdafhjalsdfjh\nChain ID: not-a-chain-id\nNonce: not a nonce\nIssued At: this-is-not-a-date\nExpiration Time: expiration-time-not-a-date\nNot Before: not-before-not-a-date\nRequest ID: random-request-id_STRING!@$%%&\nResources:noURLSreallyHERE"
173+
174+
let validationResponse = EIP4361.validate(rawSiweMessage)
175+
guard validationResponse.isEIP4361 && !validationResponse.isValid else {
176+
XCTFail("Must not be able to parse this SIWE message.")
177+
return
178+
}
179+
180+
XCTAssertEqual(validationResponse.capturedFields[.domain], "service.invalid")
181+
XCTAssertEqual(validationResponse.capturedFields[.address], "not-a-hex-1234567890qwertyuiop1234567890qwertyuiop")
182+
XCTAssertEqual(validationResponse.capturedFields[.statement], "THESTATEMENT123102938102938: aURIisSupposedToBeHEre")
183+
XCTAssertEqual(validationResponse.capturedFields[.uri], "ANOTHER_URIisSupposedToBeHEre")
184+
XCTAssertEqual(validationResponse.capturedFields[.version], "dsfjlsdafhjalsdfjh")
185+
XCTAssertEqual(validationResponse.capturedFields[.chainId], "not-a-chain-id")
186+
XCTAssertEqual(validationResponse.capturedFields[.nonce], "not a nonce")
187+
XCTAssertEqual(validationResponse.capturedFields[.issuedAt], "this-is-not-a-date")
188+
XCTAssertEqual(validationResponse.capturedFields[.expirationTime], "expiration-time-not-a-date")
189+
XCTAssertEqual(validationResponse.capturedFields[.notBefore], "not-before-not-a-date")
190+
XCTAssertEqual(validationResponse.capturedFields[.requestId], "random-request-id_STRING!@$%%&")
191+
XCTAssertEqual(validationResponse.capturedFields[.resources], "noURLSreallyHERE")
192+
}
170193
}

0 commit comments

Comments
 (0)