我正在考虑实现此处概述的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!
}