put('sign_message', $message); return $message; } public function verify(Request $request): string { $result = $this->verifySignature(session()->pull('sign_message'), $request->input('signature'), $request->input('address')); // If $result is true, perform additional logic like logging the user in, or by creating an account if one doesn't exist based on the Ethereum address return ($result ? 'OK' : 'ERROR'); } protected function verifySignature(string $message, string $signature, string $address): bool { $hash = Keccak::hash(sprintf("\x19Ethereum Signed Message:\n%s%s", strlen($message), $message), 256); $sign = [ 'r' => substr($signature, 2, 64), 's' => substr($signature, 66, 64), ]; $recid = ord(hex2bin(substr($signature, 130, 2))) - 27; if ($recid != ($recid & 1)) { return false; } $pubkey = (new EC('secp256k1'))->recoverPubKey($hash, $sign, $recid); $derived_address = '0x' . substr(Keccak::hash(substr(hex2bin($pubkey->encode('hex')), 1), 256), 24); return (Str::lower($address) === $derived_address); } }