开发者

PHP license key generator

I'm looking for a开发者_StackOverflow社区 way to generate license keys by a PHP script and then transfer its to my application (Air, AS3), and in this application to read the data correctly. For example, here is the code:

<?php
  error_reporting(E_ALL);
  function KeyGen(){
     $key = md5(mktime());
     $new_key = '';
     for($i=1; $i <= 25; $i ++ ){
               $new_key .= $key[$i];
               if ( $i%5==0 && $i != 25) $new_key.='-';
     }
  return strtoupper($new_key);
  }
  echo KeyGen();
?>

The generates key about like this: 1AS7-09BD-96A1-CC8D-F106. I want to add some information into key - e-mail user, then pass it to the client (Air app), decrypt the data and dysplay in app.

Is it possible?


Ok lets break down what you are asking:

You want to:

  1. add some information into key
    Well what information do you want to add? Do you want to make the key longer when you do this? Do you want this information to require a key to decrypt? In the vaugest sense thats quite possible with PHP
  2. e-mail user
    PHP has a mail() function. It pretty much just works.
  3. then pass it to the client (Air app)
    Is the air app invoking this php script via a http request? if so set the content-type and output the key to it.
  4. decrypt the data Back to point 1, possible, but do you want a key or not, and do you care if the format changes. Also, don't you want to decrypt the data in the AS3 app?
  5. display in app. If the AS3 app is going to display the key, or the decrypted data, then it is AS3 where you need to get it to display the data.


If you just want to store some information but "encode" it using the set of symbols you used above (0-9A-Z), you can use the algorithm below.

The code is an old Python (3) program of mine. It's certainly not fancy in any way, nor very tested, but I suppose it's better than nothing since you haven't got many answers yet. It should be pretty easy to port the code to PHP or AS. The reduce statements can for example be replaced by imperative style loops. Also note that // denotes integer division in Python.

It should also be pretty easy to slap some compression/encryption onto it. Hope it resembles what you wanted. Here goes.

from functools import reduce

class Coder:
    def __init__(self, alphabet=None, groups=4):
        if not alphabet:
            alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        self.alphabet = alphabet
        self.groups = groups

    def encode(self, txt):
        N = len(self.alphabet)
        num = reduce(lambda x,y: (x*256)+y, map(ord, txt))

        # encode to alphabet
        a = []
        while num > 0:
            i = num % N
            a.append(self.alphabet[i])
            num -= i
            num = num//N

        c = "".join(a)
        if self.groups > 0:
            # right zero pad
            while len(c) % self.groups != 0:
                c = c + self.alphabet[0]
            # make groups
            return '-'.join([c[x*self.groups:(x+1)*self.groups]
                             for x in range(len(c)//self.groups)])
        return c

    def decode(self, txt, separator='-'):
        # remove padding zeros and separators
        x = txt.rstrip(self.alphabet[0])
        if separator != None:
            x = x.replace(separator, '')
        N = len(self.alphabet)
        x = [self.alphabet.find(c) for c in x]
        x.reverse()
        num = reduce(lambda x,y: (x*N)+y, x)

        a = []
        while num > 0:
            i = num % 256
            a.append(i)
            num -= i
            num = num//256
        a.reverse()
        return ''.join(map(chr, a))

if __name__ == "__main__":
    k = Coder()
    s = "Hello world!"
    e = k.encode(s)
    print("Encoded:", e)
    d = k.decode(e)
    print("Decoded:", d)

Example output:

Encoded: D1RD-YU0C-5NVG-5XL8-7620
Decoded: Hello world!


with md5 you cannot do this as this is a one-way hash. You should use a decipher method to do so as it uses a key to encode and decode it. There are several php extensions that can do this, consult php manual. You can also use a third party software to this, e.g. http://wwww.phplicengine.com


I found value in Andre's answer using Python.

I, like the question author, needed a php solution so I rewrote Andre's code as PHP. I am posting it here in case anyone else finds it useful.

HOWEVER, there are limitations with this that don't exist in the Python version:

It does not appear to encode any string larger than 8 characters. It may be solvable? It's something to do with how PHP handles very large integers. Thankfully I only need to encode less than 8 characters for my use case. It may work under different environments, I'm not sure. Anyway, with this caveat stated, here is the class:

<?php

/**
 * Basic key generator class based on a simple Python solution by André Laszlo.
 * It's probably not secure in any way, shape or form. But may be suitable for
 * your requirements (as it was for me).
 *
 * Due to limitations with PHP's processing of large integers, unlike the Python
 * app, only a small amount of data can be encoded / decoded. It appears to
 * allow a maximum of 8 unencoded characters.
 *
 * The original Python app is here: https://stackoverflow.com/a/6515005
 */

class KeyGen
{
    /**
     * @var array
     */
    protected $alphabet;

    /**
     * @var int
     */
    protected $groups;

    /**
     * @var string
     */
    protected $separator;

    /**
     * Controller sets the alphabet and group class properties
     *
     * @param  string $alphabet
     * @param  int $groups
     * @param  string $separator
     */
    public function __construct(string $alphabet = null, int $groups = 4, string $separator = '-')
    {
        $alphabet = $alphabet ?: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $this->alphabet = str_split($alphabet);
        $this->groups = $groups;
        $this->separator = $separator;
    }

    /**
     * Encodes a string into a typical license key format
     *
     * @param  string $txt
     * @return string
     */
    public function encode(string $txt)
    {
        // calculate the magic number
        $asciiVals = array_map('ord', str_split($txt));
        $num = array_reduce($asciiVals, function($x, $y) {
            return ($x * 256) + $y;
        });

        // encode
        $a = [];
        $i = 0;
        $n = count($this->alphabet);
        while ($num > 0) {
            $i = $num % $n;
            array_push($a, $this->alphabet[$i]);
            $num -= $i;
            $num = intdiv($num, $n);
        }

        // add padding digits
        $str = implode('', $a);
        if($this->groups > 0) {
            while (strlen($str) % $this->groups != 0) {
                $str .= $this->alphabet[0];
            }
        }

        // split into groups
        if($this->groups) {
            $split = str_split($str, $this->groups);
            $str = implode($this->separator, $split);
        }

        return $str;
    }

    /**
     * Decodes a license key
     *
     * @param  string $txt
     * @return string
     */
    public function decode(string $txt)
    {
        // remove separators and padding
        $stripped = str_replace($this->separator, '', $txt);
        $stripped = rtrim($stripped, $this->alphabet[0]);

        // get array of alphabet positions
        $alphabetPosistions = [];
        foreach(str_split($stripped) as $char){
            array_push($alphabetPosistions, array_search($char, $this->alphabet));
        }

        // caluculate the magic number
        $alphabetPosistions = array_reverse($alphabetPosistions);
        $num = array_reduce($alphabetPosistions, function($x, $y) {
            $n = count($this->alphabet);
            return ($x * $n) + $y;
        });

        // decode
        $a = [];
        $i = 0;
        $n = count($this->alphabet);
        while ($num > 0) {
            $i = $num % 256;
            array_push($a, $i);
            $num -= $i;
            $num = intdiv($num, 256);
        }

        return implode('', array_map('chr', array_reverse($a)));
    }

}

And here is an example usage, encoding and decoding "ABC123":

$keyGen = new KeyGen();

$encoded = $keyGen->encode('ABC123'); //returns 3WJU-YSMF-P000

$decoded = $keyGen->decode('3WJU-YSMF-P000'); //returns ABC123
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜