## 3 Materials and Methods
### Authentication Phase
The authentication server then responds with the \(PK_{s}\) of the local dynamically selected fog server \(FS\), only if the client \(C\) identity and public key are validated from the distributed blockchain. \[AS\to C:PK_{s};\]
3. The client \(C\) then sends a \"Hello\" message to the local fog server \(FS\) with its public key \(PK_{c}\) encrypted by \(FS\)'s public key \(E_{PK_{s}}\). \[C\to FS:E_{PK_{s}}\text{ (``Hello''||}PK_{c})\]
4. The fog server \(FS\) then considers the request for authentication from user \(C\) after decrypting the received \"Hello\" message by the \(FS\)'s private key \(D_{SKs}\). The \(FS\) then selects one of the branches and blocks randomly from the graph structure to start a ZKP process as the challenge. At first, the hash key \(K_{s,c}\) is generated with the hash of \(k_{s,c}=H(t_{s}\oplus\lambda_{s})\). \(t_{s}\) represents the current timestamp of the \(FS\) and \(\lambda_{s}\) is the selected random transition value from a block. \(V_{s}\) presents the vertex in the graph selected by \(FS\) and \(\lambda_{s}\) as the corresponding transition value. A new session key \(PK_{s}^{\prime}\) is shared by the \(FS\), for encryption of the current authentication messages. \(ttl\) specifies the validity time of the message and mode as 0 as the default, 1, and 2 for advanced ZKP operations/challenges. \[FS\to C:E_{PKc}(K_{s,c}||V_{s}||\lambda_{s}||PK_{s}^{\prime}||ttl||mode);\]
5. User \(C\) then decrypts the message received from the \(FS\) by his/her private key \(D_{SKs}\) and then searches for the vertex \(V_{s}\), such that it is reached by the transition \(\lambda_{s}\) from the graph structure. Once the user \(C\) reaches that vertex \(V_{s}\), he/she then transits to the next immediate vertex \(V_{c}\) and presents the next transition value to the \(FS\) for the clue. In short, user \(C\) helps the \(FS\) reach the alternate vertex within the matrix. Furthermore, a new hash key is generated by the user by \(k_{c,s}=H(t_{c}\oplus\lambda_{c})\), where \(t_{c}\) is the current timestamp of the user \(C\) for sending messages and \(\lambda_{c}\) is the clue to the \(FS\) for the next vertex. The encryption for the new message values is performed by the session key \(E_{PK_{s}}^{\prime}\) sent by the \(FS\) in the previous message. \(a_{c}\) is used to send client \(C\)'s IP address to the \(FS\). \[C\to FS:E_{PK_{s}}^{\prime}(K_{c,s}||V_{c}||\lambda_{c}||a_{c});\]
6. Once the \(FS\) receives the response to a challenge protocol message from the \(C\), then decryption is performed using the symmetric session key \(D_{SKs}^{\prime}\). The \(FS\) then checks for the vertex flow from the previous challenge given to the \(C\) and then reaches the new vertex \(V_{s+1}\) provided as the clue by the transition \(\lambda_{c}\). The \(FS\) can then calculate the next hash key by using \(K_{s,c}\), which is updated by the hash of \(k_{s,c}=H(t_{s}\oplus\lambda_{s})\) with the current ts, and it checks for transition \(\lambda_{s}\) to reach the new vertex \(V_{s+1}\). The \(FS\) then embeds the new parameters in the final message with the new vertex \(V_{s+1}\) and the final vertex \(V_{f}\) of the corresponding matrix, so that the \(C\) can confirm the matching \(V_{s+1}\) and \(V_{f}\). After completing a cycle in the matrix sub-graph, the \(FS\) authenticates \(C\) as the ZKP is solved and allows the \(C\) to use updated \(K_{s,c}\) for further communication as the final key until the next authentication within the fog. \[FS\to C:E_{PK_{s}}^{\prime}(K_{s,c}||V_{s+1}||V_{f})\]  
Note: All the cryptographic operations are performed using the Lightweight Encryption System (LES) [40].