草庐IT

php - 检查生成的许可证是否有效

coder 2023-12-31 原文

我有一个 PHP 脚本可以生成一些字符串,这些字符串将用作许可证 key :

function KeyGen(){
     $key = md5(microtime());
     $new_key = '';
     for($i=1; $i <= 25; $i ++ ){
               $new_key .= $key[$i];
               if ( $i%5==0 && $i != 25) $new_key.='-';
     }
  return strtoupper($new_key);
  }
$x = 0;
while($x <= 10) {
  echo KeyGen();
  echo "<br />";
$x++; 
}

运行一次脚本后,我得到了这些:

8B041-EC7D2-0B9E3-09846-E8C71
C8D82-514B9-068BC-8BF80-05061
A18A3-E05E5-7DED7-D09ED-298C4
FB1EC-C9844-B9B20-ADE2F-0858F
E9AED-945C8-4BAAA-6938D-713ED
4D284-C5A3B-734DF-09BD6-6A34C
EF534-3BAE4-860B5-D3260-1CEF8
D84DB-B8C72-5BDEE-1B4FE-24E90
93AF2-80813-CD66E-E7A5E-BF0AE
C3397-93AA3-6239C-28D9F-7A582
D83B8-697C6-58CD1-56F1F-58180

我现在要做的是更改它,以便我有另一个函数来检查 key 是否已使用我的脚本生成。目前,我在想的是将 $key 设置为一个特定字符串的 MD5(例如,test),但是,当然,这会返回所有相同的字符串.

有人能帮忙吗?

最佳答案

有三种基本的处理方法。您如何操作将取决于您生成的 key 数量,以及能够在以后使 key 失效的重要性。选择哪种取决于您。

选项 1:服务器数据库存储

当服务器生成 key (例如使用您的算法)时,您将其存储在数据库中。然后稍后您需要做的就是检查 key 是否在数据库中。

注意您的算法需要的熵比您提供的要多得多。当前时间戳不够。相反,使用强随机性:

$key = mcrypt_create_iv($length_needed, MCRYPT_DEV_URANDOM);

或者,如果您没有 mcrypt:

$key = openssl_random_pseudo_bytes($length_needed);

或者,如果您没有 mcrypt 和 openssl,请使用 a library

请注意,md5 返回一个十六进制输出 (a-f0-9),其中所有上述返回完全随机二进制字符串(字符 0 - 255)。所以要么 base64_encode() 它,要么 bin2hex() 它。

优点:

  • 易于实现
  • 可以在以后“停用”颁发的 key
  • 无法伪造新 key

缺点:

  • 需要每个 key 的持久存储
  • 可能无法很好地扩展
  • 需要“ key 服务器”来验证 key

选项 2:签名 key

基本上,您生成一个强随 secret 钥(从这里开始称为私钥),并将其存储在您的服务器上。然后,在生成许可证 key 时,您生成一个随机 blob,然后 HMAC 使用私钥对其进行签名,并使许可证成为该 block 的一部分。这样,您就不需要存储每个单独的 key 。

function create_key($private_key) {
    $rand = mcrypt_create_iv(10, MCRYPT_DEV_URANDOM);
    $signature = substr(hash_hmac('sha256', $rand, $private_key, true), 0, 10);
    $license = base64_encode($rand . $signature);
    return $license;
}

function check_key($license, $private_key) {
    $tmp = base64_decode($license);
    $rand = substr($tmp, 0, 10);
    $signature = substr($tmp, 10);
    $test = substr(hash_hmac('sha256', $rand, $private_key, true), 0, 10);
    return $test === $signature;
}
    

优点:

  • 易于实现
  • 不需要持久存储
  • 微不足道的规模

缺点:

  • 不能单独“停用” key
  • 需要存储“私钥”
  • 需要“ key 服务器”来验证 key 。

选项 3:公钥加密

基本上,您生成一个公钥/私钥对。您将公钥嵌入到您的应用程序中。然后,您生成一个 key (类似于上面的“签名 key ”),但不是使用 HMAC 签名,而是使用私钥对其进行签名。

这样,应用程序(拥有公钥)可以直接验证签名,而无需回调到您的服务器。

function create_key($private_key) {
    $rand = mcrypt_create_iv(10, MCRYPT_DEV_URANDOM);

    $pkeyid = openssl_get_privatekey($private_key);
    openssl_sign($rand, $signature, $pkeyid);
    openssl_free_key($pkeyid);

    $license = base64_encode($rand . $signature);
    return $license;
}

function check_key($license, $public_key) {
    $tmp = base64_decode($license);
    $rand = substr($tmp, 0, 10);
    $signature = substr($tmp, 10);

    $pubkeyid = openssl_get_publickey($public_key);
    $ok = openssl_verify($rand, $signature, $pubkeyid);
    openssl_free_key($pubkeyid);

    return $ok === 1;
}

优点:

  • 易于实现
  • 不需要持久存储
  • 微不足道的规模
  • 不需要“ key 服务器”来验证 key

缺点:

  • 不能单独“停用” key
  • 需要存储“私钥”

关于php - 检查生成的许可证是否有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16213566/

有关php - 检查生成的许可证是否有效的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  4. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  5. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  6. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  7. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  8. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  9. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  10. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

随机推荐