如何创建和使用nonce

我正在运行一个网站,并且有一个评分系统可以为您提供玩游戏次数的积分。


它使用散列来证明http请求的完整性,因此用户无法改变任何内容,但是我担心可能会发生,有人发现他们不需要改变它,他们只需要获得高分,并复制http请求,标题和所有。


以前我被禁止防止这种攻击,因为它被认为是不可能的。但是,既然已经发生了,我可以。http请求源自Flash游戏,然后由php验证并且php将其输入数据库。


我很确定nonce会解决这个问题,但我不确定如何实现它们。设置nonce系统的常用且安全的方法是什么?


茅侃侃
浏览 1887回答 3
3回答

有只小跳蛙

它实际上很容易......有一些库可以帮到你:PHP Nonce库OpenID Nonce库或者如果你想自己编写,那很简单。使用WikiPedia页面作为跳出点,在伪代码中:在服务器端,您需要两个客户端可调用函数getNonce() {&nbsp; &nbsp; $id = Identify Request //(either by username, session, or something)&nbsp; &nbsp; $nonce = hash('sha512', makeRandomString());&nbsp; &nbsp; storeNonce($id, $nonce);&nbsp; &nbsp; return $nonce to client;}verifyNonce($data, $cnonce, $hash) {&nbsp; &nbsp; $id = Identify Request&nbsp; &nbsp; $nonce = getNonce($id);&nbsp; // Fetch the nonce from the last request&nbsp; &nbsp; removeNonce($id, $nonce); //Remove the nonce from being used again!&nbsp; &nbsp; $testHash = hash('sha512',$nonce . $cnonce . $data);&nbsp; &nbsp; return $testHash == $hash;}在客户端:sendData($data) {&nbsp; &nbsp; $nonce = getNonceFromServer();&nbsp; &nbsp; $cnonce = hash('sha512', makeRandomString());&nbsp; &nbsp; $hash = hash('sha512', $nonce . $cnonce . $data);&nbsp; &nbsp; $args = array('data' => $data, 'cnonce' => $cnonce, 'hash' => $hash);&nbsp; &nbsp; sendDataToClient($args);}该函数makeRandomString实际上只需要返回一个随机数或字符串。随机性越好,安全性越好......还要注意,由于它被直接输入到散列函数中,因此实现细节与请求请求无关。客户端的版本和服务器的版本不需要匹配。实际上,需要匹配100%的唯一位是用于hash('sha512', $nonce . $cnonce . $data);... 的哈希函数。这是一个合理安全makeRandomString函数的例子......function makeRandomString($bits = 256) {&nbsp; &nbsp; $bytes = ceil($bits / 8);&nbsp; &nbsp; $return = '';&nbsp; &nbsp; for ($i = 0; $i < $bytes; $i++) {&nbsp; &nbsp; &nbsp; &nbsp; $return .= chr(mt_rand(0, 255));&nbsp; &nbsp; }&nbsp; &nbsp; return $return;}它实际上很容易......有一些库可以帮到你:PHP Nonce库OpenID Nonce库或者如果你想自己编写,那很简单。使用WikiPedia页面作为跳出点,在伪代码中:在服务器端,您需要两个客户端可调用函数getNonce() {&nbsp; &nbsp; $id = Identify Request //(either by username, session, or something)&nbsp; &nbsp; $nonce = hash('sha512', makeRandomString());&nbsp; &nbsp; storeNonce($id, $nonce);&nbsp; &nbsp; return $nonce to client;}verifyNonce($data, $cnonce, $hash) {&nbsp; &nbsp; $id = Identify Request&nbsp; &nbsp; $nonce = getNonce($id);&nbsp; // Fetch the nonce from the last request&nbsp; &nbsp; removeNonce($id, $nonce); //Remove the nonce from being used again!&nbsp; &nbsp; $testHash = hash('sha512',$nonce . $cnonce . $data);&nbsp; &nbsp; return $testHash == $hash;}在客户端:sendData($data) {&nbsp; &nbsp; $nonce = getNonceFromServer();&nbsp; &nbsp; $cnonce = hash('sha512', makeRandomString());&nbsp; &nbsp; $hash = hash('sha512', $nonce . $cnonce . $data);&nbsp; &nbsp; $args = array('data' => $data, 'cnonce' => $cnonce, 'hash' => $hash);&nbsp; &nbsp; sendDataToClient($args);}该函数makeRandomString实际上只需要返回一个随机数或字符串。随机性越好,安全性越好......还要注意,由于它被直接输入到散列函数中,因此实现细节与请求请求无关。客户端的版本和服务器的版本不需要匹配。实际上,需要匹配100%的唯一位是用于hash('sha512', $nonce . $cnonce . $data);... 的哈希函数。这是一个合理安全makeRandomString函数的例子......function makeRandomString($bits = 256) {&nbsp; &nbsp; $bytes = ceil($bits / 8);&nbsp; &nbsp; $return = '';&nbsp; &nbsp; for ($i = 0; $i < $bytes; $i++) {&nbsp; &nbsp; &nbsp; &nbsp; $return .= chr(mt_rand(0, 255));&nbsp; &nbsp; }&nbsp; &nbsp; return $return;}

喵喔喔

Nonce是一种蠕虫。不,实际上,几个CAESAR条目的动机之一是设计一个经过验证的加密方案,最好是基于流密码,它可以抵抗随机数重用。(例如,重复使用带有AES-CTR的随机数,会破坏您的信息的机密性,使第一年编程学生可以解密它。)有六种主要的思想流派:在对称密钥加密中:使用增加的计数器,同时注意永远不要重复使用它。(这也意味着为发送方和接收方使用单独的计数器。)这需要有状态编程(即将nonce存储在某处,因此每个请求都不会从那里开始1)。有状态随机的随机数。生成随机nonce,然后记住它以便稍后验证。这是用于击败CSRF攻击的策略,这听起来更接近于此处的要求。大型无状态随机nonce。给定一个安全的随机数生成器,您几乎可以保证在您的生命中不会重复两次nonce。这是NaCl用于加密的策略。因此,考虑到这一点,要问的主要问题是:上述哪种思想与您试图解决的问题最相关?你是如何产生现时的?你是如何验证nonce的?生成一个随机数对任何随机随机数的问题2的答案是使用CSPRNG。对于PHP项目,这意味着以下之一:random_bytes() 适用于PHP 7+项目paragonie / random_compat,PHP 5 polyfill forrandom_bytes()ircmaxell / RandomLib,这是一个瑞士军刀的随机性工具,大多数处理随机性的项目(例如冷杉密码重置)应该考虑使用而不是自己滚动这两个在道德上是等价的:$factory = new RandomLib\Factory;$generator = $factory->getMediumStrengthGenerator();$_SESSION['nonce'] [] = $generator->generate(32);和$_SESSION['nonce'] []= random_bytes(32);验证随机数有状态有状态的nonce很容易推荐:$found = array_search($nonce, $_SESSION['nonces']);if (!$found) {&nbsp; &nbsp; throw new Exception("Nonce not found! Handle this or the app crashes");}// Yay, now delete it.unset($_SESSION['nonce'][$found]);随意替换array_search()数据库或memcached查找等。无国籍(这里是龙)这是一个难以解决的问题:您需要一些方法来防止重放攻击,但是您的服务器在每次HTTP请求后都有完全失忆。唯一合理的解决方案是验证到期日期/时间,以最大限度地减少重放攻击的有用性。例如:// Generating a message bearing a nonce$nonce = random_bytes(32);$expires = new DateTime('now')&nbsp; &nbsp; ->add(new DateInterval('PT01H'));$message = json_encode([&nbsp; &nbsp; 'nonce' => base64_encode($nonce),&nbsp; &nbsp; 'expires' => $expires->format('Y-m-d\TH:i:s')]);$publishThis = base64_encode(&nbsp; &nbsp; hash_hmac('sha256', $message, $authenticationKey, true) . $message);// Validating a message and retrieving the nonce$decoded = base64_decode($input);if ($decoded === false) {&nbsp; &nbsp; throw new Exception("Encoding error");}$mac = mb_substr($decoded, 0, 32, '8bit'); // stored$message = mb_substr($decoded, 32, null, '8bit');$calc = hash_hmac('sha256', $message, $authenticationKey, true); // calcuatedif (!hash_equals($calc, $mac)) {&nbsp; &nbsp; throw new Exception("Invalid MAC");}$message = json_decode($message);$currTime = new DateTime('NOW');$expireTime = new DateTime($message->expires);if ($currTime > $expireTime) {&nbsp; &nbsp; throw new Exception("Expired token");}$nonce = $message->nonce; // Valid (for one hour)细心的观察者会注意到这基本上是JSON Web令牌的非标准兼容变体。
打开App,查看更多内容
随时随地看视频慕课网APP