summaryrefslogtreecommitdiffstats
path: root/vendor/fgrosse/phpasn1/lib/ASN1
diff options
context:
space:
mode:
authorAnton Luka Šijanec <anton@sijanec.eu>2022-01-11 12:35:47 +0100
committerAnton Luka Šijanec <anton@sijanec.eu>2022-01-11 12:35:47 +0100
commit19985dbb8c0aa66dc4bf7905abc1148de909097d (patch)
tree2cd5a5d20d7e80fc2a51adf60d838d8a2c40999e /vendor/fgrosse/phpasn1/lib/ASN1
download1ka-19985dbb8c0aa66dc4bf7905abc1148de909097d.tar
1ka-19985dbb8c0aa66dc4bf7905abc1148de909097d.tar.gz
1ka-19985dbb8c0aa66dc4bf7905abc1148de909097d.tar.bz2
1ka-19985dbb8c0aa66dc4bf7905abc1148de909097d.tar.lz
1ka-19985dbb8c0aa66dc4bf7905abc1148de909097d.tar.xz
1ka-19985dbb8c0aa66dc4bf7905abc1148de909097d.tar.zst
1ka-19985dbb8c0aa66dc4bf7905abc1148de909097d.zip
Diffstat (limited to 'vendor/fgrosse/phpasn1/lib/ASN1')
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/ASNObject.php355
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/AbstractString.php136
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/AbstractTime.php78
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Base128.php63
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Composite/AttributeTypeAndValue.php35
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Composite/RDNString.php37
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Composite/RelativeDistinguishedName.php50
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Construct.php191
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Exception/NotImplementedException.php15
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Exception/ParserException.php29
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php131
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Identifier.php339
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/OID.php199
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Parsable.php32
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/TemplateParser.php70
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/BMPString.php41
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/BitString.php88
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/Boolean.php75
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/CharacterString.php28
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/Enumerated.php21
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralString.php34
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralizedTime.php134
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/GraphicString.php34
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/IA5String.php35
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/Integer.php130
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/NullObject.php54
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/NumericString.php38
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectDescriptor.php26
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectIdentifier.php138
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/OctetString.php91
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/PrintableString.php53
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/RelativeObjectIdentifier.php57
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/Sequence.php23
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/Set.php21
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/T61String.php36
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTCTime.php77
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTF8String.php34
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/UniversalString.php36
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/Universal/VisibleString.php34
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/UnknownConstructedObject.php59
-rw-r--r--vendor/fgrosse/phpasn1/lib/ASN1/UnknownObject.php59
41 files changed, 3216 insertions, 0 deletions
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/ASNObject.php b/vendor/fgrosse/phpasn1/lib/ASN1/ASNObject.php
new file mode 100644
index 0000000..3b7f162
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/ASNObject.php
@@ -0,0 +1,355 @@
+<?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 FG\ASN1\Exception\ParserException;
+use FG\ASN1\Universal\BitString;
+use FG\ASN1\Universal\Boolean;
+use FG\ASN1\Universal\Enumerated;
+use FG\ASN1\Universal\GeneralizedTime;
+use FG\ASN1\Universal\Integer;
+use FG\ASN1\Universal\NullObject;
+use FG\ASN1\Universal\ObjectIdentifier;
+use FG\ASN1\Universal\RelativeObjectIdentifier;
+use FG\ASN1\Universal\OctetString;
+use FG\ASN1\Universal\Sequence;
+use FG\ASN1\Universal\Set;
+use FG\ASN1\Universal\UTCTime;
+use FG\ASN1\Universal\IA5String;
+use FG\ASN1\Universal\PrintableString;
+use FG\ASN1\Universal\NumericString;
+use FG\ASN1\Universal\UTF8String;
+use FG\ASN1\Universal\UniversalString;
+use FG\ASN1\Universal\CharacterString;
+use FG\ASN1\Universal\GeneralString;
+use FG\ASN1\Universal\VisibleString;
+use FG\ASN1\Universal\GraphicString;
+use FG\ASN1\Universal\BMPString;
+use FG\ASN1\Universal\T61String;
+use FG\ASN1\Universal\ObjectDescriptor;
+use FG\Utility\BigInteger;
+use LogicException;
+
+/**
+ * Class ASNObject is the base class for all concrete ASN.1 objects.
+ */
+abstract class ASNObject implements Parsable
+{
+ private $contentLength;
+ private $nrOfLengthOctets;
+
+ /**
+ * Must return the number of octets of the content part.
+ *
+ * @return int
+ */
+ abstract protected function calculateContentLength();
+
+ /**
+ * Encode the object using DER encoding.
+ *
+ * @see http://en.wikipedia.org/wiki/X.690#DER_encoding
+ *
+ * @return string the binary representation of an objects value
+ */
+ abstract protected function getEncodedValue();
+
+ /**
+ * Return the content of this object in a non encoded form.
+ * This can be used to print the value in human readable form.
+ *
+ * @return mixed
+ */
+ abstract public function getContent();
+
+ /**
+ * Return the object type octet.
+ * This should use the class constants of Identifier.
+ *
+ * @see Identifier
+ *
+ * @return int
+ */
+ abstract public function getType();
+
+ /**
+ * Returns all identifier octets. If an inheriting class models a tag with
+ * the long form identifier format, it MUST reimplement this method to
+ * return all octets of the identifier.
+ *
+ * @throws LogicException If the identifier format is long form
+ *
+ * @return string Identifier as a set of octets
+ */
+ public function getIdentifier()
+ {
+ $firstOctet = $this->getType();
+
+ if (Identifier::isLongForm($firstOctet)) {
+ throw new LogicException(sprintf('Identifier of %s uses the long form and must therefor override "ASNObject::getIdentifier()".', get_class($this)));
+ }
+
+ return chr($firstOctet);
+ }
+
+ /**
+ * Encode this object using DER encoding.
+ *
+ * @return string the full binary representation of the complete object
+ */
+ public function getBinary()
+ {
+ $result = $this->getIdentifier();
+ $result .= $this->createLengthPart();
+ $result .= $this->getEncodedValue();
+
+ return $result;
+ }
+
+ private function createLengthPart()
+ {
+ $contentLength = $this->getContentLength();
+ $nrOfLengthOctets = $this->getNumberOfLengthOctets($contentLength);
+
+ if ($nrOfLengthOctets == 1) {
+ return chr($contentLength);
+ } else {
+ // the first length octet determines the number subsequent length octets
+ $lengthOctets = chr(0x80 | ($nrOfLengthOctets - 1));
+ for ($shiftLength = 8 * ($nrOfLengthOctets - 2); $shiftLength >= 0; $shiftLength -= 8) {
+ $lengthOctets .= chr($contentLength >> $shiftLength);
+ }
+
+ return $lengthOctets;
+ }
+ }
+
+ protected function getNumberOfLengthOctets($contentLength = null)
+ {
+ if (!isset($this->nrOfLengthOctets)) {
+ if ($contentLength == null) {
+ $contentLength = $this->getContentLength();
+ }
+
+ $this->nrOfLengthOctets = 1;
+ if ($contentLength > 127) {
+ do { // long form
+ $this->nrOfLengthOctets++;
+ $contentLength = $contentLength >> 8;
+ } while ($contentLength > 0);
+ }
+ }
+
+ return $this->nrOfLengthOctets;
+ }
+
+ protected function getContentLength()
+ {
+ if (!isset($this->contentLength)) {
+ $this->contentLength = $this->calculateContentLength();
+ }
+
+ return $this->contentLength;
+ }
+
+ protected function setContentLength($newContentLength)
+ {
+ $this->contentLength = $newContentLength;
+ $this->getNumberOfLengthOctets($newContentLength);
+ }
+
+ /**
+ * Returns the length of the whole object (including the identifier and length octets).
+ */
+ public function getObjectLength()
+ {
+ $nrOfIdentifierOctets = strlen($this->getIdentifier());
+ $contentLength = $this->getContentLength();
+ $nrOfLengthOctets = $this->getNumberOfLengthOctets($contentLength);
+
+ return $nrOfIdentifierOctets + $nrOfLengthOctets + $contentLength;
+ }
+
+ public function __toString()
+ {
+ return $this->getContent();
+ }
+
+ /**
+ * Returns the name of the ASN.1 Type of this object.
+ *
+ * @see Identifier::getName()
+ */
+ public function getTypeName()
+ {
+ return Identifier::getName($this->getType());
+ }
+
+ /**
+ * @param string $binaryData
+ * @param int $offsetIndex
+ *
+ * @throws ParserException
+ *
+ * @return \FG\ASN1\ASNObject
+ */
+ public static function fromBinary(&$binaryData, &$offsetIndex = 0)
+ {
+ if (strlen($binaryData) <= $offsetIndex) {
+ throw new ParserException('Can not parse binary from data: Offset index larger than input size', $offsetIndex);
+ }
+
+ $identifierOctet = ord($binaryData[$offsetIndex]);
+ if (Identifier::isContextSpecificClass($identifierOctet) && Identifier::isConstructed($identifierOctet)) {
+ return ExplicitlyTaggedObject::fromBinary($binaryData, $offsetIndex);
+ }
+
+ switch ($identifierOctet) {
+ case Identifier::BITSTRING:
+ return BitString::fromBinary($binaryData, $offsetIndex);
+ case Identifier::BOOLEAN:
+ return Boolean::fromBinary($binaryData, $offsetIndex);
+ case Identifier::ENUMERATED:
+ return Enumerated::fromBinary($binaryData, $offsetIndex);
+ case Identifier::INTEGER:
+ return Integer::fromBinary($binaryData, $offsetIndex);
+ case Identifier::NULL:
+ return NullObject::fromBinary($binaryData, $offsetIndex);
+ case Identifier::OBJECT_IDENTIFIER:
+ return ObjectIdentifier::fromBinary($binaryData, $offsetIndex);
+ case Identifier::RELATIVE_OID:
+ return RelativeObjectIdentifier::fromBinary($binaryData, $offsetIndex);
+ case Identifier::OCTETSTRING:
+ return OctetString::fromBinary($binaryData, $offsetIndex);
+ case Identifier::SEQUENCE:
+ return Sequence::fromBinary($binaryData, $offsetIndex);
+ case Identifier::SET:
+ return Set::fromBinary($binaryData, $offsetIndex);
+ case Identifier::UTC_TIME:
+ return UTCTime::fromBinary($binaryData, $offsetIndex);
+ case Identifier::GENERALIZED_TIME:
+ return GeneralizedTime::fromBinary($binaryData, $offsetIndex);
+ case Identifier::IA5_STRING:
+ return IA5String::fromBinary($binaryData, $offsetIndex);
+ case Identifier::PRINTABLE_STRING:
+ return PrintableString::fromBinary($binaryData, $offsetIndex);
+ case Identifier::NUMERIC_STRING:
+ return NumericString::fromBinary($binaryData, $offsetIndex);
+ case Identifier::UTF8_STRING:
+ return UTF8String::fromBinary($binaryData, $offsetIndex);
+ case Identifier::UNIVERSAL_STRING:
+ return UniversalString::fromBinary($binaryData, $offsetIndex);
+ case Identifier::CHARACTER_STRING:
+ return CharacterString::fromBinary($binaryData, $offsetIndex);
+ case Identifier::GENERAL_STRING:
+ return GeneralString::fromBinary($binaryData, $offsetIndex);
+ case Identifier::VISIBLE_STRING:
+ return VisibleString::fromBinary($binaryData, $offsetIndex);
+ case Identifier::GRAPHIC_STRING:
+ return GraphicString::fromBinary($binaryData, $offsetIndex);
+ case Identifier::BMP_STRING:
+ return BMPString::fromBinary($binaryData, $offsetIndex);
+ case Identifier::T61_STRING:
+ return T61String::fromBinary($binaryData, $offsetIndex);
+ case Identifier::OBJECT_DESCRIPTOR:
+ return ObjectDescriptor::fromBinary($binaryData, $offsetIndex);
+ default:
+ // At this point the identifier may be >1 byte.
+ if (Identifier::isConstructed($identifierOctet)) {
+ return new UnknownConstructedObject($binaryData, $offsetIndex);
+ } else {
+ $identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex);
+ $lengthOfUnknownObject = self::parseContentLength($binaryData, $offsetIndex);
+ $offsetIndex += $lengthOfUnknownObject;
+
+ return new UnknownObject($identifier, $lengthOfUnknownObject);
+ }
+ }
+ }
+
+ protected static function parseIdentifier($identifierOctet, $expectedIdentifier, $offsetForExceptionHandling)
+ {
+ if (is_string($identifierOctet) || is_numeric($identifierOctet) == false) {
+ $identifierOctet = ord($identifierOctet);
+ }
+
+ if ($identifierOctet != $expectedIdentifier) {
+ $message = 'Can not create an '.Identifier::getName($expectedIdentifier).' from an '.Identifier::getName($identifierOctet);
+ throw new ParserException($message, $offsetForExceptionHandling);
+ }
+ }
+
+ protected static function parseBinaryIdentifier($binaryData, &$offsetIndex)
+ {
+ if (strlen($binaryData) <= $offsetIndex) {
+ throw new ParserException('Can not parse identifier from data: Offset index larger than input size', $offsetIndex);
+ }
+
+ $identifier = $binaryData[$offsetIndex++];
+
+ if (Identifier::isLongForm(ord($identifier)) == false) {
+ return $identifier;
+ }
+
+ while (true) {
+ if (strlen($binaryData) <= $offsetIndex) {
+ throw new ParserException('Can not parse identifier (long form) from data: Offset index larger than input size', $offsetIndex);
+ }
+ $nextOctet = $binaryData[$offsetIndex++];
+ $identifier .= $nextOctet;
+
+ if ((ord($nextOctet) & 0x80) === 0) {
+ // the most significant bit is 0 to we have reached the end of the identifier
+ break;
+ }
+ }
+
+ return $identifier;
+ }
+
+ protected static function parseContentLength(&$binaryData, &$offsetIndex, $minimumLength = 0)
+ {
+ if (strlen($binaryData) <= $offsetIndex) {
+ throw new ParserException('Can not parse content length from data: Offset index larger than input size', $offsetIndex);
+ }
+
+ $contentLength = ord($binaryData[$offsetIndex++]);
+ if (($contentLength & 0x80) != 0) {
+ // bit 8 is set -> this is the long form
+ $nrOfLengthOctets = $contentLength & 0x7F;
+ $contentLength = BigInteger::create(0x00);
+ for ($i = 0; $i < $nrOfLengthOctets; $i++) {
+ if (strlen($binaryData) <= $offsetIndex) {
+ throw new ParserException('Can not parse content length (long form) from data: Offset index larger than input size', $offsetIndex);
+ }
+ $contentLength = $contentLength->shiftLeft(8)->add(ord($binaryData[$offsetIndex++]));
+ }
+
+ if ($contentLength->compare(PHP_INT_MAX) > 0) {
+ throw new ParserException("Can not parse content length from data: length > maximum integer", $offsetIndex);
+ }
+
+ $contentLength = $contentLength->toInteger();
+ }
+
+ if ($contentLength < $minimumLength) {
+ throw new ParserException('A '.get_called_class()." should have a content length of at least {$minimumLength}. Extracted length was {$contentLength}", $offsetIndex);
+ }
+
+ $lenDataRemaining = strlen($binaryData) - $offsetIndex;
+
+ if ($lenDataRemaining < $contentLength) {
+ throw new ParserException("Content length {$contentLength} exceeds remaining data length {$lenDataRemaining}", $offsetIndex);
+ }
+
+ return $contentLength;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/AbstractString.php b/vendor/fgrosse/phpasn1/lib/ASN1/AbstractString.php
new file mode 100644
index 0000000..7e0d7dd
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/AbstractString.php
@@ -0,0 +1,136 @@
+<?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;
+
+abstract class AbstractString extends ASNObject implements Parsable
+{
+ /** @var string */
+ protected $value;
+ private $checkStringForIllegalChars = true;
+ private $allowedCharacters = [];
+
+ /**
+ * The abstract base class for ASN.1 classes which represent some string of character.
+ *
+ * @param string $string
+ */
+ public function __construct($string)
+ {
+ $this->value = $string;
+ }
+
+ public function getContent()
+ {
+ return $this->value;
+ }
+
+ protected function allowCharacter($character)
+ {
+ $this->allowedCharacters[] = $character;
+ }
+
+ protected function allowCharacters(...$characters)
+ {
+ foreach ($characters as $character) {
+ $this->allowedCharacters[] = $character;
+ }
+ }
+
+ protected function allowNumbers()
+ {
+ foreach (range('0', '9') as $char) {
+ $this->allowedCharacters[] = (string) $char;
+ }
+ }
+
+ protected function allowAllLetters()
+ {
+ $this->allowSmallLetters();
+ $this->allowCapitalLetters();
+ }
+
+ protected function allowSmallLetters()
+ {
+ foreach (range('a', 'z') as $char) {
+ $this->allowedCharacters[] = $char;
+ }
+ }
+
+ protected function allowCapitalLetters()
+ {
+ foreach (range('A', 'Z') as $char) {
+ $this->allowedCharacters[] = $char;
+ }
+ }
+
+ protected function allowSpaces()
+ {
+ $this->allowedCharacters[] = ' ';
+ }
+
+ protected function allowAll()
+ {
+ $this->checkStringForIllegalChars = false;
+ }
+
+ protected function calculateContentLength()
+ {
+ return strlen($this->value);
+ }
+
+ protected function getEncodedValue()
+ {
+ if ($this->checkStringForIllegalChars) {
+ $this->checkString();
+ }
+
+ return $this->value;
+ }
+
+ protected function checkString()
+ {
+ $stringLength = $this->getContentLength();
+ for ($i = 0; $i < $stringLength; $i++) {
+ if (in_array($this->value[$i], $this->allowedCharacters) == false) {
+ $typeName = Identifier::getName($this->getType());
+ throw new Exception("Could not create a {$typeName} from the character sequence '{$this->value}'.");
+ }
+ }
+ }
+
+ public static function fromBinary(&$binaryData, &$offsetIndex = 0)
+ {
+ $parsedObject = new static('');
+
+ self::parseIdentifier($binaryData[$offsetIndex], $parsedObject->getType(), $offsetIndex++);
+ $contentLength = self::parseContentLength($binaryData, $offsetIndex);
+ $string = substr($binaryData, $offsetIndex, $contentLength);
+ $offsetIndex += $contentLength;
+
+ $parsedObject->value = $string;
+ $parsedObject->setContentLength($contentLength);
+ return $parsedObject;
+ }
+
+ public static function isValid($string)
+ {
+ $testObject = new static($string);
+ try {
+ $testObject->checkString();
+
+ return true;
+ } catch (Exception $exception) {
+ return false;
+ }
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/AbstractTime.php b/vendor/fgrosse/phpasn1/lib/ASN1/AbstractTime.php
new file mode 100644
index 0000000..9fad505
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/AbstractTime.php
@@ -0,0 +1,78 @@
+<?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 DateInterval;
+use DateTime;
+use DateTimeZone;
+use Exception;
+
+abstract class AbstractTime extends ASNObject
+{
+ /** @var DateTime */
+ protected $value;
+
+ public function __construct($dateTime = null, $dateTimeZone = 'UTC')
+ {
+ if ($dateTime == null || is_string($dateTime)) {
+ $timeZone = new DateTimeZone($dateTimeZone);
+ $dateTimeObject = new DateTime($dateTime, $timeZone);
+ if ($dateTimeObject == false) {
+ $errorMessage = $this->getLastDateTimeErrors();
+ $className = Identifier::getName($this->getType());
+ throw new Exception(sprintf("Could not create %s from date time string '%s': %s", $className, $dateTime, $errorMessage));
+ }
+ $dateTime = $dateTimeObject;
+ } elseif (!$dateTime instanceof DateTime) {
+ throw new Exception('Invalid first argument for some instance of AbstractTime constructor');
+ }
+
+ $this->value = $dateTime;
+ }
+
+ public function getContent()
+ {
+ return $this->value;
+ }
+
+ protected function getLastDateTimeErrors()
+ {
+ $messages = '';
+ $lastErrors = DateTime::getLastErrors();
+ foreach ($lastErrors['errors'] as $errorMessage) {
+ $messages .= "{$errorMessage}, ";
+ }
+
+ return substr($messages, 0, -2);
+ }
+
+ public function __toString()
+ {
+ return $this->value->format("Y-m-d\tH:i:s");
+ }
+
+ protected static function extractTimeZoneData(&$binaryData, &$offsetIndex, DateTime $dateTime)
+ {
+ $sign = $binaryData[$offsetIndex++];
+ $timeOffsetHours = intval(substr($binaryData, $offsetIndex, 2));
+ $timeOffsetMinutes = intval(substr($binaryData, $offsetIndex + 2, 2));
+ $offsetIndex += 4;
+
+ $interval = new DateInterval("PT{$timeOffsetHours}H{$timeOffsetMinutes}M");
+ if ($sign == '+') {
+ $dateTime->sub($interval);
+ } else {
+ $dateTime->add($interval);
+ }
+
+ return $dateTime;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Base128.php b/vendor/fgrosse/phpasn1/lib/ASN1/Base128.php
new file mode 100644
index 0000000..119ee7b
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Base128.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace FG\ASN1;
+
+use FG\Utility\BigInteger;
+use InvalidArgumentException;
+
+/**
+ * A base-128 decoder.
+ */
+class Base128
+{
+ /**
+ * @param int $value
+ *
+ * @return string
+ */
+ public static function encode($value)
+ {
+ $value = BigInteger::create($value);
+ $octets = chr($value->modulus(0x80)->toInteger());
+
+ $value = $value->shiftRight(7);
+ while ($value->compare(0) > 0) {
+ $octets .= chr(0x80 | $value->modulus(0x80)->toInteger());
+ $value = $value->shiftRight(7);
+ }
+
+ return strrev($octets);
+ }
+
+ /**
+ * @param string $octets
+ *
+ * @throws InvalidArgumentException if the given octets represent a malformed base-128 value or the decoded value would exceed the the maximum integer length
+ *
+ * @return int
+ */
+ public static function decode($octets)
+ {
+ $bitsPerOctet = 7;
+ $value = BigInteger::create(0);
+ $i = 0;
+
+ while (true) {
+ if (!isset($octets[$i])) {
+ throw new InvalidArgumentException(sprintf('Malformed base-128 encoded value (0x%s).', strtoupper(bin2hex($octets)) ?: '0'));
+ }
+
+ $octet = ord($octets[$i++]);
+
+ $l1 = $value->shiftLeft($bitsPerOctet);
+ $r1 = $octet & 0x7f;
+ $value = $l1->add($r1);
+
+ if (0 === ($octet & 0x80)) {
+ break;
+ }
+ }
+
+ return (string)$value;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Composite/AttributeTypeAndValue.php b/vendor/fgrosse/phpasn1/lib/ASN1/Composite/AttributeTypeAndValue.php
new file mode 100644
index 0000000..3f4027c
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Composite/AttributeTypeAndValue.php
@@ -0,0 +1,35 @@
+<?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\Composite;
+
+use FG\ASN1\ASNObject;
+use FG\ASN1\Universal\Sequence;
+use FG\ASN1\Universal\ObjectIdentifier;
+
+class AttributeTypeAndValue extends Sequence
+{
+ /**
+ * @param ObjectIdentifier|string $objIdentifier
+ * @param \FG\ASN1\ASNObject $value
+ */
+ public function __construct($objIdentifier, ASNObject $value)
+ {
+ if ($objIdentifier instanceof ObjectIdentifier == false) {
+ $objIdentifier = new ObjectIdentifier($objIdentifier);
+ }
+ parent::__construct($objIdentifier, $value);
+ }
+
+ public function __toString()
+ {
+ return $this->children[0].': '.$this->children[1];
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RDNString.php b/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RDNString.php
new file mode 100644
index 0000000..e95e7ac
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RDNString.php
@@ -0,0 +1,37 @@
+<?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\Composite;
+
+use FG\ASN1\Universal\PrintableString;
+use FG\ASN1\Universal\IA5String;
+use FG\ASN1\Universal\UTF8String;
+
+class RDNString extends RelativeDistinguishedName
+{
+ /**
+ * @param string|\FG\ASN1\Universal\ObjectIdentifier $objectIdentifierString
+ * @param string|\FG\ASN1\ASNObject $value
+ */
+ public function __construct($objectIdentifierString, $value)
+ {
+ if (PrintableString::isValid($value)) {
+ $value = new PrintableString($value);
+ } else {
+ if (IA5String::isValid($value)) {
+ $value = new IA5String($value);
+ } else {
+ $value = new UTF8String($value);
+ }
+ }
+
+ parent::__construct($objectIdentifierString, $value);
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RelativeDistinguishedName.php b/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RelativeDistinguishedName.php
new file mode 100644
index 0000000..4185f41
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RelativeDistinguishedName.php
@@ -0,0 +1,50 @@
+<?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\Composite;
+
+use FG\ASN1\Exception\NotImplementedException;
+use FG\ASN1\ASNObject;
+use FG\ASN1\Universal\Set;
+
+class RelativeDistinguishedName extends Set
+{
+ /**
+ * @param string|\FG\ASN1\Universal\ObjectIdentifier $objIdentifierString
+ * @param \FG\ASN1\ASNObject $value
+ */
+ public function __construct($objIdentifierString, ASNObject $value)
+ {
+ // TODO: This does only support one element in the RelativeDistinguishedName Set but it it is defined as follows:
+ // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
+ parent::__construct(new AttributeTypeAndValue($objIdentifierString, $value));
+ }
+
+ public function getContent()
+ {
+ /** @var \FG\ASN1\ASNObject $firstObject */
+ $firstObject = $this->children[0];
+ return $firstObject->__toString();
+ }
+
+ /**
+ * At the current version this code can not work since the implementation of Construct requires
+ * the class to support a constructor without arguments.
+ *
+ * @deprecated this function is not yet implemented! Feel free to submit a pull request on github
+ * @param string $binaryData
+ * @param int $offsetIndex
+ * @throws NotImplementedException
+ */
+ public static function fromBinary(&$binaryData, &$offsetIndex = 0)
+ {
+ throw new NotImplementedException();
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Construct.php b/vendor/fgrosse/phpasn1/lib/ASN1/Construct.php
new file mode 100644
index 0000000..58f9613
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Construct.php
@@ -0,0 +1,191 @@
+<?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 ArrayAccess;
+use ArrayIterator;
+use Countable;
+use FG\ASN1\Exception\ParserException;
+use Iterator;
+
+abstract class Construct extends ASNObject implements Countable, ArrayAccess, Iterator, Parsable
+{
+ /** @var \FG\ASN1\ASNObject[] */
+ protected $children;
+ private $iteratorPosition;
+
+ /**
+ * @param \FG\ASN1\ASNObject[] $children the variadic type hint is commented due to https://github.com/facebook/hhvm/issues/4858
+ */
+ public function __construct(/* HH_FIXME[4858]: variadic + strict */ ...$children)
+ {
+ $this->children = $children;
+ $this->iteratorPosition = 0;
+ }
+
+ public function getContent()
+ {
+ return $this->children;
+ }
+
+ public function rewind()
+ {
+ $this->iteratorPosition = 0;
+ }
+
+ public function current()
+ {
+ return $this->children[$this->iteratorPosition];
+ }
+
+ public function key()
+ {
+ return $this->iteratorPosition;
+ }
+
+ public function next()
+ {
+ $this->iteratorPosition++;
+ }
+
+ public function valid()
+ {
+ return isset($this->children[$this->iteratorPosition]);
+ }
+
+ public function offsetExists($offset)
+ {
+ return array_key_exists($offset, $this->children);
+ }
+
+ public function offsetGet($offset)
+ {
+ return $this->children[$offset];
+ }
+
+ public function offsetSet($offset, $value)
+ {
+ if ($offset === null) {
+ $offset = count($this->children);
+ }
+
+ $this->children[$offset] = $value;
+ }
+
+ public function offsetUnset($offset)
+ {
+ unset($this->children[$offset]);
+ }
+
+ protected function calculateContentLength()
+ {
+ $length = 0;
+ foreach ($this->children as $component) {
+ $length += $component->getObjectLength();
+ }
+
+ return $length;
+ }
+
+ protected function getEncodedValue()
+ {
+ $result = '';
+ foreach ($this->children as $component) {
+ $result .= $component->getBinary();
+ }
+
+ return $result;
+ }
+
+ public function addChild(ASNObject $child)
+ {
+ $this->children[] = $child;
+ }
+
+ public function addChildren(array $children)
+ {
+ foreach ($children as $child) {
+ $this->addChild($child);
+ }
+ }
+
+ public function __toString()
+ {
+ $nrOfChildren = $this->getNumberOfChildren();
+ $childString = $nrOfChildren == 1 ? 'child' : 'children';
+
+ return "[{$nrOfChildren} {$childString}]";
+ }
+
+ public function getNumberOfChildren()
+ {
+ return count($this->children);
+ }
+
+ /**
+ * @return \FG\ASN1\ASNObject[]
+ */
+ public function getChildren()
+ {
+ return $this->children;
+ }
+
+ /**
+ * @return \FG\ASN1\ASNObject
+ */
+ public function getFirstChild()
+ {
+ return $this->children[0];
+ }
+
+ /**
+ * @param string $binaryData
+ * @param int $offsetIndex
+ *
+ * @throws Exception\ParserException
+ *
+ * @return Construct|static
+ */
+ public static function fromBinary(&$binaryData, &$offsetIndex = 0)
+ {
+ $parsedObject = new static();
+ self::parseIdentifier($binaryData[$offsetIndex], $parsedObject->getType(), $offsetIndex++);
+ $contentLength = self::parseContentLength($binaryData, $offsetIndex);
+ $startIndex = $offsetIndex;
+
+ $children = [];
+ $octetsToRead = $contentLength;
+ while ($octetsToRead > 0) {
+ $newChild = ASNObject::fromBinary($binaryData, $offsetIndex);
+ $octetsToRead -= $newChild->getObjectLength();
+ $children[] = $newChild;
+ }
+
+ if ($octetsToRead !== 0) {
+ throw new ParserException("Sequence length incorrect", $startIndex);
+ }
+
+ $parsedObject->addChildren($children);
+ $parsedObject->setContentLength($contentLength);
+
+ return $parsedObject;
+ }
+
+ public function count($mode = COUNT_NORMAL)
+ {
+ return count($this->children, $mode);
+ }
+
+ public function getIterator()
+ {
+ return new ArrayIterator($this->children);
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Exception/NotImplementedException.php b/vendor/fgrosse/phpasn1/lib/ASN1/Exception/NotImplementedException.php
new file mode 100644
index 0000000..c9f8e82
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Exception/NotImplementedException.php
@@ -0,0 +1,15 @@
+<?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\Exception;
+
+class NotImplementedException extends \Exception
+{
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Exception/ParserException.php b/vendor/fgrosse/phpasn1/lib/ASN1/Exception/ParserException.php
new file mode 100644
index 0000000..4bda4e8
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Exception/ParserException.php
@@ -0,0 +1,29 @@
+<?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\Exception;
+
+class ParserException extends \Exception
+{
+ private $errorMessage;
+ private $offset;
+
+ public function __construct($errorMessage, $offset)
+ {
+ $this->errorMessage = $errorMessage;
+ $this->offset = $offset;
+ parent::__construct("ASN.1 Parser Exception at offset {$this->offset}: {$this->errorMessage}");
+ }
+
+ public function getOffset()
+ {
+ return $this->offset;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php b/vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php
new file mode 100644
index 0000000..b947a95
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php
@@ -0,0 +1,131 @@
+<?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 FG\ASN1\Exception\ParserException;
+
+/**
+ * Class ExplicitlyTaggedObject decorate an inner object with an additional tag that gives information about
+ * its context specific meaning.
+ *
+ * Explanation taken from A Layman's Guide to a Subset of ASN.1, BER, and DER:
+ * >>> An RSA Laboratories Technical Note
+ * >>> Burton S. Kaliski Jr.
+ * >>> Revised November 1, 1993
+ *
+ * [...]
+ * Explicitly tagged types are derived from other types by adding an outer tag to the underlying type.
+ * In effect, explicitly tagged types are structured types consisting of one component, the underlying type.
+ * Explicit tagging is denoted by the ASN.1 keywords [class number] EXPLICIT (see Section 5.2).
+ * [...]
+ *
+ * @see http://luca.ntop.org/Teaching/Appunti/asn1.html
+ */
+class ExplicitlyTaggedObject extends ASNObject
+{
+ /** @var \FG\ASN1\ASNObject[] */
+ private $decoratedObjects;
+ private $tag;
+
+ /**
+ * @param int $tag
+ * @param \FG\ASN1\ASNObject $objects,...
+ */
+ public function __construct($tag, /* HH_FIXME[4858]: variadic + strict */ ...$objects)
+ {
+ $this->tag = $tag;
+ $this->decoratedObjects = $objects;
+ }
+
+ protected function calculateContentLength()
+ {
+ $length = 0;
+ foreach ($this->decoratedObjects as $object) {
+ $length += $object->getObjectLength();
+ }
+
+ return $length;
+ }
+
+ protected function getEncodedValue()
+ {
+ $encoded = '';
+ foreach ($this->decoratedObjects as $object) {
+ $encoded .= $object->getBinary();
+ }
+
+ return $encoded;
+ }
+
+ public function getContent()
+ {
+ return $this->decoratedObjects;
+ }
+
+ public function __toString()
+ {
+ switch ($length = count($this->decoratedObjects)) {
+ case 0:
+ return "Context specific empty object with tag [{$this->tag}]";
+ case 1:
+ $decoratedType = Identifier::getShortName($this->decoratedObjects[0]->getType());
+ return "Context specific $decoratedType with tag [{$this->tag}]";
+ default:
+ return "$length context specific objects with tag [{$this->tag}]";
+ }
+ }
+
+ public function getType()
+ {
+ return ord($this->getIdentifier());
+ }
+
+ public function getIdentifier()
+ {
+ $identifier = Identifier::create(Identifier::CLASS_CONTEXT_SPECIFIC, true, $this->tag);
+
+ return is_int($identifier) ? chr($identifier) : $identifier;
+ }
+
+ public function getTag()
+ {
+ return $this->tag;
+ }
+
+ public static function fromBinary(&$binaryData, &$offsetIndex = 0)
+ {
+ $identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex);
+ $firstIdentifierOctet = ord($identifier);
+ assert(Identifier::isContextSpecificClass($firstIdentifierOctet), 'identifier octet should indicate context specific class');
+ assert(Identifier::isConstructed($firstIdentifierOctet), 'identifier octet should indicate constructed object');
+ $tag = Identifier::getTagNumber($identifier);
+
+ $totalContentLength = self::parseContentLength($binaryData, $offsetIndex);
+ $remainingContentLength = $totalContentLength;
+
+ $offsetIndexOfDecoratedObject = $offsetIndex;
+ $decoratedObjects = [];
+
+ while ($remainingContentLength > 0) {
+ $nextObject = ASNObject::fromBinary($binaryData, $offsetIndex);
+ $remainingContentLength -= $nextObject->getObjectLength();
+ $decoratedObjects[] = $nextObject;
+ }
+
+ if ($remainingContentLength != 0) {
+ throw new ParserException("Context-Specific explicitly tagged object [$tag] starting at offset $offsetIndexOfDecoratedObject specifies a length of $totalContentLength octets but $remainingContentLength remain after parsing the content", $offsetIndexOfDecoratedObject);
+ }
+
+ $parsedObject = new self($tag, ...$decoratedObjects);
+ $parsedObject->setContentLength($totalContentLength);
+ return $parsedObject;
+ }
+}
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;
+ }
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/OID.php b/vendor/fgrosse/phpasn1/lib/ASN1/OID.php
new file mode 100644
index 0000000..d4875c7
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/OID.php
@@ -0,0 +1,199 @@
+<?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;
+
+class OID
+{
+ const RSA_ENCRYPTION = '1.2.840.113549.1.1.1';
+ const MD5_WITH_RSA_ENCRYPTION = '1.2.840.113549.1.1.4';
+ const SHA1_WITH_RSA_SIGNATURE = '1.2.840.113549.1.1.5';
+ const SHA256_WITH_RSA_SIGNATURE = '1.2.840.113549.1.1.11';
+ const PKCS9_EMAIL = '1.2.840.113549.1.9.1';
+ const PKCS9_UNSTRUCTURED_NAME = '1.2.840.113549.1.9.2';
+ const PKCS9_CONTENT_TYPE = '1.2.840.113549.1.9.3';
+ const PKCS9_MESSAGE_DIGEST = '1.2.840.113549.1.9.4';
+ const PKCS9_SIGNING_TIME = '1.2.840.113549.1.9.5';
+ const PKCS9_EXTENSION_REQUEST = '1.2.840.113549.1.9.14';
+
+ // certificate extension identifier
+ const CERT_EXT_SUBJECT_DIRECTORY_ATTR = '2.5.29.9';
+ const CERT_EXT_SUBJECT_KEY_IDENTIFIER = '2.5.29.14';
+ const CERT_EXT_KEY_USAGE = '2.5.29.15';
+ const CERT_EXT_PRIVATE_KEY_USAGE_PERIOD = '2.5.29.16';
+ const CERT_EXT_SUBJECT_ALT_NAME = '2.5.29.17';
+ const CERT_EXT_ISSUER_ALT_NAME = '2.5.29.18';
+ const CERT_EXT_BASIC_CONSTRAINTS = '2.5.29.19';
+ const CERT_EXT_CRL_NUMBER = '2.5.29.20';
+ const CERT_EXT_REASON_CODE = '2.5.29.21';
+ const CERT_EXT_INVALIDITY_DATE = '2.5.29.24';
+ const CERT_EXT_DELTA_CRL_INDICATOR = '2.5.29.27';
+ const CERT_EXT_ISSUING_DIST_POINT = '2.5.29.28';
+ const CERT_EXT_CERT_ISSUER = '2.5.29.29';
+ const CERT_EXT_NAME_CONSTRAINTS = '2.5.29.30';
+ const CERT_EXT_CRL_DISTRIBUTION_POINTS = '2.5.29.31';
+ const CERT_EXT_CERT_POLICIES = '2.5.29.32';
+ const CERT_EXT_AUTHORITY_KEY_IDENTIFIER = '2.5.29.35';
+ const CERT_EXT_EXTENDED_KEY_USAGE = '2.5.29.37';
+
+ // standard certificate files
+ const COMMON_NAME = '2.5.4.3';
+ const SURNAME = '2.5.4.4';
+ const SERIAL_NUMBER = '2.5.4.5';
+ const COUNTRY_NAME = '2.5.4.6';
+ const LOCALITY_NAME = '2.5.4.7';
+ const STATE_OR_PROVINCE_NAME = '2.5.4.8';
+ const STREET_ADDRESS = '2.5.4.9';
+ const ORGANIZATION_NAME = '2.5.4.10';
+ const OU_NAME = '2.5.4.11';
+ const TITLE = '2.5.4.12';
+ const DESCRIPTION = '2.5.4.13';
+ const POSTAL_ADDRESS = '2.5.4.16';
+ const POSTAL_CODE = '2.5.4.17';
+ const AUTHORITY_REVOCATION_LIST = '2.5.4.38';
+
+ const AUTHORITY_INFORMATION_ACCESS = '1.3.6.1.5.5.7.1.1';
+
+ /**
+ * Returns the name of the given object identifier.
+ *
+ * Some OIDs are saved as class constants in this class.
+ * If the wanted oidString is not among them, this method will
+ * query http://oid-info.com for the right name.
+ * This behavior can be suppressed by setting the second method parameter to false.
+ *
+ * @param string $oidString
+ * @param bool $loadFromWeb
+ *
+ * @see self::loadFromWeb($oidString)
+ *
+ * @return string
+ */
+ public static function getName($oidString, $loadFromWeb = true)
+ {
+ switch ($oidString) {
+ case self::RSA_ENCRYPTION:
+ return 'RSA Encryption';
+ case self::MD5_WITH_RSA_ENCRYPTION:
+ return 'MD5 with RSA Encryption';
+ case self::SHA1_WITH_RSA_SIGNATURE:
+ return 'SHA-1 with RSA Signature';
+
+ case self::PKCS9_EMAIL:
+ return 'PKCS #9 Email Address';
+ case self::PKCS9_UNSTRUCTURED_NAME:
+ return 'PKCS #9 Unstructured Name';
+ case self::PKCS9_CONTENT_TYPE:
+ return 'PKCS #9 Content Type';
+ case self::PKCS9_MESSAGE_DIGEST:
+ return 'PKCS #9 Message Digest';
+ case self::PKCS9_SIGNING_TIME:
+ return 'PKCS #9 Signing Time';
+
+ case self::COMMON_NAME:
+ return 'Common Name';
+ case self::SURNAME:
+ return 'Surname';
+ case self::SERIAL_NUMBER:
+ return 'Serial Number';
+ case self::COUNTRY_NAME:
+ return 'Country Name';
+ case self::LOCALITY_NAME:
+ return 'Locality Name';
+ case self::STATE_OR_PROVINCE_NAME:
+ return 'State or Province Name';
+ case self::STREET_ADDRESS:
+ return 'Street Address';
+ case self::ORGANIZATION_NAME:
+ return 'Organization Name';
+ case self::OU_NAME:
+ return 'Organization Unit Name';
+ case self::TITLE:
+ return 'Title';
+ case self::DESCRIPTION:
+ return 'Description';
+ case self::POSTAL_ADDRESS:
+ return 'Postal Address';
+ case self::POSTAL_CODE:
+ return 'Postal Code';
+ case self::AUTHORITY_REVOCATION_LIST:
+ return 'Authority Revocation List';
+
+ case self::CERT_EXT_SUBJECT_DIRECTORY_ATTR:
+ return 'Subject directory attributes';
+ case self::CERT_EXT_SUBJECT_KEY_IDENTIFIER:
+ return 'Subject key identifier';
+ case self::CERT_EXT_KEY_USAGE:
+ return 'Key usage certificate extension';
+ case self::CERT_EXT_PRIVATE_KEY_USAGE_PERIOD:
+ return 'Private key usage';
+ case self::CERT_EXT_SUBJECT_ALT_NAME:
+ return 'Subject alternative name (SAN)';
+ case self::CERT_EXT_ISSUER_ALT_NAME:
+ return 'Issuer alternative name';
+ case self::CERT_EXT_BASIC_CONSTRAINTS:
+ return 'Basic constraints';
+ case self::CERT_EXT_CRL_NUMBER:
+ return 'CRL number';
+ case self::CERT_EXT_REASON_CODE:
+ return 'Reason code';
+ case self::CERT_EXT_INVALIDITY_DATE:
+ return 'Invalidity code';
+ case self::CERT_EXT_DELTA_CRL_INDICATOR:
+ return 'Delta CRL indicator';
+ case self::CERT_EXT_ISSUING_DIST_POINT:
+ return 'Issuing distribution point';
+ case self::CERT_EXT_CERT_ISSUER:
+ return 'Certificate issuer';
+ case self::CERT_EXT_NAME_CONSTRAINTS:
+ return 'Name constraints';
+ case self::CERT_EXT_CRL_DISTRIBUTION_POINTS:
+ return 'CRL distribution points';
+ case self::CERT_EXT_CERT_POLICIES:
+ return 'Certificate policies ';
+ case self::CERT_EXT_AUTHORITY_KEY_IDENTIFIER:
+ return 'Authority key identifier';
+ case self::CERT_EXT_EXTENDED_KEY_USAGE:
+ return 'Extended key usage';
+ case self::AUTHORITY_INFORMATION_ACCESS:
+ return 'Certificate Authority Information Access (AIA)';
+
+ default:
+ if ($loadFromWeb) {
+ return self::loadFromWeb($oidString);
+ } else {
+ return $oidString;
+ }
+ }
+ }
+
+ public static function loadFromWeb($oidString)
+ {
+ $ch = curl_init("http://oid-info.com/get/{$oidString}");
+
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+
+ $contents = curl_exec($ch);
+ curl_close($ch);
+
+ // This pattern needs to be updated as soon as the website layout of oid-info.com changes
+ preg_match_all('#<tt>(.+)\(\d+\)</tt>#si', $contents, $oidName);
+
+ if (empty($oidName[1])) {
+ return "{$oidString} (unknown)";
+ }
+
+ $oidName = ucfirst(strtolower(preg_replace('/([A-Z][a-z])/', ' $1', $oidName[1][0])));
+ $oidName = str_replace('-', ' ', $oidName);
+
+ return "{$oidName} ({$oidString})";
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Parsable.php b/vendor/fgrosse/phpasn1/lib/ASN1/Parsable.php
new file mode 100644
index 0000000..fa66b55
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Parsable.php
@@ -0,0 +1,32 @@
+<?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 FG\ASN1\Exception\ParserException;
+
+/**
+ * The Parsable interface describes classes that can be parsed from their binary DER representation.
+ */
+interface Parsable
+{
+ /**
+ * Parse an instance of this class from its binary DER encoded representation.
+ *
+ * @param string $binaryData
+ * @param int $offsetIndex the offset at which parsing of the $binaryData is started. This parameter ill be modified
+ * to contain the offset index of the next object after this object has been parsed
+ *
+ * @throws ParserException if the given binary data is either invalid or not currently supported
+ *
+ * @return static
+ */
+ public static function fromBinary(&$binaryData, &$offsetIndex = null);
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/TemplateParser.php b/vendor/fgrosse/phpasn1/lib/ASN1/TemplateParser.php
new file mode 100644
index 0000000..90a40b0
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/TemplateParser.php
@@ -0,0 +1,70 @@
+<?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;
+use FG\ASN1\Exception\ParserException;
+use FG\ASN1\Universal\Sequence;
+
+class TemplateParser
+{
+ /**
+ * @param string $data
+ * @param array $template
+ * @return \FG\ASN1\ASNObject|Sequence
+ * @throws ParserException if there was an issue parsing
+ */
+ public function parseBase64($data, array $template)
+ {
+ // TODO test with invalid data
+ return $this->parseBinary(base64_decode($data), $template);
+ }
+
+ /**
+ * @param string $binary
+ * @param array $template
+ * @return \FG\ASN1\ASNObject|Sequence
+ * @throws ParserException if there was an issue parsing
+ */
+ public function parseBinary($binary, array $template)
+ {
+ $parsedObject = ASNObject::fromBinary($binary);
+
+ foreach ($template as $key => $value) {
+ $this->validate($parsedObject, $key, $value);
+ }
+
+ return $parsedObject;
+ }
+
+ private function validate(ASNObject $object, $key, $value)
+ {
+ if (is_array($value)) {
+ $this->assertTypeId($key, $object);
+
+ /* @var Construct $object */
+ foreach ($value as $key => $child) {
+ $this->validate($object->current(), $key, $child);
+ $object->next();
+ }
+ } else {
+ $this->assertTypeId($value, $object);
+ }
+ }
+
+ private function assertTypeId($expectedTypeId, ASNObject $object)
+ {
+ $actualType = $object->getType();
+ if ($expectedTypeId != $actualType) {
+ throw new Exception("Expected type ($expectedTypeId) does not match actual type ($actualType");
+ }
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BMPString.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BMPString.php
new file mode 100644
index 0000000..83ec6a9
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BMPString.php
@@ -0,0 +1,41 @@
+<?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 FG\ASN1\AbstractString;
+use FG\ASN1\Identifier;
+
+class BMPString extends AbstractString
+{
+ /**
+ * Creates a new ASN.1 BMP String.
+ *
+ * BMPString is a subtype of UniversalString that has its own
+ * unique tag and contains only the characters in the
+ * Basic Multilingual Plane (those corresponding to the first
+ * 64K-2 cells, less cells whose encoding is used to address
+ * characters outside the Basic Multilingual Plane) of ISO/IEC 10646-1.
+ *
+ * TODO The encodable characters of this type are not yet checked.
+ *
+ * @param string $string
+ */
+ public function __construct($string)
+ {
+ $this->value = $string;
+ $this->allowAll();
+ }
+
+ public function getType()
+ {
+ return Identifier::BMP_STRING;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BitString.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BitString.php
new file mode 100644
index 0000000..226695c
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BitString.php
@@ -0,0 +1,88 @@
+<?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\ASN1\Exception\ParserException;
+use FG\ASN1\Parsable;
+use FG\ASN1\Identifier;
+
+class BitString extends OctetString implements Parsable
+{
+ private $nrOfUnusedBits;
+
+ /**
+ * Creates a new ASN.1 BitString object.
+ *
+ * @param string|int $value Either the hexadecimal value as a string (spaces are allowed - leading 0x is optional) or a numeric value
+ * @param int $nrOfUnusedBits the number of unused bits in the last octet [optional].
+ *
+ * @throws Exception if the second parameter is no positive numeric value
+ */
+ public function __construct($value, $nrOfUnusedBits = 0)
+ {
+ parent::__construct($value);
+
+ if (!is_numeric($nrOfUnusedBits) || $nrOfUnusedBits < 0) {
+ throw new Exception('BitString: second parameter needs to be a positive number (or zero)!');
+ }
+
+ $this->nrOfUnusedBits = $nrOfUnusedBits;
+ }
+
+ public function getType()
+ {
+ return Identifier::BITSTRING;
+ }
+
+ protected function calculateContentLength()
+ {
+ // add one to the length for the first octet which encodes the number of unused bits in the last octet
+ return parent::calculateContentLength() + 1;
+ }
+
+ protected function getEncodedValue()
+ {
+ // the first octet determines the number of unused bits
+ $nrOfUnusedBitsOctet = chr($this->nrOfUnusedBits);
+ $actualContent = parent::getEncodedValue();
+
+ return $nrOfUnusedBitsOctet.$actualContent;
+ }
+
+ public function getNumberOfUnusedBits()
+ {
+ return $this->nrOfUnusedBits;
+ }
+
+ public static function fromBinary(&$binaryData, &$offsetIndex = 0)
+ {
+ self::parseIdentifier($binaryData[$offsetIndex], Identifier::BITSTRING, $offsetIndex++);
+ $contentLength = self::parseContentLength($binaryData, $offsetIndex, 2);
+
+ $nrOfUnusedBits = ord($binaryData[$offsetIndex]);
+ $value = substr($binaryData, $offsetIndex + 1, $contentLength - 1);
+
+ if ($nrOfUnusedBits > 7 || // no less than 1 used, otherwise non-minimal
+ ($contentLength - 1) == 1 && $nrOfUnusedBits > 0 || // content length only 1, no
+ (ord($value[strlen($value)-1])&((1<<$nrOfUnusedBits)-1)) != 0 // unused bits set
+ ) {
+ throw new ParserException("Can not parse bit string with invalid padding", $offsetIndex);
+ }
+
+ $offsetIndex += $contentLength;
+
+ $parsedObject = new self(bin2hex($value), $nrOfUnusedBits);
+ $parsedObject->setContentLength($contentLength);
+
+ return $parsedObject;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Boolean.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Boolean.php
new file mode 100644
index 0000000..b73c99f
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Boolean.php
@@ -0,0 +1,75 @@
+<?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 FG\ASN1\ASNObject;
+use FG\ASN1\Parsable;
+use FG\ASN1\Identifier;
+use FG\ASN1\Exception\ParserException;
+
+class Boolean extends ASNObject implements Parsable
+{
+ private $value;
+
+ /**
+ * @param bool $value
+ */
+ public function __construct($value)
+ {
+ $this->value = $value;
+ }
+
+ public function getType()
+ {
+ return Identifier::BOOLEAN;
+ }
+
+ protected function calculateContentLength()
+ {
+ return 1;
+ }
+
+ protected function getEncodedValue()
+ {
+ if ($this->value == false) {
+ return chr(0x00);
+ } else {
+ return chr(0xFF);
+ }
+ }
+
+ public function getContent()
+ {
+ if ($this->value == true) {
+ return 'TRUE';
+ } else {
+ return 'FALSE';
+ }
+ }
+
+ public static function fromBinary(&$binaryData, &$offsetIndex = 0)
+ {
+ self::parseIdentifier($binaryData[$offsetIndex], Identifier::BOOLEAN, $offsetIndex++);
+ $contentLength = self::parseContentLength($binaryData, $offsetIndex);
+
+ if ($contentLength != 1) {
+ throw new ParserException("An ASN.1 Boolean should not have a length other than one. Extracted length was {$contentLength}", $offsetIndex);
+ }
+
+ $value = ord($binaryData[$offsetIndex++]);
+ $booleanValue = $value == 0xFF ? true : false;
+
+ $parsedObject = new self($booleanValue);
+ $parsedObject->setContentLength($contentLength);
+
+ return $parsedObject;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/CharacterString.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/CharacterString.php
new file mode 100644
index 0000000..bfc170d
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/CharacterString.php
@@ -0,0 +1,28 @@
+<?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 FG\ASN1\AbstractString;
+use FG\ASN1\Identifier;
+
+class CharacterString extends AbstractString
+{
+ public function __construct($string)
+ {
+ $this->value = $string;
+ $this->allowAll();
+ }
+
+ public function getType()
+ {
+ return Identifier::CHARACTER_STRING;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Enumerated.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Enumerated.php
new file mode 100644
index 0000000..06d04a3
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Enumerated.php
@@ -0,0 +1,21 @@
+<?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 FG\ASN1\Identifier;
+
+class Enumerated extends Integer
+{
+ public function getType()
+ {
+ return Identifier::ENUMERATED;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralString.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralString.php
new file mode 100644
index 0000000..fb0346f
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralString.php
@@ -0,0 +1,34 @@
+<?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 FG\ASN1\AbstractString;
+use FG\ASN1\Identifier;
+
+class GeneralString extends AbstractString
+{
+ /**
+ * Creates a new ASN.1 GeneralString.
+ * TODO The encodable characters of this type are not yet checked.
+ *
+ * @param string $string
+ */
+ public function __construct($string)
+ {
+ $this->value = $string;
+ $this->allowAll();
+ }
+
+ public function getType()
+ {
+ return Identifier::GENERAL_STRING;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralizedTime.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralizedTime.php
new file mode 100644
index 0000000..ca92209
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralizedTime.php
@@ -0,0 +1,134 @@
+<?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 FG\ASN1\AbstractTime;
+use FG\ASN1\Parsable;
+use FG\ASN1\Identifier;
+use FG\ASN1\Exception\ParserException;
+
+/**
+ * This ASN.1 universal type contains date and time information according to ISO 8601.
+ *
+ * The type consists of values representing:
+ * a) a calendar date, as defined in ISO 8601; and
+ * b) a time of day, to any of the precisions defined in ISO 8601, except for the hours value 24 which shall not be used; and
+ * c) the local time differential factor as defined in ISO 8601.
+ *
+ * Decoding of this type will accept the Basic Encoding Rules (BER)
+ * The encoding will comply with the Distinguished Encoding Rules (DER).
+ */
+class GeneralizedTime extends AbstractTime implements Parsable
+{
+ private $microseconds;
+
+ public function __construct($dateTime = null, $dateTimeZone = 'UTC')
+ {
+ parent::__construct($dateTime, $dateTimeZone);
+ $this->microseconds = $this->value->format('u');
+ if ($this->containsFractionalSecondsElement()) {
+ // DER requires us to remove trailing zeros
+ $this->microseconds = preg_replace('/([1-9]+)0+$/', '$1', $this->microseconds);
+ }
+ }
+
+ public function getType()
+ {
+ return Identifier::GENERALIZED_TIME;
+ }
+
+ protected function calculateContentLength()
+ {
+ $contentSize = 15; // YYYYMMDDHHmmSSZ
+
+ if ($this->containsFractionalSecondsElement()) {
+ $contentSize += 1 + strlen($this->microseconds);
+ }
+
+ return $contentSize;
+ }
+
+ public function containsFractionalSecondsElement()
+ {
+ return intval($this->microseconds) > 0;
+ }
+
+ protected function getEncodedValue()
+ {
+ $encodedContent = $this->value->format('YmdHis');
+ if ($this->containsFractionalSecondsElement()) {
+ $encodedContent .= ".{$this->microseconds}";
+ }
+
+ return $encodedContent.'Z';
+ }
+
+ public function __toString()
+ {
+ if ($this->containsFractionalSecondsElement()) {
+ return $this->value->format("Y-m-d\tH:i:s.uP");
+ } else {
+ return $this->value->format("Y-m-d\tH:i:sP");
+ }
+ }
+
+ public static function fromBinary(&$binaryData, &$offsetIndex = 0)
+ {
+ self::parseIdentifier($binaryData[$offsetIndex], Identifier::GENERALIZED_TIME, $offsetIndex++);
+ $lengthOfMinimumTimeString = 14; // YYYYMMDDHHmmSS
+ $contentLength = self::parseContentLength($binaryData, $offsetIndex, $lengthOfMinimumTimeString);
+ $maximumBytesToRead = $contentLength;
+
+ $format = 'YmdGis';
+ $content = substr($binaryData, $offsetIndex, $contentLength);
+ $dateTimeString = substr($content, 0, $lengthOfMinimumTimeString);
+ $offsetIndex += $lengthOfMinimumTimeString;
+ $maximumBytesToRead -= $lengthOfMinimumTimeString;
+
+ if ($contentLength == $lengthOfMinimumTimeString) {
+ $localTimeZone = new \DateTimeZone(date_default_timezone_get());
+ $dateTime = \DateTime::createFromFormat($format, $dateTimeString, $localTimeZone);
+ } else {
+ if ($binaryData[$offsetIndex] == '.') {
+ $maximumBytesToRead--; // account for the '.'
+ $nrOfFractionalSecondElements = 1; // account for the '.'
+
+ while ($maximumBytesToRead > 0
+ && $binaryData[$offsetIndex + $nrOfFractionalSecondElements] != '+'
+ && $binaryData[$offsetIndex + $nrOfFractionalSecondElements] != '-'
+ && $binaryData[$offsetIndex + $nrOfFractionalSecondElements] != 'Z') {
+ $nrOfFractionalSecondElements++;
+ $maximumBytesToRead--;
+ }
+
+ $dateTimeString .= substr($binaryData, $offsetIndex, $nrOfFractionalSecondElements);
+ $offsetIndex += $nrOfFractionalSecondElements;
+ $format .= '.u';
+ }
+
+ $dateTime = \DateTime::createFromFormat($format, $dateTimeString, new \DateTimeZone('UTC'));
+
+ if ($maximumBytesToRead > 0) {
+ if ($binaryData[$offsetIndex] == '+'
+ || $binaryData[$offsetIndex] == '-') {
+ $dateTime = static::extractTimeZoneData($binaryData, $offsetIndex, $dateTime);
+ } elseif ($binaryData[$offsetIndex++] != 'Z') {
+ throw new ParserException('Invalid ISO 8601 Time String', $offsetIndex);
+ }
+ }
+ }
+
+ $parsedObject = new self($dateTime);
+ $parsedObject->setContentLength($contentLength);
+
+ return $parsedObject;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GraphicString.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GraphicString.php
new file mode 100644
index 0000000..4a01d67
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GraphicString.php
@@ -0,0 +1,34 @@
+<?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 FG\ASN1\AbstractString;
+use FG\ASN1\Identifier;
+
+class GraphicString extends AbstractString
+{
+ /**
+ * Creates a new ASN.1 Graphic String.
+ * TODO The encodable characters of this type are not yet checked.
+ *
+ * @param string $string
+ */
+ public function __construct($string)
+ {
+ $this->value = $string;
+ $this->allowAll();
+ }
+
+ public function getType()
+ {
+ return Identifier::GRAPHIC_STRING;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/IA5String.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/IA5String.php
new file mode 100644
index 0000000..33a8067
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/IA5String.php
@@ -0,0 +1,35 @@
+<?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 FG\ASN1\AbstractString;
+use FG\ASN1\Identifier;
+
+/**
+ * The International Alphabet No.5 (IA5) references the encoding of the ASCII characters.
+ *
+ * Each character in the data is encoded as 1 byte.
+ */
+class IA5String extends AbstractString
+{
+ public function __construct($string)
+ {
+ parent::__construct($string);
+ for ($i = 1; $i < 128; $i++) {
+ $this->allowCharacter(chr($i));
+ }
+ }
+
+ public function getType()
+ {
+ return Identifier::IA5_STRING;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Integer.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Integer.php
new file mode 100644
index 0000000..fe3806b
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Integer.php
@@ -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;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NullObject.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NullObject.php
new file mode 100644
index 0000000..b5293e4
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NullObject.php
@@ -0,0 +1,54 @@
+<?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 FG\ASN1\ASNObject;
+use FG\ASN1\Parsable;
+use FG\ASN1\Identifier;
+use FG\ASN1\Exception\ParserException;
+
+class NullObject extends ASNObject implements Parsable
+{
+ public function getType()
+ {
+ return Identifier::NULL;
+ }
+
+ protected function calculateContentLength()
+ {
+ return 0;
+ }
+
+ protected function getEncodedValue()
+ {
+ return null;
+ }
+
+ public function getContent()
+ {
+ return 'NULL';
+ }
+
+ public static function fromBinary(&$binaryData, &$offsetIndex = 0)
+ {
+ self::parseIdentifier($binaryData[$offsetIndex], Identifier::NULL, $offsetIndex++);
+ $contentLength = self::parseContentLength($binaryData, $offsetIndex);
+
+ if ($contentLength != 0) {
+ throw new ParserException("An ASN.1 Null should not have a length other than zero. Extracted length was {$contentLength}", $offsetIndex);
+ }
+
+ $parsedObject = new self();
+ $parsedObject->setContentLength(0);
+
+ return $parsedObject;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NumericString.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NumericString.php
new file mode 100644
index 0000000..13fb7c3
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NumericString.php
@@ -0,0 +1,38 @@
+<?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 FG\ASN1\AbstractString;
+use FG\ASN1\Identifier;
+
+class NumericString extends AbstractString
+{
+ /**
+ * Creates a new ASN.1 NumericString.
+ *
+ * The following characters are permitted:
+ * Digits 0,1, ... 9
+ * SPACE (space)
+ *
+ * @param string $string
+ */
+ public function __construct($string)
+ {
+ $this->value = $string;
+ $this->allowNumbers();
+ $this->allowSpaces();
+ }
+
+ public function getType()
+ {
+ return Identifier::NUMERIC_STRING;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectDescriptor.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectDescriptor.php
new file mode 100644
index 0000000..1c5d349
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectDescriptor.php
@@ -0,0 +1,26 @@
+<?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 FG\ASN1\Identifier;
+
+class ObjectDescriptor extends GraphicString
+{
+ public function __construct($objectDescription)
+ {
+ parent::__construct($objectDescription);
+ }
+
+ public function getType()
+ {
+ return Identifier::OBJECT_DESCRIPTOR;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectIdentifier.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectIdentifier.php
new file mode 100644
index 0000000..150ce9c
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectIdentifier.php
@@ -0,0 +1,138 @@
+<?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\ASN1\Base128;
+use FG\ASN1\OID;
+use FG\ASN1\ASNObject;
+use FG\ASN1\Parsable;
+use FG\ASN1\Identifier;
+use FG\ASN1\Exception\ParserException;
+
+class ObjectIdentifier extends ASNObject implements Parsable
+{
+ protected $subIdentifiers;
+ protected $value;
+
+ public function __construct($value)
+ {
+ $this->subIdentifiers = explode('.', $value);
+ $nrOfSubIdentifiers = count($this->subIdentifiers);
+
+ for ($i = 0; $i < $nrOfSubIdentifiers; $i++) {
+ if (is_numeric($this->subIdentifiers[$i])) {
+ // enforce the integer type
+ $this->subIdentifiers[$i] = intval($this->subIdentifiers[$i]);
+ } else {
+ throw new Exception("[{$value}] is no valid object identifier (sub identifier ".($i + 1).' is not numeric)!');
+ }
+ }
+
+ // Merge the first to arcs of the OID registration tree (per ASN definition!)
+ if ($nrOfSubIdentifiers >= 2) {
+ $this->subIdentifiers[1] = ($this->subIdentifiers[0] * 40) + $this->subIdentifiers[1];
+ unset($this->subIdentifiers[0]);
+ }
+
+ $this->value = $value;
+ }
+
+ public function getContent()
+ {
+ return $this->value;
+ }
+
+ public function getType()
+ {
+ return Identifier::OBJECT_IDENTIFIER;
+ }
+
+ protected function calculateContentLength()
+ {
+ $length = 0;
+ foreach ($this->subIdentifiers as $subIdentifier) {
+ do {
+ $subIdentifier = $subIdentifier >> 7;
+ $length++;
+ } while ($subIdentifier > 0);
+ }
+
+ return $length;
+ }
+
+ protected function getEncodedValue()
+ {
+ $encodedValue = '';
+ foreach ($this->subIdentifiers as $subIdentifier) {
+ $encodedValue .= Base128::encode($subIdentifier);
+ }
+
+ return $encodedValue;
+ }
+
+ public function __toString()
+ {
+ return OID::getName($this->value);
+ }
+
+ public static function fromBinary(&$binaryData, &$offsetIndex = 0)
+ {
+ self::parseIdentifier($binaryData[$offsetIndex], Identifier::OBJECT_IDENTIFIER, $offsetIndex++);
+ $contentLength = self::parseContentLength($binaryData, $offsetIndex, 1);
+
+ $firstOctet = ord($binaryData[$offsetIndex++]);
+ $oidString = floor($firstOctet / 40).'.'.($firstOctet % 40);
+ $oidString .= '.'.self::parseOid($binaryData, $offsetIndex, $contentLength - 1);
+
+ $parsedObject = new self($oidString);
+ $parsedObject->setContentLength($contentLength);
+
+ return $parsedObject;
+ }
+
+ /**
+ * Parses an object identifier except for the first octet, which is parsed
+ * differently. This way relative object identifiers can also be parsed
+ * using this.
+ *
+ * @param $binaryData
+ * @param $offsetIndex
+ * @param $octetsToRead
+ *
+ * @throws ParserException
+ *
+ * @return string
+ */
+ protected static function parseOid(&$binaryData, &$offsetIndex, $octetsToRead)
+ {
+ $oid = '';
+
+ while ($octetsToRead > 0) {
+ $octets = '';
+
+ do {
+ if (0 === $octetsToRead) {
+ throw new ParserException('Malformed ASN.1 Object Identifier', $offsetIndex - 1);
+ }
+
+ $octetsToRead--;
+ $octet = $binaryData[$offsetIndex++];
+ $octets .= $octet;
+ } while (ord($octet) & 0x80);
+
+ $oid .= sprintf('%d.', Base128::decode($octets));
+ }
+
+ // Remove trailing '.'
+ return substr($oid, 0, -1) ?: '';
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/OctetString.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/OctetString.php
new file mode 100644
index 0000000..5d69ae7
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/OctetString.php
@@ -0,0 +1,91 @@
+<?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\ASN1\ASNObject;
+use FG\ASN1\Parsable;
+use FG\ASN1\Identifier;
+
+class OctetString extends ASNObject implements Parsable
+{
+ protected $value;
+
+ public function __construct($value)
+ {
+ if (is_string($value)) {
+ // remove gaps between hex digits
+ $value = preg_replace('/\s|0x/', '', $value);
+ } elseif (is_numeric($value)) {
+ $value = dechex($value);
+ } elseif ($value === null) {
+ return;
+ } else {
+ throw new Exception('OctetString: unrecognized input type!');
+ }
+
+ if (strlen($value) % 2 != 0) {
+ // transform values like 1F2 to 01F2
+ $value = '0'.$value;
+ }
+
+ $this->value = $value;
+ }
+
+ public function getType()
+ {
+ return Identifier::OCTETSTRING;
+ }
+
+ protected function calculateContentLength()
+ {
+ return strlen($this->value) / 2;
+ }
+
+ protected function getEncodedValue()
+ {
+ $value = $this->value;
+ $result = '';
+
+ //Actual content
+ while (strlen($value) >= 2) {
+ // get the hex value byte by byte from the string and and add it to binary result
+ $result .= chr(hexdec(substr($value, 0, 2)));
+ $value = substr($value, 2);
+ }
+
+ return $result;
+ }
+
+ public function getContent()
+ {
+ return strtoupper($this->value);
+ }
+
+ public function getBinaryContent()
+ {
+ return $this->getEncodedValue();
+ }
+
+ public static function fromBinary(&$binaryData, &$offsetIndex = 0)
+ {
+ self::parseIdentifier($binaryData[$offsetIndex], Identifier::OCTETSTRING, $offsetIndex++);
+ $contentLength = self::parseContentLength($binaryData, $offsetIndex);
+
+ $value = substr($binaryData, $offsetIndex, $contentLength);
+ $offsetIndex += $contentLength;
+
+ $parsedObject = new self(bin2hex($value));
+ $parsedObject->setContentLength($contentLength);
+
+ return $parsedObject;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/PrintableString.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/PrintableString.php
new file mode 100644
index 0000000..fe6d4bc
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/PrintableString.php
@@ -0,0 +1,53 @@
+<?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 FG\ASN1\AbstractString;
+use FG\ASN1\Identifier;
+
+class PrintableString extends AbstractString
+{
+ /**
+ * Creates a new ASN.1 PrintableString.
+ *
+ * The ITU-T X.680 Table 8 permits the following characters:
+ * Latin capital letters A,B, ... Z
+ * Latin small letters a,b, ... z
+ * Digits 0,1, ... 9
+ * SPACE (space)
+ * APOSTROPHE '
+ * LEFT PARENTHESIS (
+ * RIGHT PARENTHESIS )
+ * PLUS SIGN +
+ * COMMA ,
+ * HYPHEN-MINUS -
+ * FULL STOP .
+ * SOLIDUS /
+ * COLON :
+ * EQUALS SIGN =
+ * QUESTION MARK ?
+ *
+ * @param string $string
+ */
+ public function __construct($string)
+ {
+ $this->value = $string;
+ $this->allowNumbers();
+ $this->allowAllLetters();
+ $this->allowSpaces();
+ $this->allowCharacters("'", '(', ')', '+', '-', '.', ',', '/', ':', '=', '?');
+ }
+
+ public function getType()
+ {
+ return Identifier::PRINTABLE_STRING;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/RelativeObjectIdentifier.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/RelativeObjectIdentifier.php
new file mode 100644
index 0000000..2aa9643
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/RelativeObjectIdentifier.php
@@ -0,0 +1,57 @@
+<?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\ASN1\Parsable;
+use FG\ASN1\Identifier;
+use FG\ASN1\Exception\ParserException;
+
+class RelativeObjectIdentifier extends ObjectIdentifier implements Parsable
+{
+ public function __construct($subIdentifiers)
+ {
+ $this->value = $subIdentifiers;
+ $this->subIdentifiers = explode('.', $subIdentifiers);
+ $nrOfSubIdentifiers = count($this->subIdentifiers);
+
+ for ($i = 0; $i < $nrOfSubIdentifiers; $i++) {
+ if (is_numeric($this->subIdentifiers[$i])) {
+ // enforce the integer type
+ $this->subIdentifiers[$i] = intval($this->subIdentifiers[$i]);
+ } else {
+ throw new Exception("[{$subIdentifiers}] is no valid object identifier (sub identifier ".($i + 1).' is not numeric)!');
+ }
+ }
+ }
+
+ public function getType()
+ {
+ return Identifier::RELATIVE_OID;
+ }
+
+ public static function fromBinary(&$binaryData, &$offsetIndex = 0)
+ {
+ self::parseIdentifier($binaryData[$offsetIndex], Identifier::RELATIVE_OID, $offsetIndex++);
+ $contentLength = self::parseContentLength($binaryData, $offsetIndex, 1);
+
+ try {
+ $oidString = self::parseOid($binaryData, $offsetIndex, $contentLength);
+ } catch (ParserException $e) {
+ throw new ParserException('Malformed ASN.1 Relative Object Identifier', $e->getOffset());
+ }
+
+ $parsedObject = new self($oidString);
+ $parsedObject->setContentLength($contentLength);
+
+ return $parsedObject;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Sequence.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Sequence.php
new file mode 100644
index 0000000..0397cf1
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Sequence.php
@@ -0,0 +1,23 @@
+<?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 FG\ASN1\Construct;
+use FG\ASN1\Parsable;
+use FG\ASN1\Identifier;
+
+class Sequence extends Construct implements Parsable
+{
+ public function getType()
+ {
+ return Identifier::SEQUENCE;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Set.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Set.php
new file mode 100644
index 0000000..6e6d346
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Set.php
@@ -0,0 +1,21 @@
+<?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 FG\ASN1\Identifier;
+
+class Set extends Sequence
+{
+ public function getType()
+ {
+ return Identifier::SET;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/T61String.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/T61String.php
new file mode 100644
index 0000000..5641864
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/T61String.php
@@ -0,0 +1,36 @@
+<?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 FG\ASN1\AbstractString;
+use FG\ASN1\Identifier;
+
+class T61String extends AbstractString
+{
+ /**
+ * Creates a new ASN.1 T61 String.
+ * TODO The encodable characters of this type are not yet checked.
+ *
+ * @see http://en.wikipedia.org/wiki/ITU_T.61
+ *
+ * @param string $string
+ */
+ public function __construct($string)
+ {
+ $this->value = $string;
+ $this->allowAll();
+ }
+
+ public function getType()
+ {
+ return Identifier::T61_STRING;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTCTime.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTCTime.php
new file mode 100644
index 0000000..c4d303c
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTCTime.php
@@ -0,0 +1,77 @@
+<?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 FG\ASN1\AbstractTime;
+use FG\ASN1\Parsable;
+use FG\ASN1\Identifier;
+use FG\ASN1\Exception\ParserException;
+
+/**
+ * This ASN.1 universal type contains the calendar date and time.
+ *
+ * The precision is one minute or one second and optionally a
+ * local time differential from coordinated universal time.
+ *
+ * Decoding of this type will accept the Basic Encoding Rules (BER)
+ * The encoding will comply with the Distinguished Encoding Rules (DER).
+ */
+class UTCTime extends AbstractTime implements Parsable
+{
+ public function getType()
+ {
+ return Identifier::UTC_TIME;
+ }
+
+ protected function calculateContentLength()
+ {
+ return 13; // Content is a string o the following format: YYMMDDhhmmssZ (13 octets)
+ }
+
+ protected function getEncodedValue()
+ {
+ return $this->value->format('ymdHis').'Z';
+ }
+
+ public static function fromBinary(&$binaryData, &$offsetIndex = 0)
+ {
+ self::parseIdentifier($binaryData[$offsetIndex], Identifier::UTC_TIME, $offsetIndex++);
+ $contentLength = self::parseContentLength($binaryData, $offsetIndex, 11);
+
+ $format = 'ymdGi';
+ $dateTimeString = substr($binaryData, $offsetIndex, 10);
+ $offsetIndex += 10;
+
+ // extract optional seconds part
+ if ($binaryData[$offsetIndex] != 'Z'
+ && $binaryData[$offsetIndex] != '+'
+ && $binaryData[$offsetIndex] != '-') {
+ $dateTimeString .= substr($binaryData, $offsetIndex, 2);
+ $offsetIndex += 2;
+ $format .= 's';
+ }
+
+ $dateTime = \DateTime::createFromFormat($format, $dateTimeString, new \DateTimeZone('UTC'));
+
+ // extract time zone settings
+ if ($binaryData[$offsetIndex] == '+'
+ || $binaryData[$offsetIndex] == '-') {
+ $dateTime = static::extractTimeZoneData($binaryData, $offsetIndex, $dateTime);
+ } elseif ($binaryData[$offsetIndex++] != 'Z') {
+ throw new ParserException('Invalid UTC String', $offsetIndex);
+ }
+
+ $parsedObject = new self($dateTime);
+ $parsedObject->setContentLength($contentLength);
+
+ return $parsedObject;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTF8String.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTF8String.php
new file mode 100644
index 0000000..cba568d
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTF8String.php
@@ -0,0 +1,34 @@
+<?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 FG\ASN1\AbstractString;
+use FG\ASN1\Identifier;
+
+class UTF8String extends AbstractString
+{
+ /**
+ * Creates a new ASN.1 Universal String.
+ * TODO The encodable characters of this type are not yet checked.
+ *
+ * @param string $string
+ */
+ public function __construct($string)
+ {
+ $this->value = $string;
+ $this->allowAll();
+ }
+
+ public function getType()
+ {
+ return Identifier::UTF8_STRING;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UniversalString.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UniversalString.php
new file mode 100644
index 0000000..0c3fe1d
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UniversalString.php
@@ -0,0 +1,36 @@
+<?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 FG\ASN1\AbstractString;
+use FG\ASN1\Identifier;
+
+class UniversalString extends AbstractString
+{
+ /**
+ * Creates a new ASN.1 Universal String.
+ * TODO The encodable characters of this type are not yet checked.
+ *
+ * @see http://en.wikipedia.org/wiki/Universal_Character_Set
+ *
+ * @param string $string
+ */
+ public function __construct($string)
+ {
+ $this->value = $string;
+ $this->allowAll();
+ }
+
+ public function getType()
+ {
+ return Identifier::UNIVERSAL_STRING;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/Universal/VisibleString.php b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/VisibleString.php
new file mode 100644
index 0000000..d9326d3
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/Universal/VisibleString.php
@@ -0,0 +1,34 @@
+<?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 FG\ASN1\AbstractString;
+use FG\ASN1\Identifier;
+
+class VisibleString extends AbstractString
+{
+ /**
+ * Creates a new ASN.1 Visible String.
+ * TODO The encodable characters of this type are not yet checked.
+ *
+ * @param string $string
+ */
+ public function __construct($string)
+ {
+ $this->value = $string;
+ $this->allowAll();
+ }
+
+ public function getType()
+ {
+ return Identifier::VISIBLE_STRING;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/UnknownConstructedObject.php b/vendor/fgrosse/phpasn1/lib/ASN1/UnknownConstructedObject.php
new file mode 100644
index 0000000..b19a07a
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/UnknownConstructedObject.php
@@ -0,0 +1,59 @@
+<?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;
+
+class UnknownConstructedObject extends Construct
+{
+ private $identifier;
+ private $contentLength;
+
+ /**
+ * @param string $binaryData
+ * @param int $offsetIndex
+ *
+ * @throws \FG\ASN1\Exception\ParserException
+ */
+ public function __construct($binaryData, &$offsetIndex)
+ {
+ $this->identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex);
+ $this->contentLength = self::parseContentLength($binaryData, $offsetIndex);
+
+ $children = [];
+ $octetsToRead = $this->contentLength;
+ while ($octetsToRead > 0) {
+ $newChild = ASNObject::fromBinary($binaryData, $offsetIndex);
+ $octetsToRead -= $newChild->getObjectLength();
+ $children[] = $newChild;
+ }
+
+ parent::__construct(...$children);
+ }
+
+ public function getType()
+ {
+ return ord($this->identifier);
+ }
+
+ public function getIdentifier()
+ {
+ return $this->identifier;
+ }
+
+ protected function calculateContentLength()
+ {
+ return $this->contentLength;
+ }
+
+ protected function getEncodedValue()
+ {
+ return '';
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/ASN1/UnknownObject.php b/vendor/fgrosse/phpasn1/lib/ASN1/UnknownObject.php
new file mode 100644
index 0000000..4ac536a
--- /dev/null
+++ b/vendor/fgrosse/phpasn1/lib/ASN1/UnknownObject.php
@@ -0,0 +1,59 @@
+<?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;
+
+class UnknownObject extends ASNObject
+{
+ /** @var string */
+ private $value;
+
+ private $identifier;
+
+ /**
+ * @param string|int $identifier Either the first identifier octet as int or all identifier bytes as a string
+ * @param int $contentLength
+ */
+ public function __construct($identifier, $contentLength)
+ {
+ if (is_int($identifier)) {
+ $identifier = chr($identifier);
+ }
+
+ $this->identifier = $identifier;
+ $this->value = "Unparsable Object ({$contentLength} bytes)";
+ $this->setContentLength($contentLength);
+ }
+
+ public function getContent()
+ {
+ return $this->value;
+ }
+
+ public function getType()
+ {
+ return ord($this->identifier[0]);
+ }
+
+ public function getIdentifier()
+ {
+ return $this->identifier;
+ }
+
+ protected function calculateContentLength()
+ {
+ return $this->getContentLength();
+ }
+
+ protected function getEncodedValue()
+ {
+ return '';
+ }
+}