first commit
This commit is contained in:
130
pgserver/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Integer.php
vendored
Normal file
130
pgserver/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Integer.php
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of the PHPASN1 library.
|
||||
*
|
||||
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace FG\ASN1\Universal;
|
||||
|
||||
use Exception;
|
||||
use FG\Utility\BigInteger;
|
||||
use FG\ASN1\Exception\ParserException;
|
||||
use FG\ASN1\ASNObject;
|
||||
use FG\ASN1\Parsable;
|
||||
use FG\ASN1\Identifier;
|
||||
|
||||
class Integer extends ASNObject implements Parsable
|
||||
{
|
||||
/** @var int */
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @param int $value
|
||||
*
|
||||
* @throws Exception if the value is not numeric
|
||||
*/
|
||||
public function __construct($value)
|
||||
{
|
||||
if (is_numeric($value) == false) {
|
||||
throw new Exception("Invalid VALUE [{$value}] for ASN1_INTEGER");
|
||||
}
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return Identifier::INTEGER;
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
protected function calculateContentLength()
|
||||
{
|
||||
return strlen($this->getEncodedValue());
|
||||
}
|
||||
|
||||
protected function getEncodedValue()
|
||||
{
|
||||
$value = BigInteger::create($this->value, 10);
|
||||
$negative = $value->compare(0) < 0;
|
||||
if ($negative) {
|
||||
$value = $value->absoluteValue();
|
||||
$limit = 0x80;
|
||||
} else {
|
||||
$limit = 0x7f;
|
||||
}
|
||||
|
||||
$mod = 0xff+1;
|
||||
$values = [];
|
||||
while($value->compare($limit) > 0) {
|
||||
$values[] = $value->modulus($mod)->toInteger();
|
||||
$value = $value->shiftRight(8);
|
||||
}
|
||||
|
||||
$values[] = $value->modulus($mod)->toInteger();
|
||||
$numValues = count($values);
|
||||
|
||||
if ($negative) {
|
||||
for ($i = 0; $i < $numValues; $i++) {
|
||||
$values[$i] = 0xff - $values[$i];
|
||||
}
|
||||
for ($i = 0; $i < $numValues; $i++) {
|
||||
$values[$i] += 1;
|
||||
if ($values[$i] <= 0xff) {
|
||||
break;
|
||||
}
|
||||
assert($i != $numValues - 1);
|
||||
$values[$i] = 0;
|
||||
}
|
||||
if ($values[$numValues - 1] == 0x7f) {
|
||||
$values[] = 0xff;
|
||||
}
|
||||
}
|
||||
$values = array_reverse($values);
|
||||
$r = pack("C*", ...$values);
|
||||
return $r;
|
||||
}
|
||||
|
||||
private static function ensureMinimalEncoding($binaryData, $offsetIndex)
|
||||
{
|
||||
// All the first nine bits cannot equal 0 or 1, which would
|
||||
// be non-minimal encoding for positive and negative integers respectively
|
||||
if ((ord($binaryData[$offsetIndex]) == 0x00 && (ord($binaryData[$offsetIndex+1]) & 0x80) == 0) ||
|
||||
(ord($binaryData[$offsetIndex]) == 0xff && (ord($binaryData[$offsetIndex+1]) & 0x80) == 0x80)) {
|
||||
throw new ParserException("Integer not minimally encoded", $offsetIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
|
||||
{
|
||||
$parsedObject = new static(0);
|
||||
self::parseIdentifier($binaryData[$offsetIndex], $parsedObject->getType(), $offsetIndex++);
|
||||
$contentLength = self::parseContentLength($binaryData, $offsetIndex, 1);
|
||||
|
||||
if ($contentLength > 1) {
|
||||
self::ensureMinimalEncoding($binaryData, $offsetIndex);
|
||||
}
|
||||
$isNegative = (ord($binaryData[$offsetIndex]) & 0x80) != 0x00;
|
||||
$number = BigInteger::create(ord($binaryData[$offsetIndex++]) & 0x7F);
|
||||
|
||||
for ($i = 0; $i < $contentLength - 1; $i++) {
|
||||
$number = $number->multiply(0x100)->add(ord($binaryData[$offsetIndex++]));
|
||||
}
|
||||
|
||||
if ($isNegative) {
|
||||
$number = $number->subtract(BigInteger::create(2)->toPower(8 * $contentLength - 1));
|
||||
}
|
||||
|
||||
$parsedObject = new static((string)$number);
|
||||
$parsedObject->setContentLength($contentLength);
|
||||
|
||||
return $parsedObject;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user