[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |