ProgramingTip

nonce를 만들고 사용하는 방법

bestdevel 2020. 11. 28. 10:12
반응형

nonce를 만들고 사용하는 방법


저는 웹 사이트를 운영하고 게임을 한 횟수에 따라 점수를 점수 시스템이 있습니다.

해싱을 사용하여 점수에 대한 http 요청의 무결성을 증명하는 사용자는 아무것도 없습니다. 그러나 어느 누군가가 있다고 말하는 것이 있다고 주장합니다. http 요청, 헤더 및 모두.

이전에는이 ​​공격이 가능성이없는 것들이 공격으로부터 보호하는 것이 금지됩니다. 그러나 이제는 그렇게 할 수 있습니다. http 요청은 플래시 게임에서 시작된 다음 php에 의해 유효성이 검사되고 php는이를 데이터베이스에 입력합니다.

확신하지만 구현 방법을 정확히 모르겠습니다. nonce 시스템을 설정하는 일반적이고 안전한 방법은 무엇입니까?


당신을 위해 할 수있는 라이브러리가 있습니다.

  1. PHP Nonce 라이브러리
  2. OpenID Nonce 라이브러리

또는 직접 작성하고 매우 간단합니다. 위키 사용 피 디아 페이지를 의사 코드에서 포인트 떨어져 점프로 :

서버 측에는 두 개의 클라이언트 호출이 가능합니다.

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('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는 웜 캔입니다.

아니요, 실제로 여러 개의 CAESAR 항목 에 대한 다수의 중 하나는 무리에 저항하는 인증 된 암호화 체계를 설계하는 것이 었습니다. (예를 들어, 임시 값을 AES-CTR 학생으로 보완하면 1 학년 프로그래밍이 해독 할 수 있습니다. 메시지의 기밀성이 손상됩니다.)

논스를 사용하는 세 가지 주요 사고 학교가 있습니다.

  1. 대칭 키 암호화 : 증가하는 카운터를 사용하고 절대하지 않습니다. (즉, 각 요청이 요청을 시작하지 않는 것이 아니라는 것을 의미합니다 1).
  2. 상태 저장 무작위 임시 값. 무작위 임시 값을 생성 한 다음 나중에 유효성을 검사하기 위해 기억합니다. 이것은 CSRF 공격을 물리 치는 데 사용되는 전략이며, 여기에서 요구하는 것입니다.
  3. 큰 상태 비 저장 랜덤 임시 값. 안전한 난수 생성기를 사용하면 평생 동안 nonce를 두 번 반복하지 않을 것입니다. 이것은 암호화를 위해 NaCl 에서 사용하는 전략 입니다.

주요 질문은 다음과 질문합니다.

  1. 위의 생각 학교 중 해결하려는 문제와 가장 관련이있는 것은 무엇입니까?
  2. 임시 값을 어떻게 생성하고 있습니까?
  3. nonce를 어떻게 유전하고 있습니까?

Nonce 생성

임의의 임시 값에 대한 질문 2에 대한 대답은 CSPRNG를 사용하는 것입니다. PHP 프로젝트의 경우 다음 중 하나를 의미합니다.

  • random_bytes() PHP 7+ 프로젝트 용
  • paragonie / random_compat , PHP 5 폴리 필random_bytes()
  • ircmaxell / RandomLib , 임의성 (예 : 장식적인 암호)을 다루는 대부분의 프로젝트에서 자체 롤링 대신 사용을하는 임의성 유틸리티의 스위스 군용 칼입니다.

이 두 개의 도덕적으로 동일합니다.

$factory = new RandomLib\Factory;
$generator = $factory->getMediumStrengthGenerator();
$_SESSION['nonce'] [] = $generator->generate(32);

$_SESSION['nonce'] []= random_bytes(32);

논스

상태 저장

상태 저장 임시 값은 제조사 권장합니다.

$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]);

array_search()데이터베이스 또는 memcached 조회 등으로 자유롭게 대체하십시오 .

무국적 (여기 드래곤이있다)

이것은 해결하기 어려운 문제입니다. 리플레이 공격을 방지 할 수있는 방법이 필요하지만 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 웹 토큰 의 비표준 호환 변형이라는 점에 주목할 것입니다 .


한 가지 옵션 (댓글에서 언급 했음)은 게임 플레이를 녹화하고 안전한 환경에서 재생하는 것입니다.

다른 한 가지는 무작위로 또는 특정 시간에 무해 해 보이는 데이터를 기록하는 것입니다. 나중에 서버에서이를 검증하는 데 사용할 수 있습니다 (예 : 갑자기 라이브가 1 %에서 100 %로 변경되거나 치트를 나타내는 1에서 1000까지의 점수) ). 데이터가 충분하면 사기꾼이 가짜를 시도하는 것이 불가능할 수 있습니다. 그리고 물론 무거운 금지를 구현하십시오 :).


이 매우 간단한 임시 값은 1000 초 (16 분)마다 변경되며 동일한 응용 프로그램에서 데이터를 게시하는 XSS를 방지하는 데 사용할 수 있습니다. (예를 들어, 자바 스크립트를 통해 데이터를 게시하는 단일 페이지 애플리케이션에있는 경우. 게시 및 수신 측에서 동일한 시드 및 임시 생성기에 액세스 할 수 있어야합니다.)

function makeNonce($seed,$i=0){
    $timestamp = time();
    $q=-3; 
    //The epoch time stamp is truncated by $q chars, 
    //making the algorthim to change evry 1000 seconds
    //using q=-4; will give 10000 seconds= 2 hours 46 minutes usable time

    $TimeReduced=substr($timestamp,0,$q)-$i; 

    //the $seed is a constant string added to the string before hashing.    
    $string=$seed.$TimeReduced;
    $hash=hash('sha1', $string, false);
    return  $hash;
}   

그러나 이전 임시 값을 확인하면 사용자는 최악의 경우 16.6 분 이상, 최상의 경우 33 분 이상 기다린 경우에만 귀찮게합니다. $ q = -4를 설정하면 사용자에게 최소 2.7 시간이 제공됩니다.

function checkNonce($nonce,$seed){
//Note that the previous nonce is also checked giving  between 
// useful interval $t: 1*$qInterval < $t < 2* $qInterval where qInterval is the time deterimined by $q: 
//$q=-2: 100 seconds, $q=-3 1000 seconds, $q=-4 10000 seconds, etc.
    if($nonce==$this->makeNonce($seed,0)||$nonce==$this->makeNonce($seed,1))     {
         //handle data here
         return true;
     } else {
         //reject nonce code   
         return false;
     }
}

$ seed는 프로세스에서 사용되는 함수 호출 또는 사용자 이름 등이 될 수 있습니다.


부정 행위를 방지 할 수 없습니다. 더 어렵게 만들 수 있습니다.

누군가 PHP Nonce 라이브러리를 찾고있는 경우 : ircmaxwell이 제공 한 첫 번째 라이브러리를 사용하지 않는 것이 좋습니다 .

웹 사이트의 첫 번째 댓글은 디자인 결함을 설명합니다.

임시 값은 특정 시간 창에 적합합니다. 즉, 사용자가 해당 창 끝에 가까워 질수록 양식을 제출하는 데 걸리는 시간이 1 초 미만일 수 있습니다.

수명이 잘 정의 된 Nonce를 생성하는 방법을 찾고 있다면 NonceUtil-PHP를 살펴보십시오 .

면책 조항 : 저는 NonceUtil-PHP의 저자입니다.

참고 URL : https://stackoverflow.com/questions/4145531/how-to-create-and-use-nonces

반응형