2010-09-10 2 views
5

На протяжении моих дней в качестве программиста на PHP и начинающего программиста на C# я всегда интересовался лучшим способом создания уникальных сериалов, например, как это делают операционные системы Microsoft Office и Microsoft.Последовательная генерация с PHP

Есть ли у кого-нибудь хорошее руководство, как справиться с этим, Как то, что является важным фактором при создании уникального серийного номера, предотвращать дубликаты и т. Д. Небольшой пример того, как их создавать и проверять.

Вот RFC, о котором я говорю: http://tools.ietf.org/html/rfc1982.

ответ

12

Если ваше приложение подключено к серверу, оно тривиально, просто создайте случайные токены, сохраните их в базе данных и попросите приложение проверить сервер с сервера перед запуском. Однако некоторые клиенты могут считать это требование неприемлемым. (Лично я никогда не буду покупать программное обеспечение с требованием активации интернет я хочу купить программное обеспечение, не сдавать его в аренду..)

для ключей с Подлинность проверяемость без необходимости иметь подключение к серверу:

  1. На сервере создайте случайный уникальный токен.

  2. Используйте криптографическую схему с открытым ключом (например, RSA), чтобы подписать токен с закрытым ключом, который хранится в секрете на сервере.

  3. Кодировать уникальный токен и подпись вместе с использованием некоторой двоичной-текстовой схемы (например, base64 или просто используя символы 2-9A-KMNP-Z для более безопасной типизации). Закодированная комбинация - это ваш ключ или серийный номер.

  4. Вставьте открытый ключ, соответствующий секретному ключу сервера в каждой копии приложения, и получите приглашение приложения для ключа во время установки. Он может разделить уникальный токен и подпись и использовать открытый ключ, чтобы убедиться, что подпись действительна для этого токена.

Этот подход требует, чтобы вы связать некоторые криптографические библиотеки с программным обеспечением, и большинство алгоритмов используют довольно длинные подписи, в целях безопасности, которые сделают ваши серийные номера довольно утомительно ввести. Это нормально, если вы ожидаете пользователей копировать и вставьте числа.

По этим причинам многие программные пакеты используют менее надежную схему проверки ключа, в которой алгоритм проверки полностью встроен в клиент. Это может быть хэш, например. последние четыре шестнадцатеричных цифры серийного номера должны соответствовать самым низким двум байтам хэша SHA1 остальной части последовательного файла в сочетании с «секретным» ключом. Однако, поскольку ключ должен быть включен в приложение, хакер может посмотреть код приложения и извлечь секретный ключ, позволяющий им создавать собственные генераторы ключей.

Именно поэтому для некоторых программ вы увидите доступные «кейгены»: приложение использовало менее надежный контрольный алгоритм, который оставил достаточно информации в приложении, чтобы позволить взломщику воспроизвести процесс создания ключа. Для программ с более безопасной настройкой, основанной на криптографии или активации интернет-ключа, вы обычно видите «взломанную» версию приложения, где код проверки был изменен/удален.

... какой вид показывает, что, что бы вы ни делали, вы по-прежнему не сможете обеспечить честность. Поэтому не беспокойтесь об этом слишком много.

+0

Хорошо обо всем информации – Fanis

+0

Отлично, только тип информации, которую я искал :), Отлично читал. +1 – RobertPitt

+1

: - Это именно то, что я сказал. – Bot

1

Я не совсем уверен, что вы хотите, но есть http://www.php.net/manual/en/function.uniqid.php, который создает уникальные идентификаторы.

Если вас больше интересует, как они созданы, я бы посоветовал вам взглянуть на источник PHP, чтобы узнать, как реализован uniqid.

+0

Im говорить относительно http://tools.ietf.org/html/rfc1982 – RobertPitt

+0

uniqid вполне предсказуемо. На самом деле это всего лишь представление о микро-времени, в котором оно было создано. Это никоим образом не является случайным. – NikiC

1

Требуется дополнительная информация. Вы хотите создать серийный ключ, например, когда вы покупаете игру, или хотите получить серийный номер для уникального идентификатора пользователя.

Могут ли серийные номера хранить информацию, такую ​​как время/дата истечения срока?

@nikic - все время использования rand в качестве основы для запуска случайного генератора. Вот почему в DoD используются лавовые лампы. У них есть целая комната, посвященная лавовым лампам и сияющим лазерам на них, чтобы случайным образом создать уникальный ключ.

Отредактировано:

Ну, что вам нужно принять в силу то, что ваш метод C# приложение будет использовать для связи с вашим сайтом.

Вам нужно будет создать ключ с php и сохранить его в базе данных, чтобы C# мог подтвердить, что серийный номер правильный.

Затем вам нужно выяснить, вернет ли PHP другое значение, поэтому приложение C# знает, что ключ был аутентифицирован или нет.

Что я сделал в вставленном виде, это создать открытый ключ и закрытый ключ. Открытый ключ будет предоставлен пользователю для проверки продукта. Когда они проверяют продукт или вход в систему, открытый ключ будет проверяться в отношении базы данных, а возвращаемое значение будет закрытым. Во время всех взаимодействий с моей программой на C# пользователю необходимо проверить наличие обновлений или вывести информацию с моего сервера, частный ключ будет добавлен в запрос на сервер, чтобы подтвердить, что конечный пользователь был прав.

Другой метод, который я также использовал, является приведенным выше, но добавил дополнительную проверку, чтобы подтвердить, что пользователь не делил ключ. Приложение C# получит серийный номер процессора в компьютере и после регистрации приложения оно сохранит его в моей базе данных. Затем, если кто-то еще попытался зарегистрировать продукт с тем же открытым ключом, но с другим серийным номером процессора, он выкинул бы ошибку, и им нужно было бы обратиться в службу поддержки. Вы можете сделать это, чтобы разрешить 5 разных идентификаторов машины или как их использовать.

Создание регистрационного ключа очень просто, так как вам действительно нужно создать случайную строку со смещением (например, имя пользователя).

Вы также можете создать регистрационный ключ на основе имени или названия компании, которое предоставляет кто-то, и добавить этот алгоритм к вашей программе на C#. Недостатком этого является исходный код C#, который может быть легко декомпилирован, и алгоритм может быть легко создан для создания регистрационного кода без фактического оплаты продукта.Добавляя на сервере, который выполняет аутентификацию, для кого-то гораздо сложнее создать собственный серийный ключ.

+0

позволяет сказать, что у меня есть продукт, такой как приложение, для этого приложения требуется последовательная система, я хочу сгенерировать серию на PHP, которая может быть проверена и проверена на C#, какие факторы я должен использовать в сценарии, чтобы быть в состоянии генерировать и проверять A ключ независимо от того, какой интерпретатор. – RobertPitt

+0

Я отредактировал свой ответ, чтобы показать некоторые примеры того, что я сделал в вставленном. – Bot

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

+0

@yolapop, вы абсолютно правы. Я имел в виду написать $ pool как массив, но каким-то образом написал его как строку. Рассмотрим его как массив и методология. – Fanis

11

Очень поздний ответ на уже хорошо ответил на вопрос, но вот наше решение. Он генерирует ключ с настраиваемым размером/длиной и дополнительным суффиксом на основе действительного IPv4, Userid (или любого значимого целого) или текстовой строки. Он также избегает двусмысленных символов (i, 1, l, 0, o, O) в стандартном результате.

Мы добавляем Userid в лицензию и можем позже преобразовать эту часть обратно в base10 integer и проверить, действительно ли она действительна для учетной записи пользователя, использующего лицензию.

$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/USERID в сочетании с случайностью, вероятность дублей практически равна нулю.

/** 
* 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

Это очень элегантно! –

+0

Хорошо! учитывая Serial, вы можете декодировать обратно к дате? –