php get meta tags




如何創建和使用nonce (3)

Nonce是一種蠕蟲。

不,實際上,幾個CAESAR條目的動機之一是設計一個經過驗證的加密方案,最好是基於流密碼,它可以抵抗隨機數重用。 (例如,重複使用帶有AES-CTR的隨機數,會破壞您的信息的機密性,達到第一年編程學生可以解密它的程度。)

有六種主要的思想流派:

  1. 在對稱密鑰加密中:使用遞增計數器,同時注意不要重複使用它。 (這也意味著為發送方和接收方使用單獨的計數器。)這需要有狀態編程(即將nonce存儲在某處,因此每個請求不會從1開始)。
  2. 有狀態隨機的隨機數。 生成隨機nonce,然後記住它以便稍後驗證。 這是用於擊敗CSRF攻擊的策略,這聽起來更接近於此處的要求。
  3. 大型無狀態隨機nonce。 給定一個安全的隨機數生成器,您幾乎可以保證在您的生命中不會重複兩次nonce。 這是CAESAR用於加密的策略。

因此,考慮到這一點,要問的主要問題是:

  1. 上述哪種思想與您試圖解決的問題最相關?
  2. 你是如何產生現時的?
  3. 你是如何驗證nonce的?

生成一個隨機數

任何隨機現時的問題2的答案是使用CSPRNG。 對於PHP項目,這意味著以下之一:

這兩個在道德上是等價的:

$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) {
    throw new Exception("Nonce not found! Handle this or the app crashes");
}
// Yay, now delete it.
unset($_SESSION['nonce'][$found]);

隨意用數據庫或memcached查找等替換array_search()

無國籍(這裡是龍)

這是一個難以解決的問題:您需要一些方法來防止重放攻擊,但是您的服務器在每個HTTP請求之後都有完全失憶。

唯一合理的解決方案是驗證到期日期/時間,以最大限度地減少重放攻擊的有用性。 例如:

// Generating a message bearing a nonce
$nonce = random_bytes(32);
$expires = new DateTime('now')
    ->add(new DateInterval('PT01H'));
$message = json_encode([
    'nonce' => base64_encode($nonce),
    'expires' => $expires->format('Y-m-d\TH:i:s')
]);
$publishThis = base64_encode(
    hash_hmac('sha256', $message, $authenticationKey, true) . $message
);

// Validating a message and retrieving the nonce
$decoded = base64_decode($input);
if ($decoded === false) {
    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); // calcuated
if (!hash_equals($calc, $mac)) {
    throw new Exception("Invalid MAC");
}
$message = json_decode($message);
$currTime = new DateTime('NOW');
$expireTime = new DateTime($message->expires);
if ($currTime > $expireTime) {
    throw new Exception("Expired token");
}
$nonce = $message->nonce; // Valid (for one hour)

細心的觀察者會注意到這基本上是JSON Web令牌的非標準兼容變體。

我正在運行一個網站,並且有一個評分系統可以為您提供玩遊戲次數的積分。

它使用散列來證明http請求的完整性,因此用戶無法改變任何東西,但是我擔心可能會發生,有人發現他們不需要改變它,他們只需要獲得高分,並複制http請求,標題和所有。

以前我被禁止防止這種攻擊,因為它被認為是不可能的。 但是,既然已經發生了,我可以。 http請求源自Flash遊戲,然後由php驗證,php將其輸入數據庫。

我很確定nonce會解決這個問題,但我不確定如何實現它們。 設置現時系統的常用且安全的方法是什麼?


一個選項(我在評論中提到)是錄製遊戲玩法並在安全環境中重放它。

另一件事是隨機地,或在某些特定時間,記錄一些看似無辜的數據,後來可以用來在服務器上驗證它(比如突然生活從1%到100%,或從1到1000得分錶示作弊)。 有足夠的數據,欺騙者試圖偽造它可能是不可行的。 然後當然實施嚴重禁止:)。


它實際上很容易......有一些庫可以幫到你:

  1. PHP Nonce庫
  2. OpenID Nonce庫

或者如果你想自己編寫,那很簡單。 使用WikiPedia頁面作為跳出點,在偽代碼中:

在服務器端,您需要兩個客戶端可調用函數

getNonce() {
    $id = Identify Request //(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);
}

makeRandomString函數實際上只需要返回一個隨機數或字符串。 隨機性越好,安全性越好......還要注意,由於它被直接輸入到散列函數中,因此實現細節與請求請求無關。 客戶端的版本和服務器的版本不需要匹配。 事實上,唯一需要匹配100%的是hash中使用的哈希函數hash('sha512', $nonce . $cnonce . $data); ...這是一個相當安全的makeRandomString函數的例子......

function makeRandomString($bits = 256) {
    $bytes = ceil($bits / 8);
    $return = '';
    for ($i = 0; $i < $bytes; $i++) {
        $return .= chr(mt_rand(0, 255));
    }
    return $return;
}




nonce