2008-11-29 42 views
7

我正在构建一个带源系统,我在'提供可采用的虚拟宠物的网络上发布。该系统将主要由孩子拥有。由于我希望它可以用于绝对的初学者程序员,因此我的系统中存在一些复杂性约束:它不能使用通常不随PHP提供的库,也不能访问数据库或写入其他永久存储。在PHP中简单加密

当每只宠物被采纳时,访问者会随机获得该宠物的一系列略有不同的变化之一。变化最初看起来是一样的,但随着时间的推移成长成为不同的宠物。访问者将被给予HTML链接到他们的宠物图像短代码。由于服务器端没有永久性存储器,因此用户的图像链接必须包含所有信息以确定它们最终得到的宠物差异。

目前,URL只包含宠物的ID和用户获得的变体的ID。与此相关的问题是,通过比较代码,用户可以计算出他们中的哪些人得到相同的变化。由于某些变化比其他变化更为罕见,因此用户可以轻松地发现罕见的变化,甚至在差异甚至在视觉上变得明显。

我想要的是一个加密系统的URL中的细节。某些隐藏变体ID的内容,以便每个用户都可能获得不同的URL。我想过使用变化ID(3或4位)作为一个大的随机数的低位或高位,但用户会发现这种模式。理想情况下,加密系统将被参数化,以便我的系统的每次安装都会使用稍微不同的加密。

PHP的mcrypt库可能会有一些有用的东西,但它似乎不是很常见的主机之间。

是否有一个简单的,参数化的,混淆/加密我可以在这里使用?

回答

9

如果您期望复杂程度相对较低,那么您可以做一个非常简单的“xor”加密,并将该“密钥”存储为URL的一部分。然后你可以使用php的rand()或/ dev/random或其他来产生密钥。

低技术含量的用户不会轻易地发现,他们需要做的只是将宠物ID的下半部分与上半部分进行比较,以获得可以与朋友比较的价值。我猜想大多数人能够认识到发生的事情并不需要花时间来解决问题,而且这些人无论如何都不在目标群体中。

编辑:如果它不明显,我说你给每个宠物一个不同的关键(因为给同一个不会解决你的问题)。所以如果宠物变异(petvar)是一个16位的数字,你会生成一个16位的随机数(rnd),那么你可以这样做:petvar = (petvar^rnd)<<16 | rnd;,然后你可以反转该操作来提取rnd,然后petvar^rnd,然后只需再次得到原始petvar。

+0

听起来像一个很好的策略。我也可以使用特定于安装的密钥对整个字符串进行异或。你对“攻击者”的复杂程度的直觉是非常正确的.. :) – thenickdude 2008-11-29 03:30:55

2

为什么不给每个用户一个长的随机ID,然后在服务器上存储关于他们宠物的所有细节?最佳做法是不要在URL中存储任何内容,并且不加密。所有你需要的是一个会话ID。

+0

当然,这就是我在我自己的服务器上所做的。但是我想要一个系统,即使没有像样的存储空间,孩子们可以在自己的服务器上使用系统来赠送宠物:数据库并不总是在免费提供商上提供,并且很难配置,平面文件存储需要太多的代码。 – thenickdude 2008-11-29 04:55:55

16

您正在寻找“一次性填充”加密。它需要一个密钥并为字符创建模数以创建加密字符串。

function ecrypt($str){ 
    $key = "abc123 as long as you want bla bla bla"; 
    for($i=0; $i<strlen($str); $i++) { 
    $char = substr($str, $i, 1); 
    $keychar = substr($key, ($i % strlen($key))-1, 1); 
    $char = chr(ord($char)+ord($keychar)); 
    $result.=$char; 
    } 
    return urlencode(base64_encode($result)); 
} 


function decrypt($str){ 
    $str = base64_decode(urldecode($str)); 
    $result = ''; 
    $key = "must be same key as in encrypt"; 
    for($i=0; $i<strlen($str); $i++) { 
    $char = substr($str, $i, 1); 
    $keychar = substr($key, ($i % strlen($key))-1, 1); 
    $char = chr(ord($char)-ord($keychar)); 
    $result.=$char; 
    } 
return $result; 
} 

这就是简单的字符串加密。我会做的是序列化用户的参数数组,并把它作为在链接的变量:

$arr = array(
    'pet_name'=>"fido", 
    'favorite_food'=>"cat poop", 
    'unique_id'=>3848908043 
); 
$param_string = encrypt(serialize($arr)); 

$link = "/load_pet.php?params=$param_string"; 

在load_pet.php你应该做相反:

$param_string = $_GET["params"]; 
$params = unserialize(decrypt($param_string)); 

巴姆。

+0

当然,这只是一个粗略的概述..你必须处理用户传递一个无效param_string的情况..例如:它不会反序列化,所以你必须抓住它。 – 2008-11-29 05:17:09