将数据嵌入序列号中


Embedding data in a serial number

我正在考虑实现此处概述的PVKS。我让它按照文章中介绍的那样工作(但在 PHP 中),但是我有一个额外的要求,我试图弄清楚如何满足。我正在尝试弄清楚如何将日期和 3 位数字嵌入到生成的代码中。我什至不确定从哪里开始,所以老实说我没有尝试过任何东西。不幸的是,它们在组合中不会是唯一的,所以我无法对它们的种子值进行哈希处理。据我所知,我也不能让它们成为 getKeyByte 函数的一部分,因为该函数的输入应该只是种子和一些参数,其中这些参数定义了有效键的算法。它们在生成器和验证器之间必须是相同的,因此它们必须是静态的。这种任务有公认的做法吗?

设法自己弄清楚了这个问题。我意识到我试图找到一种可以将值编码为键字节的方法,从而使事情过于复杂。执行此操作的方法(好吧,我这样做的方式)只是在密钥字节之后和校验和之前添加额外的字节。它们不需要像其他密钥字节那样进行验证,但会影响校验和。

下面是我的课程中与生成和验证密钥相关的部分,并注明了我需要添加的新部分。

static public function generateKey($extraKeyArgs = array(), $encodedData = array())
{
    $args = self::instanceKeyArgs($extraKeyArgs);
    $keyBytes = array();
    $seed = self::getSeed();
    $hexSeed = self::intToHex($seed,self::$seedWidth);
    $key = $hexSeed;
    $numKeys = count($args);
    for ($i=0; $i < $numKeys; $i++) {
        list($a, $b, $c) = $args[$i];
        $keyBytes[$i] = self::getKeyByte($seed, $a, $b, $c, self::$keyWidthBytes);
        $key .= self::intToHex($keyBytes[$i],self::$keyWidthHex);
    }
    // Section added to handle encoded data
    foreach ($encodedData as $data) {
        // Make $data an integer value, one byte wide.
        $data = (((int) $data) & 255);
        $keyBytes[] = $data;
        $numKeys++;
        $key .= self::intToHex($data,self::$keyWidthHex);
    }
    // End Section
    $checksum = self::getChecksum($key);
    $key = $hexSeed . self::$seperator;
    for ($i=0; $i < $numKeys; $i++) {
        $key .= self::intToHex($keyBytes[$i],self::$keyWidthHex);
        if ($i & 1) {
            $key .= self::$seperator;
        }
    }
    if (substr($key, -1) !== self::$seperator) {
        $key .= self::$seperator;
    }
    $key .= $checksum;
    return $key;
}
static public function checkKey($key, $extraKeyArgs = array(), &$data = array())
{
    $args = self::instanceKeyArgs($extraKeyArgs);
    $numKeys = count($args);
    if (!self::checkKeyChecksum($key)) {
        return false;   // Failed checksum! Maybe a mistype or optical reader error?
    }
    $key = self::normalizeKey($key);
    // TODO - we would check against a blacklist here if we wanted to implement that.
    $seed = hexdec(substr($key,0,self::$seedWidth));
    if (!is_int($seed) || $seed < 1) {
        return false;   // Failed to get seed. Are you sure this key came from here?
    }
    $key = substr($key, self::$seedWidth, (strlen($key) - (self::$seedWidth + self::$checksumWidth)));
    for ($i=0; $i < $numKeys; $i++) {
        $keyByte = substr($key, 0, self::$keyWidthHex);
        $key = substr($key, self::$keyWidthHex);
        list($a, $b, $c) = $args[$i];
        if ($keyByte !== self::intToHex(self::getKeyByte($seed, $a, $b, $c, self::$keyWidthBytes),2)) {
            return false;   // Key byte failed check. Possible forgery attempt?
        }
    }
    // This line added to handle encoded data
    $data = array_map('hexdec', str_split($key, self::$keyWidthHex));
    return true; // Valid Key, Yay!
}