Literally it means a number that can be used only once. Nonce is often a random or pseudo random number that is used in authentication protocols in preventing semantic URL and replay attacks using old communications. Each 401 authentication invokes a distinct nonce response, rendering replay attacks virtually impossible. In software development nonce is often used as a security measure to make sure that certain forms and links are only available once.
To understand nonce better, let us consider two examples.
The first scenario is a user ordering products. An attacker could take the encrypted information and, without needing to decrypt, could continue to send the order into the company, thereby ordering products over and over again under the same name and purchase information. Use of nonce is such a situation can effectively neutralize the threat by forcing the authentication module to validate a distinct nonce value before sending the response to HTTP request.
For second example consider this line of code:
<a href="delete_post.php?post=003">Delete Post</a>
In the above code, anyone can start deleting posts by simply pointing the browser to the link and changing the post number. Even if strict login security is implemented through sessions or state management, spoofing still remains a viable and vibrant threat to the system. Again in such a scenario a nonce can be used to make sure an action initiated by link or request is used only once.
Each time a form or link is presented to the user, the nonce function embeds a key to to be sent to the receiving script. Every time the script is called it checks for the nonce key. If the key is found to be distinct the action is allowed to complete.
Here is how the above example code would look like in case of a nonce functionality being used.
<a href="delete_post.php?post=003&_nonce=9c5fbfabb1">Delete Post</a>
The life span of a nonce contains the following states.
(source: http://stackoverflow.com/questions/4145531/how-to-create-and-use-nonces by ircmaxell)
getNonce() { $id =$_REQUEST[‘user_id’] //(either by username, session, or something) $nonce = hash('sha512', makeRandomString()); storeNonce($id, $nonce); return $nonce to client; } verifyNonce($data, $cnonce, $hash) { $id = Identify Request $nonce = getNonce($id); // Fetch the nonce from the last request removeNonce($id, $nonce); //Remove the nonce from being used again! $testHash = hash('sha512',$nonce . $cnonce . $data); return $testHash == $hash; }
sendData($data) { $nonce = getNonceFromServer(); $cnonce = hash('sha512', makeRandomString()); $hash = hash('sha512', $nonce . $cnonce . $data); $args = array('data' => $data, 'cnonce' => $cnonce, 'hash' => $hash); sendDataToClient($args); }
function makeRandomString($bits = 256) { $bytes = ceil($bits / 8); $return = ''; for ($i = 0; $i < $bytes; $i++) { $return .= chr(mt_rand(0, 255)); } return $return; }