I'm attempting to find a client/server authentication protocol that allows the client and server to authenticate each other when the client doesn't know the server secret but does have a sensitive key derived from the secret. I would like to just use PKI, but the server in this case is extremely limited in CPU and memory resources, on the order of 16MHz and 32K Ram; but it does have hardware AES support. Speed of the process is critical to the user-experience, but security is paramount. I was thinking through it and I'd like something like this (The most secure form of each function is implicit): **ClientID (CID)**: Unique client identifier that ties the token to the client. **Client Token (CT)**: SHA(CID+Secret) **Secret (S)**: A secret that the server knows. The server (or a third party that also knows the key) creates tokens through an offline commissioning process. Client -> Server CID, CNonce Server -> Client (Server derives expected CT with secret and CID) SNonce, AES(IV=CNonce, K=CT, PT=SNonce) Client -> Server AES(IV=SNonce, K=CT, PT=CNonce) This seems to give me a few properties that I need: - The client can verify that the server knows the secret because it is able to encrypt SNonce with the derived token. - The server can verify that the client has the token because it can successfully encrypt the CNonce. - Replay attacks are mitigated by the nonces. - MITM attacks mitigated because the token is never transmitted.