在我作为 PHP 程序员和 C# 编程初学者的整个日子里,我一直想知道生成独特连续剧的最佳方法,例如 Microsoft Office 和 Microsoft 操作系统的工作方式。
有没有人有一个很好的指南来处理这个问题,比如生成唯一序列的重要因素是什么,防止重复等等。关于如何创建/验证它们的小例子。
这是我正在谈论的 RFC:https ://www.rfc-editor.org/rfc/rfc1982 。
在我作为 PHP 程序员和 C# 编程初学者的整个日子里,我一直想知道生成独特连续剧的最佳方法,例如 Microsoft Office 和 Microsoft 操作系统的工作方式。
有没有人有一个很好的指南来处理这个问题,比如生成唯一序列的重要因素是什么,防止重复等等。关于如何创建/验证它们的小例子。
这是我正在谈论的 RFC:https ://www.rfc-editor.org/rfc/rfc1982 。
这是我们的解决方案。它根据有效的 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;
}
如果您的应用程序有一个与服务器的连接,这很简单,只需生成随机令牌,将它们存储在数据库中,并要求应用程序在运行之前与服务器进行核对。然而,一些客户可能会发现这个要求是不可接受的。(我个人永远不会购买任何需要互联网激活的软件。我想购买软件,而不是租用它。)
对于具有真实性可检查性而无需连接回服务器的密钥:
在服务器上,生成一个随机的唯一令牌。
使用公钥加密方案(例如RSA)使用对服务器保密的私钥对令牌进行签名。
使用一些二进制到文本的方案(例如,base64,或仅使用2-9A-KMNP-Z
符号以实现更安全的打字)将唯一令牌和签名一起编码。编码组合是您的密钥或序列号。
在应用程序的每个副本中嵌入与服务器的私钥匹配的公钥,并在安装时让应用程序提示输入密钥。它可以拆分唯一令牌和签名,并使用公钥来验证签名对该令牌是否有效。
这种方法要求您将一些加密库与您的软件捆绑在一起,并且大多数算法都使用相当长的签名,以确保安全,这将使您的序列号输入非常繁琐。如果您希望用户复制并粘贴数字也可以。
由于这些原因,许多软件包使用安全性较低的密钥验证方案,其中检查算法完全内置在客户端中。这可能是一个哈希,例如。序列的最后四个十六进制数字必须与序列其余部分的 SHA1 散列的最低两个字节与“秘密”密钥相匹配。然而,由于密钥必须捆绑在应用程序中,黑客有可能查看应用程序代码并提取“秘密”密钥,从而允许他们编写自己的密钥生成器。
这就是为什么对于某些程序,您会看到“keygens”可用:该应用程序使用了一种安全性较低的检查算法,该算法在应用程序中留下了足够的信息,以允许破解者重现密钥制作过程。对于基于公钥加密或互联网激活的更安全设置的程序,您通常会看到应用程序的“破解”版本,其中检查代码已被更改/删除。
...这表明无论你做什么,你仍然无法做到诚实。所以不要太担心它。
我的解决方案
implode( '-', str_split( substr( strtoupper( md5( time() . rand( 1000, 9999 ) ) ), 0, 20 ), 4 ) );
如果您想集中创建随机序列号,只需从数字和字母数组中随机获取就足够了。mt_rand(0, count($poolArray))
每次都使用获取新索引,然后将该字符添加到您的序列中,直到您说出其中的 12 个。
从如此大的池(26 个字母 + 10 位数字)中随机生成它们几乎可以确保您没有重复,但您始终可以在存储新的之前检查现有的。
如果您有 36 个可能的字符,并且您从其中随机选择 12 个来制作连续剧,那就是 36*36*36*...*36 = 36^12 = 4738381338321616896 个可能的字符串。
$pool = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$countPool = strlen($pool) - 1;
$totalChars = 12;
$serial = '' ;
for ($i = 0 ; $i < $totalChars ; $i++) {
$currIndex = mt_rand(0, $countPool) ;
$currChar = $pool[$currIndex] ;
$serial .= $currChar ;
}
将它们与您的代码一起分发或让您的程序检查有效的序列是另一个问题。
我不确定你想要什么,但有http://www.php.net/manual/en/function.uniqid.php可以创建唯一标识符。
如果您对它们的创建方式更感兴趣,我建议您查看 PHP 源代码以了解 uniqid 是如何实现的。
需要更多信息。您是想在购买游戏时创建一个序列号,还是想为一个唯一的用户 ID 创建一个序列号。
序列号是否需要存储过期时间/日期等信息?
@nikic - 所有 rand 的使用时间作为启动随机生成器的基础。这就是国防部使用熔岩灯的原因。他们有一个专门用于熔岩灯的房间,并在上面照射激光以随机创建一个独特的钥匙。
编辑:
那么您需要生效的是您的 C# 应用程序将使用哪种方法与您的站点进行通信。
您需要使用 php 创建一个密钥并将其存储在数据库中,以便 C# 可以确认序列号是正确的。
然后,您需要确定 PHP 是否会返回另一个值,以便 C# 应用程序知道密钥是否经过身份验证。
我在粘贴中所做的是创建一个公钥和私钥。公钥将提供给用户以验证产品。当他们验证产品或登录系统时,将根据数据库检查公钥,返回值将是私钥。在与我的 C# 程序的所有交互过程中,如果用户需要检查更新或从我的服务器提取信息,私钥将被添加到服务器的查询中,以确认最终用户是合法的。
我也使用的另一种方法是上述方法,但添加了额外的检查以确认用户没有共享密钥。C# 应用程序将获取计算机中处理器的序列号,并在注册应用程序后将其保存到我的数据库中。然后,如果其他人尝试使用相同的公钥但处理器的序列号不同来注册产品,则会引发错误,他们需要联系支持。您可以这样做以允许 5 个不同的机器 ID 或您想要多少个。
创建注册密钥非常简单,因为您实际上只需要创建一个带有偏移量的随机字符串(例如用户名)。
但是,您也可以根据某人提供的名称或公司名称创建注册密钥,并将该算法添加到您的 C# 程序中。这样做的缺点是 C# 源代码可以很容易地反编译,可以找到该算法来轻松创建注册代码,而无需有人实际为产品付费。通过添加执行身份验证的服务器,某人生成自己的序列密钥要困难得多。