2010-09-10 37 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

相關問題