diff --git a/app/Console/Commands/Test.php b/app/Console/Commands/Test.php index 47708450..4437afa2 100644 --- a/app/Console/Commands/Test.php +++ b/app/Console/Commands/Test.php @@ -51,8 +51,10 @@ class Test extends Command public function handle() { $torrentRep = new TorrentRepository(); - $r = $torrentRep->encryptDownHash(1, 1); - dd($r, $torrentRep->decryptDownHash($r,1)); + $r = $torrentRep->getTrackerReportAuthKey(1, 1, true); +// $r = $torrentRep->resetTrackerReportAuthKeySecret(1); +// dd($r); + dd($r, $torrentRep->checkTrackerReportAuthKey($r)); } } diff --git a/app/Models/NexusModel.php b/app/Models/NexusModel.php index b64d761c..ade5906b 100644 --- a/app/Models/NexusModel.php +++ b/app/Models/NexusModel.php @@ -11,8 +11,6 @@ class NexusModel extends Model public $timestamps = false; -// protected $perPage = 2; - /** * * @param \DateTimeInterface $date diff --git a/app/Models/TorrentSecret.php b/app/Models/TorrentSecret.php new file mode 100644 index 00000000..11614f63 --- /dev/null +++ b/app/Models/TorrentSecret.php @@ -0,0 +1,8 @@ +getEncryptAuthkeyKey($user); - return (new Hashids($key))->encode($id); + $key = $this->getTrackerReportAuthKeySecret($id, $uid, $initializeIfNotExists); + $hash = (new Hashids($key))->encode(date('Ymd')); + return sprintf('%s|%s|%s', $id, $uid, $hash); } - public function decryptAuthKey($downHash, $user) + /** + * check tracker report authkey + * if valid, the result will be the date the key generate, else if will be empty string + * + * @date 2021/6/3 + * @time 20:29 + * @param $authKey + * @return array + * @throws NexusException + */ + public function checkTrackerReportAuthKey($authKey) { - $key = $this->getEncryptAuthkeyKey($user); - return (new Hashids($key))->decode($downHash); - } - - private function getEncryptAuthkeyKey($user) - { - if (!is_array($user) || empty($user['passkey']) || empty($user['id'])) { - $user = User::query()->findOrFail(intval($user), ['id', 'passkey'])->toArray(); + $arr = explode('|', $authKey); + if (count($arr) != 3) { + throw new NexusException('Invalid authkey'); } - //down hash is relative to user passkey - return md5($user['passkey'] . date('Ymd') . $user['id']); + $id = $arr[0]; + $uid = $arr[1]; + $hash = $arr[2]; + $key = $this->getTrackerReportAuthKeySecret($id, $uid); + return (new Hashids($key))->decode($hash); + } + + private function getTrackerReportAuthKeySecret($id, $uid, $initializeIfNotExists = false) + { + $secret = TorrentSecret::query() + ->where('uid', $uid) + ->whereIn('torrent_id', [0, $id]) + ->orderBy('torrent_id', 'desc') + ->first(); + if ($secret) { + return $secret->secret; + } + if ($initializeIfNotExists) { + $insert = [ + 'uid' => $uid, + 'torrent_id' => 0, + 'secret' => Str::random(), + ]; + TorrentSecret::query()->insert($insert); + return $insert['secret']; + } + throw new NexusException('No valid report secret, please re-download this torrent.'); + } + + /** + * reset user tracker report authkey secret + * + * @param $uid + * @param int $torrentId + * @return string + * @todo wrap with transaction + * + * @date 2021/6/3 + * @time 20:15 + */ + public function resetTrackerReportAuthKeySecret($uid, $torrentId = 0) + { + $insert = [ + 'uid' => $uid, + 'secret' => Str::random(), + 'torrent_id' => $torrentId, + ]; + if ($torrentId > 0) { + return TorrentSecret::query()->insert($insert); + } + + TorrentSecret::query()->where('uid', $uid)->delete(); + TorrentSecret::query()->insert($insert); + return $insert['secret']; + } diff --git a/public/announce.php b/public/announce.php index 7fa5b0ec..f6542e90 100644 --- a/public/announce.php +++ b/public/announce.php @@ -3,10 +3,35 @@ require_once('../include/bittorrent_announce.php'); require_once('../include/benc.php'); dbconn_announce(); do_log(nexus_json_encode($_SERVER)); -$log = ""; //1. BLOCK ACCESS WITH WEB BROWSERS AND CHEATS! $agent = $_SERVER["HTTP_USER_AGENT"]; block_browser(); + +//check authkey +if (!empty($_REQUEST['authkey'])) { + $arr = explode('|', $_REQUEST['authkey']); + if (count($arr) != 3) { + err('Invalid authkey'); + } + $torrentId = $arr[0]; + $uid = $arr[1]; + $torrentRep = new \App\Repositories\TorrentRepository(); + try { + $decrypted = $torrentRep->checkTrackerReportAuthKey($_REQUEST['authkey']); + } catch (\Exception $exception) { + err($exception->getMessage()); + } + if (empty($decrypted)) { + err('Invalid authkey'); + } + $userInfo = \App\Models\User::query()->where('id', $uid)->first(['id', 'passkey']); + if (!$userInfo) { + err('Invalid authkty'); + } + $_GET['passkey'] = $userInfo->passkey; +} + + //2. GET ANNOUNCE VARIABLES // get string type passkey, info_hash, peer_id, event, ip from client foreach (array("passkey","info_hash","peer_id","event") as $x) diff --git a/public/download.php b/public/download.php index 2db2874d..63a34507 100644 --- a/public/download.php +++ b/public/download.php @@ -105,9 +105,11 @@ if (strlen($CURUSER['passkey']) != 32) { sql_query("UPDATE users SET passkey=".sqlesc($CURUSER['passkey'])." WHERE id=".sqlesc($CURUSER['id'])); } +$trackerReportAuthKey = $torrentRep->getTrackerReportAuthKey($id, $CURUSER['id'], true); + $dict = bdec_file($fn, $max_torrent_size); //$dict['value']['announce']['value'] = $ssl_torrent . $base_announce_url . "?passkey=$CURUSER[passkey]"; -$dict['value']['announce']['value'] = getSchemeAndHttpHost() . "/announce.php?passkey=$CURUSER[passkey]"; +$dict['value']['announce']['value'] = getSchemeAndHttpHost() . "/announce.php?authkey=$trackerReportAuthKey"; $dict['value']['announce']['string'] = strlen($dict['value']['announce']['value']).":".$dict['value']['announce']['value']; $dict['value']['announce']['strlen'] = strlen($dict['value']['announce']['string']); /*if ($announce_urls[1] != "") // add multi-tracker