[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/fgrosse/phpasn1/lib/ASN1/ -> ASNObject.php (source)

   1  <?php
   2  /*
   3   * This file is part of the PHPASN1 library.
   4   *
   5   * Copyright © Friedrich Große <[email protected]>
   6   *
   7   * For the full copyright and license information, please view the LICENSE
   8   * file that was distributed with this source code.
   9   */
  10  
  11  namespace FG\ASN1;
  12  
  13  use FG\ASN1\Exception\ParserException;
  14  use FG\ASN1\Universal\BitString;
  15  use FG\ASN1\Universal\Boolean;
  16  use FG\ASN1\Universal\Enumerated;
  17  use FG\ASN1\Universal\GeneralizedTime;
  18  use FG\ASN1\Universal\Integer;
  19  use FG\ASN1\Universal\NullObject;
  20  use FG\ASN1\Universal\ObjectIdentifier;
  21  use FG\ASN1\Universal\RelativeObjectIdentifier;
  22  use FG\ASN1\Universal\OctetString;
  23  use FG\ASN1\Universal\Sequence;
  24  use FG\ASN1\Universal\Set;
  25  use FG\ASN1\Universal\UTCTime;
  26  use FG\ASN1\Universal\IA5String;
  27  use FG\ASN1\Universal\PrintableString;
  28  use FG\ASN1\Universal\NumericString;
  29  use FG\ASN1\Universal\UTF8String;
  30  use FG\ASN1\Universal\UniversalString;
  31  use FG\ASN1\Universal\CharacterString;
  32  use FG\ASN1\Universal\GeneralString;
  33  use FG\ASN1\Universal\VisibleString;
  34  use FG\ASN1\Universal\GraphicString;
  35  use FG\ASN1\Universal\BMPString;
  36  use FG\ASN1\Universal\T61String;
  37  use FG\ASN1\Universal\ObjectDescriptor;
  38  use FG\Utility\BigInteger;
  39  use LogicException;
  40  
  41  /**
  42   * Class ASNObject is the base class for all concrete ASN.1 objects.
  43   */
  44  abstract class ASNObject implements Parsable
  45  {
  46      private $contentLength;
  47      private $nrOfLengthOctets;
  48  
  49      /**
  50       * Must return the number of octets of the content part.
  51       *
  52       * @return int
  53       */
  54      abstract protected function calculateContentLength();
  55  
  56      /**
  57       * Encode the object using DER encoding.
  58       *
  59       * @see http://en.wikipedia.org/wiki/X.690#DER_encoding
  60       *
  61       * @return string the binary representation of an objects value
  62       */
  63      abstract protected function getEncodedValue();
  64  
  65      /**
  66       * Return the content of this object in a non encoded form.
  67       * This can be used to print the value in human readable form.
  68       *
  69       * @return mixed
  70       */
  71      abstract public function getContent();
  72  
  73      /**
  74       * Return the object type octet.
  75       * This should use the class constants of Identifier.
  76       *
  77       * @see Identifier
  78       *
  79       * @return int
  80       */
  81      abstract public function getType();
  82  
  83      /**
  84       * Returns all identifier octets. If an inheriting class models a tag with
  85       * the long form identifier format, it MUST reimplement this method to
  86       * return all octets of the identifier.
  87       *
  88       * @throws LogicException If the identifier format is long form
  89       *
  90       * @return string Identifier as a set of octets
  91       */
  92      public function getIdentifier()
  93      {
  94          $firstOctet = $this->getType();
  95  
  96          if (Identifier::isLongForm($firstOctet)) {
  97              throw new LogicException(sprintf('Identifier of %s uses the long form and must therefor override "ASNObject::getIdentifier()".', get_class($this)));
  98          }
  99  
 100          return chr($firstOctet);
 101      }
 102  
 103      /**
 104       * Encode this object using DER encoding.
 105       *
 106       * @return string the full binary representation of the complete object
 107       */
 108      public function getBinary()
 109      {
 110          $result  = $this->getIdentifier();
 111          $result .= $this->createLengthPart();
 112          $result .= $this->getEncodedValue();
 113  
 114          return $result;
 115      }
 116  
 117      private function createLengthPart()
 118      {
 119          $contentLength = $this->getContentLength();
 120          $nrOfLengthOctets = $this->getNumberOfLengthOctets($contentLength);
 121  
 122          if ($nrOfLengthOctets == 1) {
 123              return chr($contentLength);
 124          } else {
 125              // the first length octet determines the number subsequent length octets
 126              $lengthOctets = chr(0x80 | ($nrOfLengthOctets - 1));
 127              for ($shiftLength = 8 * ($nrOfLengthOctets - 2); $shiftLength >= 0; $shiftLength -= 8) {
 128                  $lengthOctets .= chr($contentLength >> $shiftLength);
 129              }
 130  
 131              return $lengthOctets;
 132          }
 133      }
 134  
 135      protected function getNumberOfLengthOctets($contentLength = null)
 136      {
 137          if (!isset($this->nrOfLengthOctets)) {
 138              if ($contentLength == null) {
 139                  $contentLength = $this->getContentLength();
 140              }
 141  
 142              $this->nrOfLengthOctets = 1;
 143              if ($contentLength > 127) {
 144                  do { // long form
 145                      $this->nrOfLengthOctets++;
 146                      $contentLength = $contentLength >> 8;
 147                  } while ($contentLength > 0);
 148              }
 149          }
 150  
 151          return $this->nrOfLengthOctets;
 152      }
 153  
 154      protected function getContentLength()
 155      {
 156          if (!isset($this->contentLength)) {
 157              $this->contentLength = $this->calculateContentLength();
 158          }
 159  
 160          return $this->contentLength;
 161      }
 162  
 163      protected function setContentLength($newContentLength)
 164      {
 165          $this->contentLength = $newContentLength;
 166          $this->getNumberOfLengthOctets($newContentLength);
 167      }
 168  
 169      /**
 170       * Returns the length of the whole object (including the identifier and length octets).
 171       */
 172      public function getObjectLength()
 173      {
 174          $nrOfIdentifierOctets = strlen($this->getIdentifier());
 175          $contentLength = $this->getContentLength();
 176          $nrOfLengthOctets = $this->getNumberOfLengthOctets($contentLength);
 177  
 178          return $nrOfIdentifierOctets + $nrOfLengthOctets + $contentLength;
 179      }
 180  
 181      public function __toString()
 182      {
 183          return $this->getContent();
 184      }
 185  
 186      /**
 187       * Returns the name of the ASN.1 Type of this object.
 188       *
 189       * @see Identifier::getName()
 190       */
 191      public function getTypeName()
 192      {
 193          return Identifier::getName($this->getType());
 194      }
 195  
 196      /**
 197       * @param string $binaryData
 198       * @param int $offsetIndex
 199       *
 200       * @throws ParserException
 201       *
 202       * @return \FG\ASN1\ASNObject
 203       */
 204      public static function fromBinary(&$binaryData, &$offsetIndex = 0)
 205      {
 206          if (strlen($binaryData) <= $offsetIndex) {
 207              throw new ParserException('Can not parse binary from data: Offset index larger than input size', $offsetIndex);
 208          }
 209  
 210          $identifierOctet = ord($binaryData[$offsetIndex]);
 211          if (Identifier::isContextSpecificClass($identifierOctet) && Identifier::isConstructed($identifierOctet)) {
 212              return ExplicitlyTaggedObject::fromBinary($binaryData, $offsetIndex);
 213          }
 214  
 215          switch ($identifierOctet) {
 216              case Identifier::BITSTRING:
 217                  return BitString::fromBinary($binaryData, $offsetIndex);
 218              case Identifier::BOOLEAN:
 219                  return Boolean::fromBinary($binaryData, $offsetIndex);
 220              case Identifier::ENUMERATED:
 221                  return Enumerated::fromBinary($binaryData, $offsetIndex);
 222              case Identifier::INTEGER:
 223                  return Integer::fromBinary($binaryData, $offsetIndex);
 224              case Identifier::NULL:
 225                  return NullObject::fromBinary($binaryData, $offsetIndex);
 226              case Identifier::OBJECT_IDENTIFIER:
 227                  return ObjectIdentifier::fromBinary($binaryData, $offsetIndex);
 228              case Identifier::RELATIVE_OID:
 229                  return RelativeObjectIdentifier::fromBinary($binaryData, $offsetIndex);
 230              case Identifier::OCTETSTRING:
 231                  return OctetString::fromBinary($binaryData, $offsetIndex);
 232              case Identifier::SEQUENCE:
 233                  return Sequence::fromBinary($binaryData, $offsetIndex);
 234              case Identifier::SET:
 235                  return Set::fromBinary($binaryData, $offsetIndex);
 236              case Identifier::UTC_TIME:
 237                  return UTCTime::fromBinary($binaryData, $offsetIndex);
 238              case Identifier::GENERALIZED_TIME:
 239                  return GeneralizedTime::fromBinary($binaryData, $offsetIndex);
 240              case Identifier::IA5_STRING:
 241                  return IA5String::fromBinary($binaryData, $offsetIndex);
 242              case Identifier::PRINTABLE_STRING:
 243                  return PrintableString::fromBinary($binaryData, $offsetIndex);
 244              case Identifier::NUMERIC_STRING:
 245                  return NumericString::fromBinary($binaryData, $offsetIndex);
 246              case Identifier::UTF8_STRING:
 247                  return UTF8String::fromBinary($binaryData, $offsetIndex);
 248              case Identifier::UNIVERSAL_STRING:
 249                  return UniversalString::fromBinary($binaryData, $offsetIndex);
 250              case Identifier::CHARACTER_STRING:
 251                  return CharacterString::fromBinary($binaryData, $offsetIndex);
 252              case Identifier::GENERAL_STRING:
 253                  return GeneralString::fromBinary($binaryData, $offsetIndex);
 254              case Identifier::VISIBLE_STRING:
 255                  return VisibleString::fromBinary($binaryData, $offsetIndex);
 256              case Identifier::GRAPHIC_STRING:
 257                  return GraphicString::fromBinary($binaryData, $offsetIndex);
 258              case Identifier::BMP_STRING:
 259                  return BMPString::fromBinary($binaryData, $offsetIndex);
 260              case Identifier::T61_STRING:
 261                  return T61String::fromBinary($binaryData, $offsetIndex);
 262              case Identifier::OBJECT_DESCRIPTOR:
 263                  return ObjectDescriptor::fromBinary($binaryData, $offsetIndex);
 264              default:
 265                  // At this point the identifier may be >1 byte.
 266                  if (Identifier::isConstructed($identifierOctet)) {
 267                      return new UnknownConstructedObject($binaryData, $offsetIndex);
 268                  } else {
 269                      $identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex);
 270                      $lengthOfUnknownObject = self::parseContentLength($binaryData, $offsetIndex);
 271                      $offsetIndex += $lengthOfUnknownObject;
 272  
 273                      return new UnknownObject($identifier, $lengthOfUnknownObject);
 274                  }
 275          }
 276      }
 277  
 278      protected static function parseIdentifier($identifierOctet, $expectedIdentifier, $offsetForExceptionHandling)
 279      {
 280          if (is_string($identifierOctet) || is_numeric($identifierOctet) == false) {
 281              $identifierOctet = ord($identifierOctet);
 282          }
 283  
 284          if ($identifierOctet != $expectedIdentifier) {
 285              $message = 'Can not create an '.Identifier::getName($expectedIdentifier).' from an '.Identifier::getName($identifierOctet);
 286              throw new ParserException($message, $offsetForExceptionHandling);
 287          }
 288      }
 289  
 290      protected static function parseBinaryIdentifier($binaryData, &$offsetIndex)
 291      {
 292          if (strlen($binaryData) <= $offsetIndex) {
 293              throw new ParserException('Can not parse identifier from data: Offset index larger than input size', $offsetIndex);
 294          }
 295  
 296          $identifier = $binaryData[$offsetIndex++];
 297  
 298          if (Identifier::isLongForm(ord($identifier)) == false) {
 299              return $identifier;
 300          }
 301  
 302          while (true) {
 303              if (strlen($binaryData) <= $offsetIndex) {
 304                  throw new ParserException('Can not parse identifier (long form) from data: Offset index larger than input size', $offsetIndex);
 305              }
 306              $nextOctet = $binaryData[$offsetIndex++];
 307              $identifier .= $nextOctet;
 308  
 309              if ((ord($nextOctet) & 0x80) === 0) {
 310                  // the most significant bit is 0 to we have reached the end of the identifier
 311                  break;
 312              }
 313          }
 314  
 315          return $identifier;
 316      }
 317  
 318      protected static function parseContentLength(&$binaryData, &$offsetIndex, $minimumLength = 0)
 319      {
 320          if (strlen($binaryData) <= $offsetIndex) {
 321              throw new ParserException('Can not parse content length from data: Offset index larger than input size', $offsetIndex);
 322          }
 323  
 324          $contentLength = ord($binaryData[$offsetIndex++]);
 325          if (($contentLength & 0x80) != 0) {
 326              // bit 8 is set -> this is the long form
 327              $nrOfLengthOctets = $contentLength & 0x7F;
 328              $contentLength = BigInteger::create(0x00);
 329              for ($i = 0; $i < $nrOfLengthOctets; $i++) {
 330                  if (strlen($binaryData) <= $offsetIndex) {
 331                      throw new ParserException('Can not parse content length (long form) from data: Offset index larger than input size', $offsetIndex);
 332                  }
 333                  $contentLength = $contentLength->shiftLeft(8)->add(ord($binaryData[$offsetIndex++]));
 334              }
 335  
 336              if ($contentLength->compare(PHP_INT_MAX) > 0) {
 337                  throw new ParserException("Can not parse content length from data: length > maximum integer", $offsetIndex);
 338              }
 339  
 340              $contentLength = $contentLength->toInteger();
 341          }
 342  
 343          if ($contentLength < $minimumLength) {
 344              throw new ParserException('A '.get_called_class()." should have a content length of at least {$minimumLength}. Extracted length was {$contentLength}", $offsetIndex);
 345          }
 346  
 347          $lenDataRemaining = strlen($binaryData) - $offsetIndex;
 348  
 349          if ($lenDataRemaining < $contentLength) {
 350              throw new ParserException("Content length {$contentLength} exceeds remaining data length {$lenDataRemaining}", $offsetIndex);
 351          }
 352  
 353          return $contentLength;
 354      }
 355  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer