作为一名PHP程序员和C#编程初学者,我一直想知道生成独特的串行数据的最佳方式,例如Microsoft Office和Microsoft操作系统的工作方式。使用PHP进行串行生成
有没有人有一个很好的指导如何处理这一点,像什么是生成独特的序列,防止重复等重要因素如何创建/验证它们的小例子。
这里是我正在谈论的RFC:http://tools.ietf.org/html/rfc1982。
作为一名PHP程序员和C#编程初学者,我一直想知道生成独特的串行数据的最佳方式,例如Microsoft Office和Microsoft操作系统的工作方式。使用PHP进行串行生成
有没有人有一个很好的指导如何处理这一点,像什么是生成独特的序列,防止重复等重要因素如何创建/验证它们的小例子。
这里是我正在谈论的RFC:http://tools.ietf.org/html/rfc1982。
如果您的应用程序有一个连接回到服务器,那么只需生成随机令牌,将它们存储在数据库中,并要求应用程序在运行前检查服务器。但是有些客户可能会发现这个要求是不可接受的。 (我个人绝不会与互联网激活要求购买任何软件,我想购买软件,而不是把它租。)
对于真实性checkability键,而无需有一个连接到服务器:
在服务器上,生成一个随机的唯一标记。
使用公钥加密方案(例如RSA)使用对服务器保密的私钥对令牌进行签名。
使用一些二进制到文本方案(例如,base64或仅使用2-9A-KMNP-Z
符号以实现更安全的可打字性)将唯一标记和签名一起编码。编码的组合是您的钥匙或串行。
在应用程序的每个副本中嵌入与服务器私钥匹配的公钥,并在安装时让应用程序提示输入密钥。它可以拆分唯一标记和签名,并使用公钥来验证签名对该标记是否有效。
这种方法需要你捆绑一些加密库与你的软件,和大多数算法使用了相当长的签名,为了安全,这将使你的序列号,相当乏味的输入,如果你希望用户能够复制它的确定并粘贴数字。
由于这些原因,许多软件包使用不太安全的密钥验证方案,其中检查算法完全内置于客户端。这可能是一个散列,例如。串行的最后四个十六进制数字必须与串行其余部分的SHA1散列的最低两个字节匹配,并与“秘密”密钥相结合。但是,由于密钥必须捆绑在应用程序中,所以黑客可能会查看应用程序代码并提取“秘密”密钥,从而允许他们编写自己的密钥生成器。
这就是为什么对于某些程序,您会看到'keygens'可用:应用程序使用安全性较低的检查算法,在应用程序中留下足够的信息以允许cracker重新生成密钥制作过程。对于基于公钥密码或互联网激活的更安全设置的程序,您通常会看到应用程序的“破解”版本,而检查代码已被更改/删除。
......哪种表现无论你做什么,你仍然无法执行诚实。所以不要太担心。
我不是很确定你想要什么,但有http://www.php.net/manual/en/function.uniqid.php它创建唯一标识符。
如果您对它们的创建方式更感兴趣,我建议您查看一下PHP源代码,以了解uniqid是如何实现的。
林的问候交谈http://tools.ietf.org/html/rfc1982 – RobertPitt 2010-09-10 20:13:28
uniqid是完全可以预见的。实际上,它只是它生成的microtime的一个代表。它绝不是随机的。 – NikiC 2010-09-10 20:26:17
需要更多信息。你想创建一个序列键,比如你购买一款游戏,或者你想要一个序列号作为唯一的用户ID。
序列号是否需要存储过期时间/日期等信息?
@nikic - 所有rand的使用时间作为启动随机生成器的基础。这就是国防部使用熔岩灯的原因。他们有一个整个房间专用于熔岩灯和闪耀的激光,随机创建一个独特的钥匙。
编辑:
那么你需要考虑到影响的只是你的C#应用程序会用什么方法与您的网站进行通信。
您将需要使用php创建一个密钥并将其存储在数据库中,以便C#可以确认该串行是正确的。
然后您需要弄清楚PHP是否会返回另一个值,以便C#应用程序知道密钥是否已通过身份验证。
我在粘贴中做了什么是创建一个公钥和私钥。公钥将提供给用户验证产品。当他们验证产品或登录到系统时,将根据数据库检查公钥,返回值将是私钥。在与我的C#程序的所有交互过程中,如果用户需要检查更新或从我的服务器获取信息,私钥将被添加到服务器的查询中,以确认最终用户是合法的。
我还使用的另一种方法是上面的,但增加了额外的检查以确认用户不共享密钥。 C#应用程序将获得计算机中处理器的序列号,并在注册该应用程序时将其保存到我的数据库中。然后,如果有人试图用相同的公钥注册产品但处理器的序列号不同,则会发出错误,他们需要联系支持人员。你可以这样做,以允许5个不同的机器ID或每个你想要的。
创建注册码非常简单,因为您实际上只需要创建一个具有偏移量的随机字符串(例如用户名)。
但是,您也可以根据某人提供的名称或公司名称创建注册码,并将该算法添加到C#程序中。不利之处在于C#源代码可以轻松地反编译,可以发现该算法很容易创建注册码,而无需真正为产品付费。通过添加身份验证的服务器,对于某人来说,生成自己的序列密钥要困难得多。
可以说我有一个产品,比如应用程序,这个应用程序需要一个串行系统,我想在PHP中生成一个可以在C#中进行检查和验证的序列,我必须使用哪些因素才能将脚本应用到脚本中无论使用何种解释器,都可以生成并验证一个密钥。 – RobertPitt 2010-09-10 20:55:57
我编辑了我的答案,以显示我在粘贴过程中所做的一些示例。 – Bot 2010-09-10 21:27:13
如果您想要集中创建随机序列号,只需从数字和字母数组中随机获取就足够了。使用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 ;
}
分配他们与您的代码或让您的程序检查有效的序列是另一个问题。
已经很好回答的问题的答案很晚,但这是我们的解决方案。它会根据有效的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;
}
我的解决方案
implode('-', str_split(substr(strtoupper(md5(time() . rand(1000, 9999))), 0, 20), 4));
这非常优雅! – 2017-11-20 05:32:03
好!鉴于串行你可以解码回日期? – 2018-01-01 17:28:09
周围信息很好 – Fanis 2010-09-10 21:03:56
完美,只是我一直在寻找的信息类型:),非常棒的阅读。 +1 – RobertPitt 2010-09-10 21:12:59
: - 这正是我所说的。 – Bot 2010-09-11 16:50:47