NexusPHP优化(3)以人为本,加密种子下载链接和Tracker汇报链接

前言

NexusPHP多年前已停止更新,作为NexusPHP的玩家都知道有个参数叫passkey简称pk;
passkey可以做很多事情:RSS订阅站内种子下载站点所有种子上传下载时Tracker汇报等;NexusPHP搭建的很多站,下载链接内和种子announce字段都存在明文的passkey,没有进行任何加密
很多用户在截图下载器Tracker错误或者在站点之间转种、发种时并未对明文的passkey做任何的处理,可见泄露passkey的几率很大。
passkey权限非常大,一旦泄露,严重者直接ban号,后患无穷!
鉴于以上情况,笔者觉得有必要对passkey的使用进行隔离、并限定权限,引入可操作性更强,更安全的加密算法来解决隐患!


解决方案

保留passkey参数,新增hashauthkey参数,3个参数各用户独立,并且hash参数按天变化
采用安全性很高的AES加密算法,无需读写数据库、无需读写缓存,节省资源。

$pass = '站点私钥'
$hash_crypt_key = sha1($SITENAME . $CURUSER["passkey"] . $pass . date("Ymd")) . $CURUSER["id"];
$authkey_crypt_key = sha1($SITENAME . $CURUSER['secret'] . $pass . '当前种子用户的首次下载时间') . $CURUSER['id'];

物理隔离

passkey仅在usercp.php,getrss.php存在,在torrentrss.php使用;
hash仅在download.php使用;
authkey仅在种子文件的announce字段存在,在announce.php使用!


限定权限

  1. 限定passkey权限:专用于生成RSS订阅链接,不能下载种子、不能Tracker汇报(移除种子内明文存在的passkey);
  2. 限定hash权限:专用于下载种子链接,不能RSS订阅、不能Tracker汇报;
  3. 限定authkey权限:专用于种子announce字段Tracker汇报,不能RSS订阅、不能下载种子;

达成效果

  1. 用户重置passkey仅影响RSS订阅页面链接,不影响Tracker汇报;
  2. 种子下载使用的hash,每个用户、每个种子都不同,且按天变化;
  3. 用户重置所有authkey,(更新$CURUSER['secret'])可以让所有种子Tracker失效;
  4. 用户也可以重置单个种子的authkey,(更新‘当前种子用户的首次下载时间’)只影响当前种子的Tracker汇报;
  5. 因种子announce字段的Tracker连接参数authkey是加密的,有效避免第三方分发种子源文件,所有种子必须从站点下载。

泄漏处理

  • 种子authkey泄漏:只影响当前种子,用户只需重置当前单个种子的tracker即可,不影响其他;
  • 下载链接hash泄漏:因hash有效性只有一天,所以只影响当前单个种子,不影响其他,只需要重置当前单个种子的tracker即可;
  • passkey仅存在于RSS订阅链接,安全性仅次于用户的账号、密码,泄漏的可能性大大降低;
    如果不幸passkey泄漏:也无法下载站点所有种子,仅影响当前RSS订阅链接最多50个种子和泄漏之后更新的种子,用户可以先重置passkey,然后查看种子下载记录,只需要重置已泄漏种子即可。

代码实现

index.php

<?php
/**
 * RSS订阅权限:passkey
 * 种子下载权限:hash(AES对称加密)
 * Tracker权限:authkey(AES对称加密 | HASH加密)
 */
include __DIR__ .'/ICrypt.php';
$pass = '站点唯一的密钥';
$uid  = '321611';   // 用户id
/**
 * 种子下载链接加密
 * @desc AES对称加密生成hash(受控于passkey,各用户拥有独立的passkey)
 * 注意:重置passkey时,影响用户RSS订阅链接,不影响用户Tracker汇报;
 */
echo '------------------------------------'.PHP_EOL;
# 1. 根据用户uid查询出passkey
$passkey = 'MIIEowIBAAKCAQEA4T9gNTdx3jQXTWtsbz7V8BbNGxvLNNxdcOZiWmMreH8wFaeL';
# 2. 用户download加密key(每天变化)
$key = sha1($passkey . $pass . date("Ymd")) . $uid;
echo '用户download加密密钥:'.$key.PHP_EOL;
# 3. 加密参数
$config = [
    'method' => 'AES-128-CBC',      //加密方式 AES-256-CBC等
    'key'    => $key,               //加密key
    'iv'     => md5($key, true),    //保证偏移量为16位
];
# 4. 模拟加密解密的全部过程
$id = 9129016;      // 种子id
while ($id > 9129013) {
    $data = $uid.'.'.$id;       // 原始数据
    echo '原始数据:'.$data;
    $hash = ICrypt::encode($data, $config);     // 加密
    echo ' | AES加密torrent_id:download.php?hash='.$hash.'&uid='.$uid.' ('.strlen($hash).'位)';
    echo ' | AES解密torrent_id:'.ICrypt::decode($hash, $config).PHP_EOL;      //解密
    $id--;
}

/**
 * 种子Tracker链接加密
 * @desc AES对称加密生成hash(受控于secret,各用户拥有独立的secret)
 * 优势:重置单个种子时,把torrent_id、uid、新secret写入数据表torrent_secret,不影响用户Tracker汇报、不影响用户RSS订阅连接;
 * 注意:重置secret时,影响用户所有种子Tracker汇报,不影响用户RSS订阅连接(应删除数据表torrent_secret内当前用户数据)
 */
echo '------------------------------------'.PHP_EOL;
# 1. 根据用户uid查询出secret
$secret = 'biwbSB6Pqd/H1fmQSI28uLUzgwXCv1uAE3L2liy8WJOrcH9mxl9qMyBoeyB7QswG';    // 全局 用户独立
# 2. 用户tracker加密key
$key = sha1($secret . $pass) . $uid;
echo '用户Tracker加密密钥:'.$key.PHP_EOL;
# 3. 加密参数
$config = [
    'method' => 'AES-128-CBC',      //加密方式 AES-256-CBC等
    'key'    => $key,               //加密key
    'iv'     => md5($key, true),    //保证偏移量为16位
];
# 4. 模拟加密解密的全部过程
$id = 412900016;    // 种子id
while ($id > 412900013) {
    $data = json_encode(['id' => $id,'uid' => $uid], JSON_UNESCAPED_UNICODE);   // 原始数据
    echo '原始数据:'.$data;
    $hash = ICrypt::encode($data, $config);     // 加密
    echo ' | 方法一.AES加密Tracker:announce.php?authkey='.$hash.'&uid='.$uid.' ('.strlen($hash).'位)';
    echo ' | AES解密Tracker:'.ICrypt::decode($hash, $config);     // 解密
    echo ' | 方法二.hash_hmac签名Tracker:announce.php?authkey='.$uid.'.'.sha1($key.$id).PHP_EOL;
    $id--;
}
echo '------------------------------------'.PHP_EOL;

备注:为进一步提高安全性,在生成$key变量时,可以加入站点唯一的密钥作为参数:
$key = sha1($passkey . $pass . date("Ymd")) . $uid;$key = sha1($secret . $pass) . $uid;


ICrypt.php

<?php
/**
 * @copyright (c) 2020 www.iyuu.cn
 * @file ICrypt.php
 * @brief 加密解密
 * @author david
 * @date 2020年7月16日
 */
class ICrypt
{
    /**
     * @brief  MD5加密方法
     * @param  string $string  字符串
     * @return string $string  加密后的字符串
     */
    public static function md5($string)
    {
        return md5($string);
    }

    /**
     * @brief  SHA1加密方法
     * @param  string $string  字符串
     * @return string $string  加密后的字符串
     */
    public static function sha1($string)
    {
        return sha1($string);
    }

    /**
     * @brief base64url加密方法
     * @param  String $str 字符串
     * @return String $str 加密后字符串
     */
    public static function base64url_encode($str)
    {
        return rtrim(strtr(base64_encode($str), '+/', '-_'), '=');
    }

    /**
     * @brief  base64url解密方法
     * @param  String $str  字符串
     * @return String $str  解密后的字符串
     */
    public static function base64url_decode($str)
    {
        return base64_decode(str_pad(strtr($str, '-_', '+/'), strlen($str) % 4, '=', STR_PAD_RIGHT));
    }

    /**
     * @brief 动态加密函数
     * @param  String  $string 字符串
     * @param  Array   $config 加密参数
     * @return String   加密后的字符串
     */
    public static function encode($string, $config = array())
    {
        return self::base64url_encode(openssl_encrypt($string, $config['method'], $config['key'], OPENSSL_RAW_DATA, $config['iv']));
    }
    
    /**
     * @brief 动态解密函数
     * @param  String $string 字符串
     * @param  Array  $config 解密参数
     * @return String   解密后的字符串
     */
    public static function decode($string, $config = array())
    {
        $string = openssl_decrypt(self::base64url_decode($string), $config['method'], $config['key'], OPENSSL_RAW_DATA, $config['iv']);
        return rtrim(rtrim($string, chr(0)), chr(7));
    }
}

附件:点此下载crypt.zip


测试结果

------------------------------------
用户download加密密钥:df6ac9b443bc950135197fa7b641f5824b4908de321611
原始数据:321611.9129016 | AES加密torrent_id:download.php?hash=TFTresyZBATrwz5krs43-g (22位) | AES解密torrent_id:321611.9129016
原始数据:321611.9129015 | AES加密torrent_id:download.php?hash=i1oWHot5YmGUatgN92AmMw (22位) | AES解密torrent_id:321611.9129015
原始数据:321611.9129014 | AES加密torrent_id:download.php?hash=DEOZ0sF-Wiqmjn_RRGlQfw (22位) | AES解密torrent_id:321611.9129014
------------------------------------
用户Tracker加密密钥:68a73366b45f4cb06e66f6ad279e928aa2f6828b321611
原始数据:{"id":412900016,"uid":"321611"} | 方法一.AES加密Tracker:announce.php?authkey=93KtavYRAbpbkty0u9jNOinIqg4jbrgE5LKJjx8CRvs (43位) | AES解密Tracker:{"id":412900016,"uid":"321611"} | 方法二.HASH加密Tracker:announce.php?authkey=321611.9b6f84f85bb67b259ec1cb7804951bf1a65b2f58
原始数据:{"id":412900015,"uid":"321611"} | 方法一.AES加密Tracker:announce.php?authkey=c56fORCZym3TxALzWGwO5Zw4a3Tt_OSl9acaXgjtKWw (43位) | AES解密Tracker:{"id":412900015,"uid":"321611"} | 方法二.HASH加密Tracker:announce.php?authkey=321611.0de0d726a765cc019d24cf8ac960986ec3e1d4cc
原始数据:{"id":412900014,"uid":"321611"} | 方法一.AES加密Tracker:announce.php?authkey=qNFx6MuF9TVd9N0HbGbkbbg8v3S8lZzJil64R6xAXAM (43位) | AES解密Tracker:{"id":412900014,"uid":"321611"} | 方法二.HASH加密Tracker:announce.php?authkey=321611.d01a2ce758257456f7c24016a72e55baa53de441
------------------------------------
最后修改:2020 年 08 月 11 日 12 : 04 PM
如果觉得我的文章对你有用,请随意赞赏

发表评论