2010-09-10 45 views
5

作为一名PHP程序员和C#编程初学者,我一直想知道生成独特的串行数据的最佳方式,例如Microsoft Office和Microsoft操作系统的工作方式。使用PHP进行串行生成

有没有人有一个很好的指导如何处理这一点,像什么是生成独特的序列,防止重复等重要因素如何创建/验证它们的小例子。

这里是我正在谈论的RFC:http://tools.ietf.org/html/rfc1982

回答

12

如果您的应用程序有一个连接回到服务器,那么只需生成随机令牌,将它们存储在数据库中,并要求应用程序在运行前检查服务器。但是有些客户可能会发现这个要求是不可接受的。 (我个人绝不会与互联网激活要求购买任何软件,我想购买软件,而不是把它租。)

对于真实性checkability键,而无需有一个连接到服务器:

  1. 在服务器上,生成一个随机的唯一标记。

  2. 使用公钥加密方案(例如RSA)使用对服务器保密的私钥对令牌进行签名。

  3. 使用一些二进制到文本方案(例如,base64或仅使用2-9A-KMNP-Z符号以实现更安全的可打字性)将唯一标记和签名一起编码。编码的组合是您的钥匙或串行。

  4. 在应用程序的每个副本中嵌入与服务器私钥匹配的公钥,并在安装时让应用程序提示输入密钥。它可以拆分唯一标记和签名,并使用公钥来验证签名对该标记是否有效。

这种方法需要你捆绑一些加密库与你的软件,和大多数算法使用了相当长的签名,为了安全,这将使你的序列号,相当乏味的输入,如果你希望用户能够复制它的确定并粘贴数字。

由于这些原因,许多软件包使用不太安全的密钥验证方案,其中检查算法完全内置于客户端。这可能是一个散列,例如。串行的最后四个十六进制数字必须与串行其余部分的SHA1散列的最低两个字节匹配,并与“秘密”密钥相结合。但是,由于密钥必须捆绑在应用程序中,所以黑客可能会查看应用程序代码并提取“秘密”密钥,从而允许他们编写自己的密钥生成器。

这就是为什么对于某些程序,您会看到'keygens'可用:应用程序使用安全性较低的检查算法,在应用程序中留下足够的信息以允许cracker重新生成密钥制作过程。对于基于公钥密码或互联网激活的更安全设置的程序,您通常会看到应用程序的“破解”版本,而检查代码已被更改/删除。

......哪种表现无论你做什么,你仍然无法执行诚实。所以不要太担心。

+0

周围信息很好 – Fanis 2010-09-10 21:03:56

+0

完美,只是我一直在寻找的信息类型:),非常棒的阅读。 +1 – RobertPitt 2010-09-10 21:12:59

+1

: - 这正是我所说的。 – Bot 2010-09-11 16:50:47

1

我不是很确定你想要什么,但有http://www.php.net/manual/en/function.uniqid.php它创建唯一标识符。

如果您对它们的创建方式更感兴趣,我建议您查看一下PHP源代码,以了解uniqid是如何实现的。

+0

林的问候交谈http://tools.ietf.org/html/rfc1982 – RobertPitt 2010-09-10 20:13:28

+0

uniqid是完全可以预见的。实际上,它只是它生成的microtime的一个代表。它绝不是随机的。 – NikiC 2010-09-10 20:26:17

1

需要更多信息。你想创建一个序列键,比如你购买一款游戏,或者你想要一个序列号作为唯一的用户ID。

序列号是否需要存储过期时间/日期等信息?

@nikic - 所有rand的使用时间作为启动随机生成器的基础。这就是国防部使用熔岩灯的原因。他们有一个整个房间专用于熔岩灯和闪耀的激光,随机创建一个独特的钥匙。

编辑:

那么你需要考虑到影响的只是你的C#应用​​程序会用什么方法与您的网站进行通信。

您将需要使用php创建一个密钥并将其存储在数据库中,以便C#可以确认该串行是正确的。

然后您需要弄清楚PHP是否会返回另一个值,以便C#应用程序知道密钥是否已通过身份验证。

我在粘贴中做了什么是创建一个公钥和私钥。公钥将提供给用户验证产品。当他们验证产品或登录到系统时,将根据数据库检查公钥,返回值将是私钥。在与我的C#程序的所有交互过程中,如果用户需要检查更新或从我的服务器获取信息,私钥将被添加到服务器的查询中,以确认最终用户是合法的。

我还使用的另一种方法是上面的,但增加了额外的检查以确认用户不共享密钥。 C#应用程序将获得计算机中处理器的序列号,并在注册该应用程序时将其保存到我的数据库中。然后,如果有人试图用相同的公钥注册产品但处理器的序列号不同,则会发出错误,他们需要联系支持人员。你可以这样做,以允许5个不同的机器ID或每个你想要的。

创建注册码非常简单,因为您实际上只需要创建一个具有偏移量的随机字符串(例如用户名)。

但是,您也可以根据某人提供的名称或公司名称创建注册码,并将该算法添加到C#程序中。不利之处在于C#源代码可以轻松地反编译,可以发现该算法很容易创建注册码,而无需真正为产品付费。通过添加身份验证的服务器,对于某人来说,生成自己的序列密钥要困难得多。

+0

可以说我有一个产品,比如应用程序,这个应用程序需要一个串行系统,我想在PHP中生成一个可以在C#中进行检查和验证的序列,我必须使用哪些因素才能将脚本应用到脚本中无论使用何种解释器,都可以生成并验证一个密钥。 – RobertPitt 2010-09-10 20:55:57

+0

我编辑了我的答案,以显示我在粘贴过程中所做的一些示例。 – Bot 2010-09-10 21:27:13

1

如果您想要集中创建随机序列号,只需从数字和字母数组中随机获取就足够了。使用mt_rand(0, count($poolArray))每次获得一个新的索引,只需将该字符添加到您的序列号中,直到您有12个字符。

从这样一个庞大的游泳池(26个字母+10位数)中随机生成它们几乎可以确保您没有重复,但您可以随时在存储新游戏之前检查现有游戏。

如果您有36个可能的字符,并且您从中随机选取12个字符串来制作您的连续字符串,即36 * 36 * 36 * ... * 36 = 36^12 = 4738381338321616896可能的字符串。

$pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
$countPool = count($pool) ; 
$totalChars = 12 ; 

$serial = '' ; 
for ($i = 0 ; $i < $totalChars ; $i++) { 
    $currIndex = mt_rand(0, $countPool) ; 
    $currChar = $pool[$currIndex] ; 
    $serial .= $currChar ; 
} 

分配他们与您的代码或让您的程序检查有效的序列是另一个问题。

+0

对不起,为什么'count($ pool)'给我的结果是101000100100,而如果我明确地分配了35,那么它的工作原理是3UNPWR3GWHQP,如果我分配了36,那么它的单位偏移量为 – Zyoo 2013-02-01 18:46:04

+0

@yolapop,你绝对正确。我的意思是把$ pool写成一个数组,但不知怎的,最后把它写成一个字符串。考虑它是一个数组和方法论的作品。 – Fanis 2013-02-02 15:03:52

11

已经很好回答的问题的答案很晚,但这是我们的解决方案。它会根据有效的IPv4,Userid(或任何有意义的整数)或文本字符串生成可配置大小/长度和可选后缀的密钥。它还避免了标准结果中的模糊字符(i,1,l,0,o,O)。

我们在许可证中附加了Userid,然后可以将该部分转换回base10整数,并检查它是否对使用许可证的用户帐户有效。

$license = generate_license(); 
// YF6G2-HJQEZ-8JZKY-8C8ZN 

$license = generate_license(123456); 
// ZJK82N-8GA5AR-ZSPQVX-2N9C 

$license = generate_license($_SERVER['REMOTE_ADDR']); 
// M9H7FP-996BNB-77Y9KW-ARUP4 

$license = generate_license('my text suffix'); 
// Q98K2F-THAZWG-HJ8R56-MY-TEXT-SUFFIX 

我们这样做时创建的数据库检查的独特性,但与随机性结合使用IP /用户ID,复制的可能性几乎为零。

/** 
* Generate a License Key. 
* Optional Suffix can be an integer or valid IPv4, either of which is converted to Base36 equivalent 
* If Suffix is neither Numeric or IPv4, the string itself is appended 
* 
* @param string $suffix Append this to generated Key. 
* @return string 
*/ 
function generate_license($suffix = null) { 
    // Default tokens contain no "ambiguous" characters: 1,i,0,o 
    if(isset($suffix)){ 
     // Fewer segments if appending suffix 
     $num_segments = 3; 
     $segment_chars = 6; 
    }else{ 
     $num_segments = 4; 
     $segment_chars = 5; 
    } 
    $tokens = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; 
    $license_string = ''; 
    // Build Default License String 
    for ($i = 0; $i < $num_segments; $i++) { 
     $segment = ''; 
     for ($j = 0; $j < $segment_chars; $j++) { 
      $segment .= $tokens[rand(0, strlen($tokens)-1)]; 
     } 
     $license_string .= $segment; 
     if ($i < ($num_segments - 1)) { 
      $license_string .= '-'; 
     } 
    } 
    // If provided, convert Suffix 
    if(isset($suffix)){ 
     if(is_numeric($suffix)) { // Userid provided 
      $license_string .= '-'.strtoupper(base_convert($suffix,10,36)); 
     }else{ 
      $long = sprintf("%u\n", ip2long($suffix),true); 
      if($suffix === long2ip($long)) { 
       $license_string .= '-'.strtoupper(base_convert($long,10,36)); 
      }else{ 
       $license_string .= '-'.strtoupper(str_ireplace(' ','-',$suffix)); 
      } 
     } 
    } 
    return $license_string; 
} 
2

我的解决方案

implode('-', str_split(substr(strtoupper(md5(time() . rand(1000, 9999))), 0, 20), 4)); 
+0

这非常优雅! – 2017-11-20 05:32:03

+0

好!鉴于串行你可以解码回日期? – 2018-01-01 17:28:09

相关问题