Subversion Repositories php_clientchallenge

Compare Revisions

No changes between revisions

Regard whitespace Rev 5 → Rev 6

/trunk/.gitignore
1,3 → 1,5
vendor/
composer.lock
composer.phar
Sha3.php
 
/trunk/ClientChallenge.class.php
2,7 → 2,7
 
/*
* php_clientchallenge
* Copyright 2021 Daniel Marschall, ViaThinkSoft
* Copyright 2021-2022 Daniel Marschall, ViaThinkSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
21,13 → 21,25
 
class ClientChallenge {
 
const OPEN_TRANS_DIR = __DIR__.'/cache';
 
private static function sha3_512($message, $raw_output=false) {
if (version_compare(PHP_VERSION, '7.1.0') >= 0) {
return hash('sha3-512', $message, $raw_output);
} else {
return \bb\Sha3\Sha3::hash($message, 512, $raw_output); /** @phpstan-ignore-line */
// Download file if required (usually composer should do it)
if (file_exists(__DIR__.'/Sha3.php')) include_once __DIR__.'/Sha3.php';
if (!class_exists('\bb\Sha3\Sha3')) {
$sha3_lib = file_get_contents('https://raw.githubusercontent.com/danielmarschall/php-sha3/master/src/Sha3.php');
if (file_put_contents(__DIR__.'/Sha3.php', $sha3_lib)) {
include_once __DIR__.'/Sha3.php';
} else {
eval('?>'.$sha3_lib);
}
}
return \bb\Sha3\Sha3::hash($message, 512, $raw_output);
}
}
 
private static function sha3_512_hmac($message, $key, $raw_output=false) {
// RFC 2104 HMAC
53,11 → 65,22
}
}
 
public static function checkValidation($max_time=10, $server_secret) {
private static function getOpenTransFileName($ip_target, $random) {
// Delete challenges which were never completed
$files = glob(self::OPEN_TRANS_DIR.'/*.tmp');
$expire = strtotime('-3 DAYS');
foreach ($files as $file) {
if (!is_file($file)) continue;
if (filemtime($file) > $expire) continue;
@unlink($file);
}
 
if (!isset($_REQUEST['vts_validation_result'])) throw new \Exception('No challenge response found');
return self::OPEN_TRANS_DIR.'/'.self::sha3_512($ip_target.'/'.$random).'.tmp';
}
 
list($starttime, $ip_target, $challenge, $answer, $challenge_integrity) = @json_decode($_REQUEST['vts_validation_result'], true);
public static function checkValidation($client_response, $max_time=10, $server_secret) {
list($starttime, $ip_target, $challenge, $answer, $challenge_integrity) = $client_response;
$open_trans_file = self::getOpenTransFileName($ip_target, $answer);
 
if ($ip_target != $_SERVER['REMOTE_ADDR']) {
throw new \Exception('Wrong IP');
67,17 → 90,19
throw new \Exception('Challenge integrity failed');
} else if ($challenge !== self::sha3_512($starttime.'/'.$ip_target.'/'.$answer)) {
throw new \Exception('Wrong answer');
} else if (!file_exists($open_trans_file)) {
throw new \Exception('Challenge submitted twice or transaction missing');
} else {
unlink($open_trans_file);
return true;
}
}
 
// This is only called by ajax_get_challenge.php
public static function createChallenge($complexity=500000, $server_secret) {
public static function createChallenge($complexity=50000, $server_secret) {
$offset = 0; // doesn't matter
$min = $offset;
$max = $offset + $complexity;
 
$min = 0;
$max = $complexity;
 
$starttime = time();
 
$random = rand($min,$max); // TODO: cryptographic rand
90,9 → 115,12
 
$send_to_client = array($starttime, $ip_target, $challenge, $min, $max, $challenge_integrity);
 
header('Content-Type:application/json');
die(json_encode($send_to_client));
$open_trans_file = self::getOpenTransFileName($ip_target, $random);
if (@file_put_contents($open_trans_file, '') === false) {
throw new \Exception("Cannot write $open_trans_file");
}
 
return $send_to_client;
}
 
}
/trunk/ClientChallenge.js
1,6 → 1,6
/*
* php_clientchallenge
* Copyright 2021 Daniel Marschall, ViaThinkSoft
* Copyright 2021-2022 Daniel Marschall, ViaThinkSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
22,6 → 22,10
data: {
},
success: function(data) {
if ("error" in data) {
error_cb(null,null,data["error"]);
return;
}
var starttime = data[0];
var ip_target = data[1];
var challenge = data[2];
/trunk/cache/.gitignore
--- composer.json (revision 5)
+++ composer.json (revision 6)
@@ -1,7 +1,7 @@
{
"name": "danielmarschall/php_clientchallenge",
"description": "Server requests using client-challenges in order to mitigate resource starvation",
- "version": "1.0",
+ "version": "1.1",
"type": "package",
"homepage": "https://www.viathinksoft.com/projects/php_clientchallenge",
"authors": [
/trunk/example/ajax_example.php
2,7 → 2,7
 
/*
* php_clientchallenge
* Copyright 2021 Daniel Marschall, ViaThinkSoft
* Copyright 2021-2022 Daniel Marschall, ViaThinkSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
29,7 → 29,9
 
// Check request field "vts_validation_result" for valid response of the Challenge
try {
\ViaThinkSoft\RateLimitingChallenge\ClientChallenge::checkValidation(MAX_TIME, VTS_CS_SERVER_SECRET);
if (!isset($_REQUEST['vts_validation_result'])) throw new \Exception('No challenge response found');
$client_response = @json_decode($_REQUEST['vts_validation_result'], true);
\ViaThinkSoft\RateLimitingChallenge\ClientChallenge::checkValidation($client_response, MAX_TIME, VTS_CS_SERVER_SECRET);
} catch (\Exception $e) {
$res = array("error" => $e->getMessage());
header('Content-Type:application/json');
/trunk/example/ajax_get_challenge.php
2,7 → 2,7
 
/*
* php_clientchallenge
* Copyright 2021 Daniel Marschall, ViaThinkSoft
* Copyright 2021-2022 Daniel Marschall, ViaThinkSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
25,4 → 25,11
 
require_once __DIR__ . '/config.inc.php';
 
\ViaThinkSoft\RateLimitingChallenge\ClientChallenge::createChallenge(COMPLEXITY, VTS_CS_SERVER_SECRET);
try {
$res = \ViaThinkSoft\RateLimitingChallenge\ClientChallenge::createChallenge(COMPLEXITY, VTS_CS_SERVER_SECRET);
} catch (\Exception $e) {
$res = array("error" => $e->getMessage());
}
 
header('Content-Type:application/json');
die(json_encode($res));
/trunk/example/config.inc.php
2,7 → 2,7
 
/*
* php_clientchallenge
* Copyright 2021 Daniel Marschall, ViaThinkSoft
* Copyright 2021-2022 Daniel Marschall, ViaThinkSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
18,5 → 18,5
*/
 
define('VTS_CS_SERVER_SECRET', '1234567890'); // PLEASE CHANGE THIS VALUE TO SOMETHING RANDOM!
define('MAX_TIME', 10); // seconds
define('COMPLEXITY', 500000);
define('MAX_TIME', 15); // seconds
define('COMPLEXITY', 50000);
/trunk/example/index.html
12,6 → 12,7
 
let error_cb = function (request, status, error) {
$("#out").val("Error!");
alert(error);
}
 
let callback = function(params, vts_validation_result) {
29,8 → 30,7
},
success: function(data) {
if ("error" in data) {
$("#out").val('ERROR');
alert(data["error"]);
error_cb(null,null,data["error"]);
} else {
$("#out").val(data["result"]);
}
/trunk/phpstan.neon.dist
6,6 → 6,8
paths:
- .
excludePaths:
analyse:
- Sha3.php
analyseAndScan:
- .phpstan.tmp
tmpDir: .phpstan.tmp
/trunk/.
Property changes:
Modified: svn:ignore
composer.phar
.phpstan.tmp
phpstan.neon
+Sha3.php
+