diff options
Diffstat (limited to 'vendor/fgrosse/phpasn1/lib/ASN1/Identifier.php')
-rw-r--r-- | vendor/fgrosse/phpasn1/lib/ASN1/Identifier.php | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Identifier.php b/vendor/fgrosse/phpasn1/lib/ASN1/Identifier.php new file mode 100644 index 0000000..b21caa3 --- /dev/null +++ b/vendor/fgrosse/phpasn1/lib/ASN1/Identifier.php @@ -0,0 +1,339 @@ +<?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; + +use Exception; + +/** + * The Identifier encodes the ASN.1 tag (class and number) of the type of a data value. + * + * Every identifier whose number is in the range 0 to 30 has the following structure: + * + * Bits: 8 7 6 5 4 3 2 1 + * | Class | P/C | Tag number | + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * Bits 8 and 7 define the class of this type ( Universal, Application, Context-specific or Private). + * Bit 6 encoded whether this type is primitive or constructed + * The remaining bits 5 - 1 encode the tag number + */ +class Identifier +{ + const CLASS_UNIVERSAL = 0x00; + const CLASS_APPLICATION = 0x01; + const CLASS_CONTEXT_SPECIFIC = 0x02; + const CLASS_PRIVATE = 0x03; + + const EOC = 0x00; // unsupported for now + const BOOLEAN = 0x01; + const INTEGER = 0x02; + const BITSTRING = 0x03; + const OCTETSTRING = 0x04; + const NULL = 0x05; + const OBJECT_IDENTIFIER = 0x06; + const OBJECT_DESCRIPTOR = 0x07; + const EXTERNAL = 0x08; // unsupported for now + const REAL = 0x09; // unsupported for now + const ENUMERATED = 0x0A; + const EMBEDDED_PDV = 0x0B; // unsupported for now + const UTF8_STRING = 0x0C; + const RELATIVE_OID = 0x0D; + // value 0x0E and 0x0F are reserved for future use + + const SEQUENCE = 0x30; + const SET = 0x31; + const NUMERIC_STRING = 0x12; + const PRINTABLE_STRING = 0x13; + const T61_STRING = 0x14; // sometimes referred to as TeletextString + const VIDEOTEXT_STRING = 0x15; + const IA5_STRING = 0x16; + const UTC_TIME = 0x17; + const GENERALIZED_TIME = 0x18; + const GRAPHIC_STRING = 0x19; + const VISIBLE_STRING = 0x1A; + const GENERAL_STRING = 0x1B; + const UNIVERSAL_STRING = 0x1C; + const CHARACTER_STRING = 0x1D; // Unrestricted character type + const BMP_STRING = 0x1E; + + const LONG_FORM = 0x1F; + const IS_CONSTRUCTED = 0x20; + + /** + * Creates an identifier. Short form identifiers are returned as integers + * for BC, long form identifiers will be returned as a string of octets. + * + * @param int $class + * @param bool $isConstructed + * @param int $tagNumber + * + * @throws Exception if the given arguments are invalid + * + * @return int|string + */ + public static function create($class, $isConstructed, $tagNumber) + { + if (!is_numeric($class) || $class < self::CLASS_UNIVERSAL || $class > self::CLASS_PRIVATE) { + throw new Exception(sprintf('Invalid class %d given', $class)); + } + + if (!is_bool($isConstructed)) { + throw new Exception("\$isConstructed must be a boolean value ($isConstructed given)"); + } + + $tagNumber = self::makeNumeric($tagNumber); + if ($tagNumber < 0) { + throw new Exception(sprintf('Invalid $tagNumber %d given. You can only use positive integers.', $tagNumber)); + } + + if ($tagNumber < self::LONG_FORM) { + return ($class << 6) | ($isConstructed << 5) | $tagNumber; + } + + $firstOctet = ($class << 6) | ($isConstructed << 5) | self::LONG_FORM; + + // Tag numbers formatted in long form are base-128 encoded. See X.609#8.1.2.4 + return chr($firstOctet).Base128::encode($tagNumber); + } + + public static function isConstructed($identifierOctet) + { + return ($identifierOctet & self::IS_CONSTRUCTED) === self::IS_CONSTRUCTED; + } + + public static function isLongForm($identifierOctet) + { + return ($identifierOctet & self::LONG_FORM) === self::LONG_FORM; + } + + /** + * Return the name of the mapped ASN.1 type with a preceding "ASN.1 ". + * + * Example: ASN.1 Octet String + * + * @see Identifier::getShortName() + * + * @param int|string $identifier + * + * @return string + */ + public static function getName($identifier) + { + $identifierOctet = self::makeNumeric($identifier); + + $typeName = static::getShortName($identifier); + + if (($identifierOctet & self::LONG_FORM) < self::LONG_FORM) { + $typeName = "ASN.1 {$typeName}"; + } + + return $typeName; + } + + /** + * Return the short version of the type name. + * + * If the given identifier octet can be mapped to a known universal type this will + * return its name. Else Identifier::getClassDescription() is used to retrieve + * information about the identifier. + * + * @see Identifier::getName() + * @see Identifier::getClassDescription() + * + * @param int|string $identifier + * + * @return string + */ + public static function getShortName($identifier) + { + $identifierOctet = self::makeNumeric($identifier); + + switch ($identifierOctet) { + case self::EOC: + return 'End-of-contents octet'; + case self::BOOLEAN: + return 'Boolean'; + case self::INTEGER: + return 'Integer'; + case self::BITSTRING: + return 'Bit String'; + case self::OCTETSTRING: + return 'Octet String'; + case self::NULL: + return 'NULL'; + case self::OBJECT_IDENTIFIER: + return 'Object Identifier'; + case self::OBJECT_DESCRIPTOR: + return 'Object Descriptor'; + case self::EXTERNAL: + return 'External Type'; + case self::REAL: + return 'Real'; + case self::ENUMERATED: + return 'Enumerated'; + case self::EMBEDDED_PDV: + return 'Embedded PDV'; + case self::UTF8_STRING: + return 'UTF8 String'; + case self::RELATIVE_OID: + return 'Relative OID'; + case self::SEQUENCE: + return 'Sequence'; + case self::SET: + return 'Set'; + case self::NUMERIC_STRING: + return 'Numeric String'; + case self::PRINTABLE_STRING: + return 'Printable String'; + case self::T61_STRING: + return 'T61 String'; + case self::VIDEOTEXT_STRING: + return 'Videotext String'; + case self::IA5_STRING: + return 'IA5 String'; + case self::UTC_TIME: + return 'UTC Time'; + case self::GENERALIZED_TIME: + return 'Generalized Time'; + case self::GRAPHIC_STRING: + return 'Graphic String'; + case self::VISIBLE_STRING: + return 'Visible String'; + case self::GENERAL_STRING: + return 'General String'; + case self::UNIVERSAL_STRING: + return 'Universal String'; + case self::CHARACTER_STRING: + return 'Character String'; + case self::BMP_STRING: + return 'BMP String'; + + case 0x0E: + return 'RESERVED (0x0E)'; + case 0x0F: + return 'RESERVED (0x0F)'; + + case self::LONG_FORM: + default: + $classDescription = self::getClassDescription($identifier); + + if (is_int($identifier)) { + $identifier = chr($identifier); + } + + return "$classDescription (0x".strtoupper(bin2hex($identifier)).')'; + } + } + + /** + * Returns a textual description of the information encoded in a given identifier octet. + * + * The first three (most significant) bytes are evaluated to determine if this is a + * constructed or primitive type and if it is either universal, application, context-specific or + * private. + * + * Example: + * Constructed context-specific + * Primitive universal + * + * @param int|string $identifier + * + * @return string + */ + public static function getClassDescription($identifier) + { + $identifierOctet = self::makeNumeric($identifier); + + if (self::isConstructed($identifierOctet)) { + $classDescription = 'Constructed '; + } else { + $classDescription = 'Primitive '; + } + $classBits = $identifierOctet >> 6; + switch ($classBits) { + case self::CLASS_UNIVERSAL: + $classDescription .= 'universal'; + break; + case self::CLASS_APPLICATION: + $classDescription .= 'application'; + break; + case self::CLASS_CONTEXT_SPECIFIC: + $tagNumber = self::getTagNumber($identifier); + $classDescription = "[$tagNumber] Context-specific"; + break; + case self::CLASS_PRIVATE: + $classDescription .= 'private'; + break; + + default: + return "INVALID IDENTIFIER OCTET: {$identifierOctet}"; + } + + return $classDescription; + } + + /** + * @param int|string $identifier + * + * @return int + */ + public static function getTagNumber($identifier) + { + $firstOctet = self::makeNumeric($identifier); + $tagNumber = $firstOctet & self::LONG_FORM; + + if ($tagNumber < self::LONG_FORM) { + return $tagNumber; + } + + if (is_numeric($identifier)) { + $identifier = chr($identifier); + } + return Base128::decode(substr($identifier, 1)); + } + + public static function isUniversalClass($identifier) + { + $identifier = self::makeNumeric($identifier); + + return $identifier >> 6 == self::CLASS_UNIVERSAL; + } + + public static function isApplicationClass($identifier) + { + $identifier = self::makeNumeric($identifier); + + return $identifier >> 6 == self::CLASS_APPLICATION; + } + + public static function isContextSpecificClass($identifier) + { + $identifier = self::makeNumeric($identifier); + + return $identifier >> 6 == self::CLASS_CONTEXT_SPECIFIC; + } + + public static function isPrivateClass($identifier) + { + $identifier = self::makeNumeric($identifier); + + return $identifier >> 6 == self::CLASS_PRIVATE; + } + + private static function makeNumeric($identifierOctet) + { + if (!is_numeric($identifierOctet)) { + return ord($identifierOctet); + } else { + return $identifierOctet; + } + } +} |